mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-22 13:11:27 +00:00
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:
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user