mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-24 13:44:26 -04:00
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:
commit
211c8d4942
91 changed files with 3945 additions and 1028 deletions
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 *);
|
||||
|
|
|
|||
Loading…
Reference in a new issue