Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (59 commits)
  [SCSI] replace __FUNCTION__ with __func__
  [SCSI] extend the last_sector_bug flag to cover more sectors
  [SCSI] qla2xxx: Update version number to 8.02.01-k6.
  [SCSI] qla2xxx: Additional NPIV corrections.
  [SCSI] qla2xxx: suppress uninitialized-var warning
  [SCSI] qla2xxx: use memory_read_from_buffer()
  [SCSI] qla2xxx: Issue proper ISP callbacks during stop-firmware.
  [SCSI] ch: fix ch_remove oops
  [SCSI] 3w-9xxx: add MSI support and misc fixes
  [SCSI] scsi_lib: use blk_rq_tagged in scsi_request_fn
  [SCSI] ibmvfc: Update driver version to 1.0.1
  [SCSI] ibmvfc: Add ADISC support
  [SCSI] ibmvfc: Miscellaneous fixes
  [SCSI] ibmvfc: Fix hang on module removal
  [SCSI] ibmvfc: Target refcounting fixes
  [SCSI] ibmvfc: Reduce unnecessary log noise
  [SCSI] sym53c8xx: free luntbl in sym_hcb_free
  [SCSI] scsi_scan.c: Release mutex in error handling code
  [SCSI] scsi_eh_prep_cmnd should save scmd->underflow
  [SCSI] sd: Support for SCSI disk (SBC) Data Integrity Field
  ...
This commit is contained in:
Linus Torvalds 2008-07-27 10:04:52 -07:00
commit 211c8d4942
91 changed files with 3945 additions and 1028 deletions

View file

@ -106,6 +106,7 @@
#define VARIABLE_LENGTH_CMD 0x7f
#define REPORT_LUNS 0xa0
#define MAINTENANCE_IN 0xa3
#define MAINTENANCE_OUT 0xa4
#define MOVE_MEDIUM 0xa5
#define EXCHANGE_MEDIUM 0xa6
#define READ_12 0xa8
@ -125,6 +126,8 @@
#define SAI_READ_CAPACITY_16 0x10
/* values for maintenance in */
#define MI_REPORT_TARGET_PGS 0x0a
/* values for maintenance out */
#define MO_SET_TARGET_PGS 0x0a
/* Values for T10/04-262r7 */
#define ATA_16 0x85 /* 16-byte pass-thru */

View file

@ -77,6 +77,9 @@ struct scsi_cmnd {
int allowed;
int timeout_per_command;
unsigned char prot_op;
unsigned char prot_type;
unsigned short cmd_len;
enum dma_data_direction sc_data_direction;
@ -87,6 +90,8 @@ struct scsi_cmnd {
/* These elements define the operation we ultimately want to perform */
struct scsi_data_buffer sdb;
struct scsi_data_buffer *prot_sdb;
unsigned underflow; /* Return error if less than
this amount is transferred */
@ -208,4 +213,85 @@ static inline int scsi_sg_copy_to_buffer(struct scsi_cmnd *cmd,
buf, buflen);
}
/*
* The operations below are hints that tell the controller driver how
* to handle I/Os with DIF or similar types of protection information.
*/
enum scsi_prot_operations {
/* Normal I/O */
SCSI_PROT_NORMAL = 0,
/* OS-HBA: Protected, HBA-Target: Unprotected */
SCSI_PROT_READ_INSERT,
SCSI_PROT_WRITE_STRIP,
/* OS-HBA: Unprotected, HBA-Target: Protected */
SCSI_PROT_READ_STRIP,
SCSI_PROT_WRITE_INSERT,
/* OS-HBA: Protected, HBA-Target: Protected */
SCSI_PROT_READ_PASS,
SCSI_PROT_WRITE_PASS,
/* OS-HBA: Protected, HBA-Target: Protected, checksum conversion */
SCSI_PROT_READ_CONVERT,
SCSI_PROT_WRITE_CONVERT,
};
static inline void scsi_set_prot_op(struct scsi_cmnd *scmd, unsigned char op)
{
scmd->prot_op = op;
}
static inline unsigned char scsi_get_prot_op(struct scsi_cmnd *scmd)
{
return scmd->prot_op;
}
/*
* The controller usually does not know anything about the target it
* is communicating with. However, when DIX is enabled the controller
* must be know target type so it can verify the protection
* information passed along with the I/O.
*/
enum scsi_prot_target_type {
SCSI_PROT_DIF_TYPE0 = 0,
SCSI_PROT_DIF_TYPE1,
SCSI_PROT_DIF_TYPE2,
SCSI_PROT_DIF_TYPE3,
};
static inline void scsi_set_prot_type(struct scsi_cmnd *scmd, unsigned char type)
{
scmd->prot_type = type;
}
static inline unsigned char scsi_get_prot_type(struct scsi_cmnd *scmd)
{
return scmd->prot_type;
}
static inline sector_t scsi_get_lba(struct scsi_cmnd *scmd)
{
return scmd->request->sector;
}
static inline unsigned scsi_prot_sg_count(struct scsi_cmnd *cmd)
{
return cmd->prot_sdb ? cmd->prot_sdb->table.nents : 0;
}
static inline struct scatterlist *scsi_prot_sglist(struct scsi_cmnd *cmd)
{
return cmd->prot_sdb ? cmd->prot_sdb->table.sgl : NULL;
}
static inline struct scsi_data_buffer *scsi_prot(struct scsi_cmnd *cmd)
{
return cmd->prot_sdb;
}
#define scsi_for_each_prot_sg(cmd, sg, nseg, __i) \
for_each_sg(scsi_prot_sglist(cmd), sg, nseg, __i)
#endif /* _SCSI_SCSI_CMND_H */

View file

@ -140,7 +140,8 @@ struct scsi_device {
unsigned fix_capacity:1; /* READ_CAPACITY is too high by 1 */
unsigned guess_capacity:1; /* READ_CAPACITY might be too high by 1 */
unsigned retry_hwerror:1; /* Retry HARDWARE_ERROR */
unsigned last_sector_bug:1; /* Always read last sector in a 1 sector read */
unsigned last_sector_bug:1; /* do not use multisector accesses on
SD_LAST_BUGGY_SECTORS */
DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */
struct list_head event_list; /* asserted events */
@ -167,15 +168,22 @@ struct scsi_device {
unsigned long sdev_data[0];
} __attribute__((aligned(sizeof(unsigned long))));
struct scsi_dh_devlist {
char *vendor;
char *model;
};
struct scsi_device_handler {
/* Used by the infrastructure */
struct list_head list; /* list of scsi_device_handlers */
struct notifier_block nb;
/* Filled by the hardware handler */
struct module *module;
const char *name;
const struct scsi_dh_devlist *devlist;
int (*check_sense)(struct scsi_device *, struct scsi_sense_hdr *);
int (*attach)(struct scsi_device *);
void (*detach)(struct scsi_device *);
int (*activate)(struct scsi_device *);
int (*prep_fn)(struct scsi_device *, struct request *);
};
@ -416,6 +424,11 @@ static inline int scsi_device_enclosure(struct scsi_device *sdev)
return sdev->inquiry[6] & (1<<6);
}
static inline int scsi_device_protection(struct scsi_device *sdev)
{
return sdev->inquiry[5] & (1<<0);
}
#define MODULE_ALIAS_SCSI_DEVICE(type) \
MODULE_ALIAS("scsi:t-" __stringify(type) "*")
#define SCSI_DEVICE_MODALIAS_FMT "scsi:t-0x%02x"

View file

@ -32,6 +32,7 @@ enum {
*/
SCSI_DH_DEV_FAILED, /* generic device error */
SCSI_DH_DEV_TEMP_BUSY,
SCSI_DH_DEV_UNSUPP, /* device handler not supported */
SCSI_DH_DEVICE_MAX, /* max device blkerr definition */
/*
@ -57,6 +58,8 @@ enum {
#if defined(CONFIG_SCSI_DH) || defined(CONFIG_SCSI_DH_MODULE)
extern int scsi_dh_activate(struct request_queue *);
extern int scsi_dh_handler_exist(const char *);
extern int scsi_dh_attach(struct request_queue *, const char *);
extern void scsi_dh_detach(struct request_queue *);
#else
static inline int scsi_dh_activate(struct request_queue *req)
{
@ -66,4 +69,12 @@ static inline int scsi_dh_handler_exist(const char *name)
{
return 0;
}
static inline int scsi_dh_attach(struct request_queue *req, const char *name)
{
return SCSI_DH_NOSYS;
}
static inline void scsi_dh_detach(struct request_queue *q)
{
return;
}
#endif

View file

@ -74,7 +74,9 @@ struct scsi_eh_save {
/* saved state */
int result;
enum dma_data_direction data_direction;
unsigned underflow;
unsigned char cmd_len;
unsigned char prot_op;
unsigned char *cmnd;
struct scsi_data_buffer sdb;
struct request *next_rq;

View file

@ -547,7 +547,7 @@ struct Scsi_Host {
unsigned int host_failed; /* commands that failed. */
unsigned int host_eh_scheduled; /* EH scheduled without command */
unsigned short host_no; /* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */
unsigned int host_no; /* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */
int resetting; /* if set, it means that last_reset is a valid value */
unsigned long last_reset;
@ -636,6 +636,10 @@ struct Scsi_Host {
*/
unsigned int max_host_blocked;
/* Protection Information */
unsigned int prot_capabilities;
unsigned char prot_guard_type;
/*
* q used for scsi_tgt msgs, async events or any other requests that
* need to be processed in userspace
@ -756,6 +760,86 @@ extern struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost,
extern void scsi_free_host_dev(struct scsi_device *);
extern struct scsi_device *scsi_get_host_dev(struct Scsi_Host *);
/*
* DIF defines the exchange of protection information between
* initiator and SBC block device.
*
* DIX defines the exchange of protection information between OS and
* initiator.
*/
enum scsi_host_prot_capabilities {
SHOST_DIF_TYPE1_PROTECTION = 1 << 0, /* T10 DIF Type 1 */
SHOST_DIF_TYPE2_PROTECTION = 1 << 1, /* T10 DIF Type 2 */
SHOST_DIF_TYPE3_PROTECTION = 1 << 2, /* T10 DIF Type 3 */
SHOST_DIX_TYPE0_PROTECTION = 1 << 3, /* DIX between OS and HBA only */
SHOST_DIX_TYPE1_PROTECTION = 1 << 4, /* DIX with DIF Type 1 */
SHOST_DIX_TYPE2_PROTECTION = 1 << 5, /* DIX with DIF Type 2 */
SHOST_DIX_TYPE3_PROTECTION = 1 << 6, /* DIX with DIF Type 3 */
};
/*
* SCSI hosts which support the Data Integrity Extensions must
* indicate their capabilities by setting the prot_capabilities using
* this call.
*/
static inline void scsi_host_set_prot(struct Scsi_Host *shost, unsigned int mask)
{
shost->prot_capabilities = mask;
}
static inline unsigned int scsi_host_get_prot(struct Scsi_Host *shost)
{
return shost->prot_capabilities;
}
static inline unsigned int scsi_host_dif_capable(struct Scsi_Host *shost, unsigned int target_type)
{
switch (target_type) {
case 1: return shost->prot_capabilities & SHOST_DIF_TYPE1_PROTECTION;
case 2: return shost->prot_capabilities & SHOST_DIF_TYPE2_PROTECTION;
case 3: return shost->prot_capabilities & SHOST_DIF_TYPE3_PROTECTION;
}
return 0;
}
static inline unsigned int scsi_host_dix_capable(struct Scsi_Host *shost, unsigned int target_type)
{
switch (target_type) {
case 0: return shost->prot_capabilities & SHOST_DIX_TYPE0_PROTECTION;
case 1: return shost->prot_capabilities & SHOST_DIX_TYPE1_PROTECTION;
case 2: return shost->prot_capabilities & SHOST_DIX_TYPE2_PROTECTION;
case 3: return shost->prot_capabilities & SHOST_DIX_TYPE3_PROTECTION;
}
return 0;
}
/*
* All DIX-capable initiators must support the T10-mandated CRC
* checksum. Controllers can optionally implement the IP checksum
* scheme which has much lower impact on system performance. Note
* that the main rationale for the checksum is to match integrity
* metadata with data. Detecting bit errors are a job for ECC memory
* and buses.
*/
enum scsi_host_guard_type {
SHOST_DIX_GUARD_CRC = 1 << 0,
SHOST_DIX_GUARD_IP = 1 << 1,
};
static inline void scsi_host_set_guard(struct Scsi_Host *shost, unsigned char type)
{
shost->prot_guard_type = type;
}
static inline unsigned char scsi_host_get_guard(struct Scsi_Host *shost)
{
return shost->prot_guard_type;
}
/* legacy interfaces */
extern struct Scsi_Host *scsi_register(struct scsi_host_template *, int);
extern void scsi_unregister(struct Scsi_Host *);