dev_done() made generic, small generic parse() optimization and cleanups

git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@107 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2007-04-03 14:51:18 +00:00
parent 0733627b2c
commit 8f692614cf
11 changed files with 374 additions and 364 deletions

View File

@@ -2311,7 +2311,9 @@ static inline void scst_thr_data_put(struct scst_thr_data_hdr *data)
}
/**
** Generic parse() support routines
** Generic parse() support routines.
** Done via pointer on functions to avoid unneeded dereferences on
** the fast path.
**/
/* Calculates and returns block shift for the given sector size */
@@ -2319,36 +2321,48 @@ int scst_calc_block_shift(int sector_size);
/* Generic parse() for SBC (disk) devices */
int scst_sbc_generic_parse(struct scst_cmd *cmd,
struct scst_info_cdb *info_cdb, int block_shift);
struct scst_info_cdb *info_cdb,
int (*get_block_shift)(struct scst_cmd *cmd));
/* Generic parse() for MMC (cdrom) devices */
int scst_cdrom_generic_parse(struct scst_cmd *cmd,
struct scst_info_cdb *info_cdb, int block_shift);
struct scst_info_cdb *info_cdb,
int (*get_block_shift)(struct scst_cmd *cmd));
/* Generic parse() for MO disk devices */
int scst_modisk_generic_parse(struct scst_cmd *cmd,
struct scst_info_cdb *info_cdb, int block_shift);
struct scst_info_cdb *info_cdb,
int (*get_block_shift)(struct scst_cmd *cmd));
/* Generic parse() for tape devices */
int scst_tape_generic_parse(struct scst_cmd *cmd,
struct scst_info_cdb *info_cdb, int block_size);
struct scst_info_cdb *info_cdb,
int (*get_block_size)(struct scst_cmd *cmd));
/* Generic parse() functions for other devices */
int scst_null_parse(struct scst_cmd *cmd, struct scst_info_cdb *info_cdb);
static inline int scst_changer_generic_parse(struct scst_cmd *cmd,
struct scst_info_cdb *info_cdb)
{
return scst_null_parse(cmd, info_cdb);
}
static inline int scst_processor_generic_parse(struct scst_cmd *cmd,
struct scst_info_cdb *info_cdb)
{
return scst_null_parse(cmd, info_cdb);
}
static inline int scst_raid_generic_parse(struct scst_cmd *cmd,
struct scst_info_cdb *info_cdb)
{
return scst_null_parse(cmd, info_cdb);
}
/* Generic parse() for changer devices */
int scst_changer_generic_parse(struct scst_cmd *cmd,
struct scst_info_cdb *info_cdb, int nothing);
/* Generic parse() for "processor" devices */
int scst_processor_generic_parse(struct scst_cmd *cmd,
struct scst_info_cdb *info_cdb, int nothing);
/* Generic parse() for RAID devices */
int scst_raid_generic_parse(struct scst_cmd *cmd,
struct scst_info_cdb *info_cdb, int nothing);
/**
** Generic dev_done() support routines.
** Done via pointer on functions to avoid unneeded dereferences on
** the fast path.
**/
/* Generic dev_done() for block devices */
int scst_block_generic_dev_done(struct scst_cmd *cmd,
void (*set_block_shift)(struct scst_cmd *cmd, int block_shift));
/* Generic dev_done() for tape devices */
int scst_tape_generic_dev_done(struct scst_cmd *cmd,
void (*set_block_size)(struct scst_cmd *cmd, int block_size));
#endif /* __SCST_H */

View File

@@ -41,6 +41,8 @@
#define CDROM_REG_TIMEOUT (900 * HZ)
#define CDROM_LONG_TIMEOUT (14000 * HZ)
#define CDROM_DEF_BLOCK_SHIFT 11
struct cdrom_params
{
int block_shift;
@@ -72,7 +74,7 @@ int cdrom_attach(struct scst_device *dev)
unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE];
enum dma_data_direction data_dir;
unsigned char *sbuff;
struct cdrom_params *cdrom;
struct cdrom_params *params;
TRACE_ENTRY();
@@ -83,8 +85,8 @@ int cdrom_attach(struct scst_device *dev)
goto out;
}
cdrom = kzalloc(sizeof(*cdrom), GFP_KERNEL);
if (cdrom == NULL) {
params = kzalloc(sizeof(*params), GFP_KERNEL);
if (params == NULL) {
TRACE(TRACE_OUT_OF_MEM, "%s",
"Unable to allocate struct cdrom_params");
res = -ENOMEM;
@@ -95,7 +97,7 @@ int cdrom_attach(struct scst_device *dev)
if (!buffer) {
TRACE(TRACE_OUT_OF_MEM, "%s", "Memory allocation failure");
res = -ENOMEM;
goto out_free_cdrom;
goto out_free_params;
}
/* Clear any existing UA's and get cdrom capacity (cdrom block size) */
@@ -123,7 +125,7 @@ int cdrom_attach(struct scst_device *dev)
if (!--retries) {
PRINT_ERROR_PR("UA not clear after %d retries",
SCST_DEV_UA_RETRIES);
cdrom->block_shift = 11; /* 2048 bytes */
params->block_shift = CDROM_DEF_BLOCK_SHIFT;
// res = -ENODEV;
goto out_free_buf;
}
@@ -132,13 +134,14 @@ int cdrom_attach(struct scst_device *dev)
int sector_size = ((buffer[4] << 24) | (buffer[5] << 16) |
(buffer[6] << 8) | (buffer[7] << 0));
if (sector_size == 0)
sector_size = 2048;
cdrom->block_shift = scst_calc_block_shift(sector_size);
params->block_shift = CDROM_DEF_BLOCK_SHIFT;
else
params->block_shift = scst_calc_block_shift(sector_size);
TRACE_DBG("Sector size is %i scsi_level %d(SCSI_2 %d)",
sector_size, dev->scsi_dev->scsi_level, SCSI_2);
} else {
TRACE_BUFFER("Sense set", sbuff, SCSI_SENSE_BUFFERSIZE);
cdrom->block_shift = 11; /* 2048 bytes */
params->block_shift = CDROM_DEF_BLOCK_SHIFT;
// res = -ENODEV;
goto out_free_buf;
}
@@ -146,11 +149,11 @@ int cdrom_attach(struct scst_device *dev)
out_free_buf:
kfree(buffer);
out_free_cdrom:
out_free_params:
if (res == 0)
dev->dh_priv = cdrom;
dev->dh_priv = params;
else
kfree(cdrom);
kfree(params);
out:
TRACE_EXIT();
@@ -168,17 +171,24 @@ out:
************************************************************/
void cdrom_detach(struct scst_device *dev)
{
struct cdrom_params *cdrom = (struct cdrom_params *)dev->dh_priv;
struct cdrom_params *params =
(struct cdrom_params *)dev->dh_priv;
TRACE_ENTRY();
kfree(cdrom);
kfree(params);
dev->dh_priv = NULL;
TRACE_EXIT();
return;
}
static int cdrom_get_block_shift(struct scst_cmd *cmd)
{
struct cdrom_params *params = (struct cdrom_params *)cmd->dev->dh_priv;
return params->block_shift;
}
/********************************************************************
* Function: cdrom_parse
*
@@ -193,14 +203,14 @@ void cdrom_detach(struct scst_device *dev)
int cdrom_parse(struct scst_cmd *cmd, struct scst_info_cdb *info_cdb)
{
int res = SCST_CMD_STATE_DEFAULT;
struct cdrom_params *cdrom = (struct cdrom_params *)cmd->dev->dh_priv;
/*
* No need for locks here, since *_detach() can not be
* called, when there are existing commands.
*/
scst_cdrom_generic_parse(cmd, info_cdb, cdrom->block_shift);
scst_cdrom_generic_parse(cmd, info_cdb, cdrom_get_block_shift);
cmd->retries = 1;
@@ -214,6 +224,16 @@ int cdrom_parse(struct scst_cmd *cmd, struct scst_info_cdb *info_cdb)
return res;
}
static void cdrom_set_block_shift(struct scst_cmd *cmd, int block_shift)
{
struct cdrom_params *params = (struct cdrom_params *)cmd->dev->dh_priv;
if (block_shift != 0)
params->block_shift = block_shift;
else
params->block_shift = CDROM_DEF_BLOCK_SHIFT;
return;
}
/********************************************************************
* Function: cdrom_done
*
@@ -227,69 +247,17 @@ int cdrom_parse(struct scst_cmd *cmd, struct scst_info_cdb *info_cdb)
********************************************************************/
int cdrom_done(struct scst_cmd *cmd)
{
int opcode = cmd->cdb[0];
int status = cmd->status;
struct cdrom_params *cdrom;
int res = SCST_CMD_STATE_DEFAULT;
TRACE_ENTRY();
if (unlikely(cmd->sg == NULL))
goto out;
/*
* SCST sets good defaults for cmd->tgt_resp_flags and cmd->resp_data_len
* based on cmd->status and cmd->data_direction, therefore change
* them only if necessary
/*
* No need for locks here, since *_detach() can not be
* called, when there are existing commands.
*/
res = scst_block_generic_dev_done(cmd, cdrom_set_block_shift);
if ((status == SAM_STAT_GOOD) || (status == SAM_STAT_CONDITION_MET)) {
switch (opcode) {
case READ_CAPACITY:
{
/* Always keep track of cdrom capacity */
int buffer_size, sector_size, block_shift;
uint8_t *buffer;
buffer_size = scst_get_buf_first(cmd, &buffer);
if (unlikely(buffer_size <= 0)) {
PRINT_ERROR_PR("%s: Unable to get the buffer",
__FUNCTION__);
scst_set_busy(cmd);
goto out;
}
/*
* No need for locks here, since *_detach() can not be
* called, when there are existing commands.
*/
cdrom = (struct cdrom_params *)cmd->dev->dh_priv;
sector_size =
((buffer[4] << 24) | (buffer[5] << 16) |
(buffer[6] << 8) | (buffer[7] << 0));
scst_put_buf(cmd, buffer);
if (sector_size == 0)
sector_size = 2048;
block_shift = scst_calc_block_shift(sector_size);
/*
* To force the compiler not to optimize it out to keep
* cdrom->block_shift access atomic
*/
barrier();
cdrom->block_shift = block_shift;
break;
}
default:
/* It's all good */
break;
}
}
TRACE_DBG("cmd->tgt_resp_flags=%x, cmd->resp_data_len=%d, "
"res=%d", cmd->tgt_resp_flags, cmd->resp_data_len, res);
out:
TRACE_EXIT();
TRACE_EXIT_RES(res);
return res;
}

View File

@@ -128,7 +128,7 @@ int changer_parse(struct scst_cmd *cmd, struct scst_info_cdb *info_cdb)
{
int res = SCST_CMD_STATE_DEFAULT;
scst_changer_generic_parse(cmd, info_cdb);
scst_changer_generic_parse(cmd, info_cdb, 0);
cmd->retries = 1;

View File

@@ -60,6 +60,8 @@
#define DISK_REG_TIMEOUT (60 * HZ)
#define DISK_LONG_TIMEOUT (3600 * HZ)
#define DISK_DEF_BLOCK_SHIFT 9
struct disk_params
{
int block_shift;
@@ -148,7 +150,7 @@ int disk_attach(struct scst_device *dev)
unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE];
enum dma_data_direction data_dir;
unsigned char *sbuff;
struct disk_params *disk;
struct disk_params *params;
TRACE_ENTRY();
@@ -159,8 +161,8 @@ int disk_attach(struct scst_device *dev)
goto out;
}
disk = kzalloc(sizeof(*disk), GFP_KERNEL);
if (disk == NULL) {
params = kzalloc(sizeof(*params), GFP_KERNEL);
if (params == NULL) {
TRACE(TRACE_OUT_OF_MEM, "%s",
"Unable to allocate struct disk_params");
res = -ENOMEM;
@@ -171,7 +173,7 @@ int disk_attach(struct scst_device *dev)
if (!buffer) {
TRACE(TRACE_OUT_OF_MEM, "%s", "Memory allocation failure");
res = -ENOMEM;
goto out_free_disk;
goto out_free_params;
}
/* Clear any existing UA's and get disk capacity (disk block size) */
@@ -206,7 +208,10 @@ int disk_attach(struct scst_device *dev)
if (res == 0) {
int sector_size = ((buffer[4] << 24) | (buffer[5] << 16) |
(buffer[6] << 8) | (buffer[7] << 0));
disk->block_shift = scst_calc_block_shift(sector_size);
if (sector_size == 0)
params->block_shift = DISK_DEF_BLOCK_SHIFT;
else
params->block_shift = scst_calc_block_shift(sector_size);
} else {
TRACE_BUFFER("Sense set", sbuff, SCSI_SENSE_BUFFERSIZE);
res = -ENODEV;
@@ -216,11 +221,11 @@ int disk_attach(struct scst_device *dev)
out_free_buf:
kfree(buffer);
out_free_disk:
out_free_params:
if (res == 0)
dev->dh_priv = disk;
dev->dh_priv = params;
else
kfree(disk);
kfree(params);
out:
TRACE_EXIT_RES(res);
@@ -238,17 +243,24 @@ out:
************************************************************/
void disk_detach(struct scst_device *dev)
{
struct disk_params *disk = (struct disk_params *)dev->dh_priv;
struct disk_params *params =
(struct disk_params *)dev->dh_priv;
TRACE_ENTRY();
kfree(disk);
kfree(params);
dev->dh_priv = NULL;
TRACE_EXIT();
return;
}
static int disk_get_block_shift(struct scst_cmd *cmd)
{
struct disk_params *params = (struct disk_params *)cmd->dev->dh_priv;
return params->block_shift;
}
/********************************************************************
* Function: disk_parse
*
@@ -262,7 +274,6 @@ void disk_detach(struct scst_device *dev)
********************************************************************/
int disk_parse(struct scst_cmd *cmd, struct scst_info_cdb *info_cdb)
{
struct disk_params *disk = (struct disk_params *)cmd->dev->dh_priv;
int res = SCST_CMD_STATE_DEFAULT;
/*
@@ -270,7 +281,7 @@ int disk_parse(struct scst_cmd *cmd, struct scst_info_cdb *info_cdb)
* called, when there are existing commands.
*/
scst_sbc_generic_parse(cmd, info_cdb, disk->block_shift);
scst_sbc_generic_parse(cmd, info_cdb, disk_get_block_shift);
cmd->retries = 1;
@@ -285,6 +296,16 @@ int disk_parse(struct scst_cmd *cmd, struct scst_info_cdb *info_cdb)
return res;
}
static void disk_set_block_shift(struct scst_cmd *cmd, int block_shift)
{
struct disk_params *params = (struct disk_params *)cmd->dev->dh_priv;
if (block_shift != 0)
params->block_shift = block_shift;
else
params->block_shift = DISK_DEF_BLOCK_SHIFT;
return;
}
/********************************************************************
* Function: disk_done
*
@@ -298,66 +319,16 @@ int disk_parse(struct scst_cmd *cmd, struct scst_info_cdb *info_cdb)
********************************************************************/
int disk_done(struct scst_cmd *cmd)
{
int opcode = cmd->cdb[0];
int status = cmd->status;
struct disk_params *disk;
int res = SCST_CMD_STATE_DEFAULT;
TRACE_ENTRY();
if (unlikely(cmd->sg == NULL))
goto out;
/*
* SCST sets good defaults for cmd->tgt_resp_flags and cmd->resp_data_len
* based on cmd->status and cmd->data_direction, therefore change
* them only if necessary
/*
* No need for locks here, since *_detach() can not be
* called, when there are existing commands.
*/
res = scst_block_generic_dev_done(cmd, disk_set_block_shift);
if ((status == SAM_STAT_GOOD) || (status == SAM_STAT_CONDITION_MET)) {
switch (opcode) {
case READ_CAPACITY:
{
/* Always keep track of disk capacity */
int buffer_size, sector_size, block_shift;
uint8_t *buffer;
buffer_size = scst_get_buf_first(cmd, &buffer);
if (unlikely(buffer_size <= 0)) {
PRINT_ERROR_PR("%s: Unable to get the buffer",
__FUNCTION__);
scst_set_busy(cmd);
goto out;
}
/*
* No need for locks here, since *_detach() can not be
* called, when there are existing commands.
*/
disk = (struct disk_params *)cmd->dev->dh_priv;
sector_size =
((buffer[4] << 24) | (buffer[5] << 16) |
(buffer[6] << 8) | (buffer[7] << 0));
scst_put_buf(cmd, buffer);
block_shift = scst_calc_block_shift(sector_size);
/*
* To force the compiler not to optimize it out to keep
* disk->block_shift access atomic
*/
barrier();
disk->block_shift = block_shift;
break;
}
default:
/* It's all good */
break;
}
}
TRACE_DBG("cmd->tgt_resp_flags=%x, cmd->resp_data_len=%d, "
"res=%d", cmd->tgt_resp_flags, cmd->resp_data_len, res);
out:
TRACE_EXIT_RES(res);
return res;
}

View File

@@ -59,8 +59,8 @@
#define MODISK_SMALL_TIMEOUT (3 * HZ)
#define MODISK_REG_TIMEOUT (900 * HZ)
#define MODISK_LONG_TIMEOUT (14000 * HZ)
#define MODISK_BLOCK_SHIFT 10
#define MODISK_SECTOR_SIZE (1 << MODISK_BLOCK_SHIFT)
#define MODISK_DEF_BLOCK_SHIFT 10
struct modisk_params
{
@@ -150,7 +150,7 @@ int modisk_attach(struct scst_device *dev)
unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE];
enum dma_data_direction data_dir;
unsigned char *sbuff;
struct modisk_params *modisk;
struct modisk_params *params;
TRACE_ENTRY();
@@ -161,14 +161,14 @@ int modisk_attach(struct scst_device *dev)
goto out;
}
modisk = kzalloc(sizeof(*modisk), GFP_KERNEL);
if (modisk == NULL) {
params = kzalloc(sizeof(*params), GFP_KERNEL);
if (params == NULL) {
TRACE(TRACE_OUT_OF_MEM, "%s",
"Unable to allocate struct modisk_params");
res = -ENOMEM;
goto out;
}
modisk->block_shift = MODISK_BLOCK_SHIFT;
params->block_shift = MODISK_DEF_BLOCK_SHIFT;
/*
* If the device is offline, don't try to read capacity or any
@@ -178,14 +178,14 @@ int modisk_attach(struct scst_device *dev)
{
TRACE_DBG("%s", "Device is offline");
res = -ENODEV;
goto out_free_modisk;
goto out_free_params;
}
buffer = kzalloc(buffer_size, GFP_KERNEL);
if (!buffer) {
TRACE(TRACE_OUT_OF_MEM, "%s", "Memory allocation failure");
res = -ENOMEM;
goto out_free_modisk;
goto out_free_params;
}
/* Clear any existing UA's and get modisk capacity (modisk block size) */
@@ -220,8 +220,9 @@ int modisk_attach(struct scst_device *dev)
int sector_size = ((buffer[4] << 24) | (buffer[5] << 16) |
(buffer[6] << 8) | (buffer[7] << 0));
if (sector_size == 0)
sector_size = MODISK_SECTOR_SIZE;
modisk->block_shift = scst_calc_block_shift(sector_size);
params->block_shift = MODISK_DEF_BLOCK_SHIFT;
else
params->block_shift = scst_calc_block_shift(sector_size);
TRACE_DBG("Sector size is %i scsi_level %d(SCSI_2 %d)",
sector_size, dev->scsi_dev->scsi_level, SCSI_2);
} else {
@@ -235,11 +236,11 @@ int modisk_attach(struct scst_device *dev)
out_free_buf:
kfree(buffer);
out_free_modisk:
out_free_params:
if (res == 0)
dev->dh_priv = modisk;
dev->dh_priv = params;
else
kfree(modisk);
kfree(params);
out:
TRACE_EXIT_RES(res);
@@ -257,17 +258,24 @@ out:
************************************************************/
void modisk_detach(struct scst_device *dev)
{
struct modisk_params *modisk = (struct modisk_params *)dev->dh_priv;
struct modisk_params *params =
(struct modisk_params *)dev->dh_priv;
TRACE_ENTRY();
kfree(modisk);
kfree(params);
dev->dh_priv = NULL;
TRACE_EXIT();
return;
}
static int modisk_get_block_shift(struct scst_cmd *cmd)
{
struct modisk_params *params = (struct modisk_params *)cmd->dev->dh_priv;
return params->block_shift;
}
/********************************************************************
* Function: modisk_parse
*
@@ -282,14 +290,13 @@ void modisk_detach(struct scst_device *dev)
int modisk_parse(struct scst_cmd *cmd, struct scst_info_cdb *info_cdb)
{
int res = SCST_CMD_STATE_DEFAULT;
struct modisk_params *modisk = (struct modisk_params*)cmd->dev->dh_priv;
/*
* No need for locks here, since *_detach() can not be
* called, when there are existing commands.
*/
scst_modisk_generic_parse(cmd, info_cdb, modisk->block_shift);
scst_modisk_generic_parse(cmd, info_cdb, modisk_get_block_shift);
cmd->retries = 1;
@@ -303,6 +310,16 @@ int modisk_parse(struct scst_cmd *cmd, struct scst_info_cdb *info_cdb)
return res;
}
static void modisk_set_block_shift(struct scst_cmd *cmd, int block_shift)
{
struct modisk_params *params = (struct modisk_params *)cmd->dev->dh_priv;
if (block_shift != 0)
params->block_shift = block_shift;
else
params->block_shift = MODISK_DEF_BLOCK_SHIFT;
return;
}
/********************************************************************
* Function: modisk_done
*
@@ -316,68 +333,16 @@ int modisk_parse(struct scst_cmd *cmd, struct scst_info_cdb *info_cdb)
********************************************************************/
int modisk_done(struct scst_cmd *cmd)
{
int opcode = cmd->cdb[0];
int status = cmd->status;
struct modisk_params *modisk;
int res = SCST_CMD_STATE_DEFAULT;
int res;
TRACE_ENTRY();
if (unlikely(cmd->sg == NULL))
goto out;
/*
* SCST sets good defaults for cmd->tgt_resp_flags and cmd->resp_data_len
* based on cmd->status and cmd->data_direction, therefore change
* them only if necessary
/*
* No need for locks here, since *_detach() can not be
* called, when there are existing commands.
*/
res = scst_block_generic_dev_done(cmd, modisk_set_block_shift);
if ((status == SAM_STAT_GOOD) || (status == SAM_STAT_CONDITION_MET)) {
switch (opcode) {
case READ_CAPACITY:
{
/* Always keep track of modisk capacity */
int buffer_size, sector_size, block_shift;
uint8_t *buffer;
buffer_size = scst_get_buf_first(cmd, &buffer);
if (unlikely(buffer_size <= 0)) {
PRINT_ERROR_PR("%s: Unable to get the buffer",
__FUNCTION__);
scst_set_busy(cmd);
goto out;
}
/*
* No need for locks here, since *_detach() can not be
* called, when there are existing commands.
*/
modisk = (struct modisk_params *)cmd->dev->dh_priv;
sector_size =
((buffer[4] << 24) | (buffer[5] << 16) |
(buffer[6] << 8) | (buffer[7] << 0));
scst_put_buf(cmd, buffer);
if (!sector_size)
sector_size = MODISK_SECTOR_SIZE;
block_shift = scst_calc_block_shift(sector_size);
/*
* To force the compiler not to optimize it out to keep
* cdrom->block_shift access atomic
*/
barrier();
modisk->block_shift = block_shift;
break;
}
default:
/* It's all good */
break;
}
}
TRACE_DBG("cmd->tgt_resp_flags=%x, cmd->resp_data_len=%d, "
"res=%d", cmd->tgt_resp_flags, cmd->resp_data_len, res);
out:
TRACE_EXIT_RES(res);
return res;
}

View File

@@ -128,7 +128,7 @@ int processor_parse(struct scst_cmd *cmd, struct scst_info_cdb *info_cdb)
{
int res = SCST_CMD_STATE_DEFAULT;
scst_processor_generic_parse(cmd, info_cdb);
scst_processor_generic_parse(cmd, info_cdb, 0);
cmd->retries = 1;

View File

@@ -128,7 +128,7 @@ int raid_parse(struct scst_cmd *cmd, struct scst_info_cdb *info_cdb)
{
int res = SCST_CMD_STATE_DEFAULT;
scst_raid_generic_parse(cmd, info_cdb);
scst_raid_generic_parse(cmd, info_cdb, 0);
cmd->retries = 1;

View File

@@ -62,16 +62,13 @@
#define TAPE_REG_TIMEOUT (900 * HZ)
#define TAPE_LONG_TIMEOUT (14000 * HZ)
#define TAPE_DEF_BLOCK_SIZE 512
/* The fixed bit in READ/WRITE/VERIFY */
#define SILI_BIT 2
struct tape_params
{
spinlock_t tp_lock;
uint8_t density;
uint8_t mode;
uint8_t speed;
uint8_t medium_type;
int block_size;
};
@@ -155,7 +152,7 @@ int tape_attach(struct scst_device *dev)
struct scsi_mode_data data;
const int buffer_size = 512;
uint8_t *buffer = NULL;
struct tape_params *tape;
struct tape_params *params;
TRACE_ENTRY();
@@ -166,14 +163,13 @@ int tape_attach(struct scst_device *dev)
goto out;
}
tape = kzalloc(sizeof(*tape), GFP_KERNEL);
if (tape == NULL) {
params = kzalloc(sizeof(*params), GFP_KERNEL);
if (params == NULL) {
TRACE(TRACE_OUT_OF_MEM, "%s",
"Unable to allocate struct tape_params");
res = -ENOMEM;
goto out;
}
spin_lock_init(&tape->tp_lock);
buffer = kmalloc(buffer_size, GFP_KERNEL);
if (!buffer) {
@@ -205,21 +201,21 @@ int tape_attach(struct scst_device *dev)
TRACE_DBG("MODE_SENSE done: %x", res);
if (res == 0) {
int medium_type, mode, speed, density;
if (buffer[3] == 8) {
tape->block_size = ((buffer[9] << 16) |
params->block_size = ((buffer[9] << 16) |
(buffer[10] << 8) |
(buffer[11] << 0));
} else {
tape->block_size = 512;
params->block_size = TAPE_DEF_BLOCK_SIZE;
}
tape->medium_type = buffer[1];
tape->mode = (buffer[2] & 0x70) >> 4;
tape->speed = buffer[2] & 0x0f;
tape->density = buffer[4];
medium_type = buffer[1];
mode = (buffer[2] & 0x70) >> 4;
speed = buffer[2] & 0x0f;
density = buffer[4];
TRACE_DBG("Tape: lun %d. bs %d. type 0x%02x mode 0x%02x "
"speed 0x%02x dens 0x%02x", dev->scsi_dev->lun,
tape->block_size, tape->medium_type,
tape->mode, tape->speed, tape->density);
params->block_size, medium_type, mode, speed, density);
} else {
res = -ENODEV;
goto out_free_buf;
@@ -230,9 +226,9 @@ out_free_buf:
out_free_req:
if (res == 0)
dev->dh_priv = tape;
dev->dh_priv = params;
else
kfree(tape);
kfree(params);
out:
TRACE_EXIT_RES(res);
@@ -250,17 +246,24 @@ out:
************************************************************/
void tape_detach(struct scst_device *dev)
{
struct tape_params *tape = (struct tape_params *)dev->dh_priv;
struct tape_params *params =
(struct tape_params *)dev->dh_priv;
TRACE_ENTRY();
kfree(tape);
kfree(params);
dev->dh_priv = NULL;
TRACE_EXIT();
return;
}
static int tape_get_block_size(struct scst_cmd *cmd)
{
struct tape_params *params = (struct tape_params *)cmd->dev->dh_priv;
return params->block_size;
}
/********************************************************************
* Function: tape_parse
*
@@ -275,14 +278,13 @@ void tape_detach(struct scst_device *dev)
int tape_parse(struct scst_cmd *cmd, struct scst_info_cdb *info_cdb)
{
int res = SCST_CMD_STATE_DEFAULT;
struct tape_params *tape = (struct tape_params*)cmd->dev->dh_priv;
/*
* No need for locks here, since *_detach() can not be called,
* when there are existing commands.
*/
scst_tape_generic_parse(cmd, info_cdb, tape->block_size);
scst_tape_generic_parse(cmd, info_cdb, tape_get_block_size);
cmd->retries = 1;
@@ -296,6 +298,13 @@ int tape_parse(struct scst_cmd *cmd, struct scst_info_cdb *info_cdb)
return res;
}
static void tape_set_block_size(struct scst_cmd *cmd, int block_size)
{
struct tape_params *params = (struct tape_params *)cmd->dev->dh_priv;
params->block_size = block_size;
return;
}
/********************************************************************
* Function: tape_done
*
@@ -311,94 +320,21 @@ int tape_done(struct scst_cmd *cmd)
{
int opcode = cmd->cdb[0];
int status = cmd->status;
struct tape_params *tape;
int res = SCST_CMD_STATE_DEFAULT;
TRACE_ENTRY();
if (unlikely(cmd->sg == NULL))
goto out;
/*
* SCST sets good defaults for cmd->tgt_resp_flags and cmd->resp_data_len
* based on cmd->status and cmd->data_direction, therefore change
* them only if necessary
/*
* No need for locks here, since *_detach() can not be called, when
* there are existing commands.
*/
if ((status == SAM_STAT_GOOD) || (status == SAM_STAT_CONDITION_MET)) {
int buffer_size;
uint8_t *buffer = NULL;
switch (opcode) {
case MODE_SENSE:
case MODE_SELECT:
buffer_size = scst_get_buf_first(cmd, &buffer);
if (unlikely(buffer_size <= 0)) {
PRINT_ERROR_PR("%s: Unable to get the buffer",
__FUNCTION__);
scst_set_busy(cmd);
goto out;
}
break;
}
switch (opcode) {
case MODE_SENSE:
TRACE_DBG("%s", "MODE_SENSE");
if ((cmd->cdb[2] & 0xC0) == 0) {
/*
* No need for locks here, since *_detach()
* can not be called, when there are
* existing commands.
*/
tape = (struct tape_params *)cmd->dev->dh_priv;
spin_lock_bh(&tape->tp_lock);
if (buffer[3] == 8) {
tape->block_size = (buffer[9] << 16) |
(buffer[10] << 8) | buffer[11];
}
tape->medium_type = buffer[1];
tape->mode = (buffer[2] & 0x70) >> 4;
tape->speed = buffer[2] & 0x0f;
tape->density = buffer[4];
spin_unlock_bh(&tape->tp_lock);
}
break;
case MODE_SELECT:
TRACE_DBG("%s", "MODE_SELECT");
/*
* No need for locks here, since *_detach() can not be
* called, when there are existing commands.
*/
tape = (struct tape_params *)cmd->dev->dh_priv;
spin_lock_bh(&tape->tp_lock);
if (buffer[3] == 8) {
tape->block_size =
(buffer[9] << 16) | (buffer[10] << 8) |
(buffer[11]);
}
tape->medium_type = buffer[1];
tape->mode = (buffer[2] & 0x70) >> 4;
tape->speed = buffer[2] & 0x0f;
if (buffer[4] != 0x7f)
tape->density = buffer[4];
spin_unlock_bh(&tape->tp_lock);
break;
default:
/* It's all good */
break;
}
switch (opcode) {
case MODE_SENSE:
case MODE_SELECT:
scst_put_buf(cmd, buffer);
break;
}
}
else if ((status == SAM_STAT_CHECK_CONDITION) &&
res = scst_tape_generic_dev_done(cmd, tape_set_block_size);
} else if ((status == SAM_STAT_CHECK_CONDITION) &&
SCST_SENSE_VALID(cmd->sense_buffer))
{
struct tape_params *params;
TRACE_DBG("%s", "Extended sense");
if (opcode == READ_6 && !(cmd->cdb[1] & SILI_BIT) &&
(cmd->sense_buffer[2] & 0xe0)) { /* EOF, EOM, or ILI */
@@ -428,8 +364,8 @@ int tape_done(struct scst_cmd *cmd)
* *_detach() can not be called, when
* there are existing commands.
*/
tape = (struct tape_params *)cmd->dev->dh_priv;
resp_data_len *= tape->block_size;
params = (struct tape_params *)cmd->dev->dh_priv;
resp_data_len *= params->block_size;
}
scst_set_resp_data_len(cmd, resp_data_len);
}
@@ -439,7 +375,6 @@ int tape_done(struct scst_cmd *cmd)
TRACE_DBG("cmd->tgt_resp_flags=%x, cmd->resp_data_len=%d, "
"res=%d", cmd->tgt_resp_flags, cmd->resp_data_len, res);
out:
TRACE_EXIT_RES(res);
return res;
}

View File

@@ -818,6 +818,13 @@ out:
return SCST_EXEC_COMPLETED;
}
static int vdisk_get_block_shift(struct scst_cmd *cmd)
{
struct scst_vdisk_dev *virt_dev =
(struct scst_vdisk_dev *)cmd->dev->dh_priv;
return virt_dev->block_shift;
}
/********************************************************************
* Function: vdisk_parse
*
@@ -832,10 +839,7 @@ out:
static int vdisk_parse(struct scst_cmd *cmd,
struct scst_info_cdb *info_cdb)
{
struct scst_vdisk_dev *virt_dev =
(struct scst_vdisk_dev *)cmd->dev->dh_priv;
scst_sbc_generic_parse(cmd, info_cdb, virt_dev->block_shift);
scst_sbc_generic_parse(cmd, info_cdb, vdisk_get_block_shift);
return SCST_CMD_STATE_DEFAULT;
}
@@ -853,10 +857,7 @@ static int vdisk_parse(struct scst_cmd *cmd,
static int vcdrom_parse(struct scst_cmd *cmd,
struct scst_info_cdb *info_cdb)
{
struct scst_vdisk_dev *virt_dev =
(struct scst_vdisk_dev *)cmd->dev->dh_priv;
scst_cdrom_generic_parse(cmd, info_cdb, virt_dev->block_shift);
scst_cdrom_generic_parse(cmd, info_cdb, vdisk_get_block_shift);
return SCST_CMD_STATE_DEFAULT;
}

View File

@@ -96,7 +96,7 @@ LIST_HEAD(scst_sess_mgmt_list);
DECLARE_WAIT_QUEUE_HEAD(scst_dev_cmd_waitQ);
DECLARE_MUTEX(scst_suspend_mutex);;
DECLARE_MUTEX(scst_suspend_mutex);
LIST_HEAD(scst_cmd_lists_list); /* protected by scst_suspend_mutex */
static int scst_threads;
@@ -1482,7 +1482,13 @@ EXPORT_SYMBOL(scst_sbc_generic_parse);
EXPORT_SYMBOL(scst_cdrom_generic_parse);
EXPORT_SYMBOL(scst_modisk_generic_parse);
EXPORT_SYMBOL(scst_tape_generic_parse);
EXPORT_SYMBOL(scst_null_parse);
EXPORT_SYMBOL(scst_changer_generic_parse);
EXPORT_SYMBOL(scst_processor_generic_parse);
EXPORT_SYMBOL(scst_raid_generic_parse);
/* Generic dev_done() routines */
EXPORT_SYMBOL(scst_block_generic_dev_done);
EXPORT_SYMBOL(scst_tape_generic_dev_done);
/*
* Other Commands

View File

@@ -1854,7 +1854,8 @@ int scst_calc_block_shift(int sector_size)
}
int scst_sbc_generic_parse(struct scst_cmd *cmd,
struct scst_info_cdb *info_cdb, int block_shift)
struct scst_info_cdb *info_cdb,
int (*get_block_shift)(struct scst_cmd *cmd))
{
int res = 0;
@@ -1886,7 +1887,7 @@ int scst_sbc_generic_parse(struct scst_cmd *cmd,
case VERIFY_16:
if ((cmd->cdb[1] & BYTCHK) == 0) {
cmd->data_len =
info_cdb->transfer_len << block_shift;
info_cdb->transfer_len << get_block_shift(cmd);
cmd->bufflen = 0;
cmd->data_direction = SCST_DATA_NONE;
info_cdb->flags &= ~SCST_TRANSFER_LEN_TYPE_FIXED;
@@ -1903,7 +1904,7 @@ int scst_sbc_generic_parse(struct scst_cmd *cmd,
* No need for locks here, since *_detach() can not be
* called, when there are existing commands.
*/
cmd->bufflen = info_cdb->transfer_len << block_shift;
cmd->bufflen = info_cdb->transfer_len << get_block_shift(cmd);
}
TRACE_DBG("res %d, bufflen %zd, data_len %zd, direct %d",
@@ -1914,7 +1915,8 @@ int scst_sbc_generic_parse(struct scst_cmd *cmd,
}
int scst_cdrom_generic_parse(struct scst_cmd *cmd,
struct scst_info_cdb *info_cdb, int block_shift)
struct scst_info_cdb *info_cdb,
int (*get_block_shift)(struct scst_cmd *cmd))
{
int res = 0;
@@ -1952,7 +1954,7 @@ int scst_cdrom_generic_parse(struct scst_cmd *cmd,
case VERIFY_16:
if ((cmd->cdb[1] & BYTCHK) == 0) {
cmd->data_len =
info_cdb->transfer_len << block_shift;
info_cdb->transfer_len << get_block_shift(cmd);
cmd->bufflen = 0;
cmd->data_direction = SCST_DATA_NONE;
info_cdb->flags &= ~SCST_TRANSFER_LEN_TYPE_FIXED;
@@ -1964,7 +1966,7 @@ int scst_cdrom_generic_parse(struct scst_cmd *cmd,
}
if (info_cdb->flags & SCST_TRANSFER_LEN_TYPE_FIXED)
cmd->bufflen = info_cdb->transfer_len << block_shift;
cmd->bufflen = info_cdb->transfer_len << get_block_shift(cmd);
TRACE_DBG("res %d bufflen %zd direct %d",
res, cmd->bufflen, cmd->data_direction);
@@ -1974,7 +1976,8 @@ int scst_cdrom_generic_parse(struct scst_cmd *cmd,
}
int scst_modisk_generic_parse(struct scst_cmd *cmd,
struct scst_info_cdb *info_cdb, int block_shift)
struct scst_info_cdb *info_cdb,
int (*get_block_shift)(struct scst_cmd *cmd))
{
int res = 0;
@@ -2012,7 +2015,7 @@ int scst_modisk_generic_parse(struct scst_cmd *cmd,
case VERIFY_16:
if ((cmd->cdb[1] & BYTCHK) == 0) {
cmd->data_len =
info_cdb->transfer_len << block_shift;
info_cdb->transfer_len << get_block_shift(cmd);
cmd->bufflen = 0;
cmd->data_direction = SCST_DATA_NONE;
info_cdb->flags &= ~SCST_TRANSFER_LEN_TYPE_FIXED;
@@ -2024,7 +2027,7 @@ int scst_modisk_generic_parse(struct scst_cmd *cmd,
}
if (info_cdb->flags & SCST_TRANSFER_LEN_TYPE_FIXED)
cmd->bufflen = info_cdb->transfer_len << block_shift;;
cmd->bufflen = info_cdb->transfer_len << get_block_shift(cmd);
TRACE_DBG("res %d bufflen %zd direct %d",
res, cmd->bufflen, cmd->data_direction);
@@ -2034,7 +2037,8 @@ int scst_modisk_generic_parse(struct scst_cmd *cmd,
}
int scst_tape_generic_parse(struct scst_cmd *cmd,
struct scst_info_cdb *info_cdb, int block_size)
struct scst_info_cdb *info_cdb,
int (*get_block_size)(struct scst_cmd *cmd))
{
int res = 0;
@@ -2065,13 +2069,13 @@ int scst_tape_generic_parse(struct scst_cmd *cmd,
}
if (info_cdb->flags & SCST_TRANSFER_LEN_TYPE_FIXED & cmd->cdb[1])
cmd->bufflen = info_cdb->transfer_len * block_size;
cmd->bufflen = info_cdb->transfer_len * get_block_size(cmd);
TRACE_EXIT_RES(res);
return res;
}
int scst_null_parse(struct scst_cmd *cmd, struct scst_info_cdb *info_cdb)
static int scst_null_parse(struct scst_cmd *cmd, struct scst_info_cdb *info_cdb)
{
int res = 0;
@@ -2099,6 +2103,152 @@ int scst_null_parse(struct scst_cmd *cmd, struct scst_info_cdb *info_cdb)
return res;
}
int scst_changer_generic_parse(struct scst_cmd *cmd,
struct scst_info_cdb *info_cdb, int nothing)
{
return scst_null_parse(cmd, info_cdb);
}
int scst_processor_generic_parse(struct scst_cmd *cmd,
struct scst_info_cdb *info_cdb, int nothing)
{
return scst_null_parse(cmd, info_cdb);
}
int scst_raid_generic_parse(struct scst_cmd *cmd,
struct scst_info_cdb *info_cdb, int nothing)
{
return scst_null_parse(cmd, info_cdb);
}
int scst_block_generic_dev_done(struct scst_cmd *cmd,
void (*set_block_shift)(struct scst_cmd *cmd, int block_shift))
{
int opcode = cmd->cdb[0];
int status = cmd->status;
int res = SCST_CMD_STATE_DEFAULT;
TRACE_ENTRY();
if (unlikely(cmd->sg == NULL))
goto out;
/*
* SCST sets good defaults for cmd->tgt_resp_flags and cmd->resp_data_len
* based on cmd->status and cmd->data_direction, therefore change
* them only if necessary
*/
if ((status == SAM_STAT_GOOD) || (status == SAM_STAT_CONDITION_MET)) {
switch (opcode) {
case READ_CAPACITY:
{
/* Always keep track of disk capacity */
int buffer_size, sector_size, sh;
uint8_t *buffer;
buffer_size = scst_get_buf_first(cmd, &buffer);
if (unlikely(buffer_size <= 0)) {
PRINT_ERROR_PR("%s: Unable to get the buffer",
__FUNCTION__);
scst_set_busy(cmd);
goto out;
}
sector_size =
((buffer[4] << 24) | (buffer[5] << 16) |
(buffer[6] << 8) | (buffer[7] << 0));
scst_put_buf(cmd, buffer);
if (sector_size != 0)
sh = scst_calc_block_shift(sector_size);
else
sh = 0;
set_block_shift(cmd, sh);
TRACE(TRACE_SCSI, "block_shift %d", sh);
break;
}
default:
/* It's all good */
break;
}
}
TRACE_DBG("cmd->tgt_resp_flags=%x, cmd->resp_data_len=%d, "
"res=%d", cmd->tgt_resp_flags, cmd->resp_data_len, res);
out:
TRACE_EXIT_RES(res);
return res;
}
int scst_tape_generic_dev_done(struct scst_cmd *cmd,
void (*set_block_size)(struct scst_cmd *cmd, int block_shift))
{
int opcode = cmd->cdb[0];
int res = SCST_CMD_STATE_DEFAULT;
int buffer_size, bs;
uint8_t *buffer = NULL;
TRACE_ENTRY();
if (unlikely(cmd->sg == NULL))
goto out;
/*
* SCST sets good defaults for cmd->tgt_resp_flags and cmd->resp_data_len
* based on cmd->status and cmd->data_direction, therefore change
* them only if necessary
*/
switch (opcode) {
case MODE_SENSE:
case MODE_SELECT:
buffer_size = scst_get_buf_first(cmd, &buffer);
if (unlikely(buffer_size <= 0)) {
PRINT_ERROR_PR("%s: Unable to get the buffer",
__FUNCTION__);
scst_set_busy(cmd);
goto out;
}
break;
}
switch (opcode) {
case MODE_SENSE:
TRACE_DBG("%s", "MODE_SENSE");
if ((cmd->cdb[2] & 0xC0) == 0) {
if (buffer[3] == 8) {
bs = (buffer[9] << 16) |
(buffer[10] << 8) | buffer[11];
set_block_size(cmd, bs);
}
}
break;
case MODE_SELECT:
TRACE_DBG("%s", "MODE_SELECT");
if (buffer[3] == 8) {
bs = (buffer[9] << 16) | (buffer[10] << 8) |
(buffer[11]);
set_block_size(cmd, bs);
}
break;
default:
/* It's all good */
break;
}
switch (opcode) {
case MODE_SENSE:
case MODE_SELECT:
scst_put_buf(cmd, buffer);
break;
}
out:
TRACE_EXIT_RES(res);
return res;
}
/* Called under dev_lock and BH off */
void scst_process_reset(struct scst_device *dev,
struct scst_session *originator, struct scst_cmd *exclude_cmd,