From 881a256d84e658d14ca1c162fe56e9cbbb1cdd49 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 31 Dec 2008 13:12:46 -0500 Subject: [SCSI] Add VPD helper Based on prior work by Martin Petersen and James Bottomley, this patch adds a generic helper for retrieving VPD pages from SCSI devices. Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley --- drivers/scsi/scsi.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index cbcd3f681b6..a2ef03243a2 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -966,6 +966,110 @@ int scsi_track_queue_full(struct scsi_device *sdev, int depth) } EXPORT_SYMBOL(scsi_track_queue_full); +/** + * scsi_vpd_inquiry - Request a device provide us with a VPD page + * @sdev: The device to ask + * @buffer: Where to put the result + * @page: Which Vital Product Data to return + * @len: The length of the buffer + * + * This is an internal helper function. You probably want to use + * scsi_get_vpd_page instead. + * + * Returns 0 on success or a negative error number. + */ +static int scsi_vpd_inquiry(struct scsi_device *sdev, unsigned char *buffer, + u8 page, unsigned len) +{ + int result; + unsigned char cmd[16]; + + cmd[0] = INQUIRY; + cmd[1] = 1; /* EVPD */ + cmd[2] = page; + cmd[3] = len >> 8; + cmd[4] = len & 0xff; + cmd[5] = 0; /* Control byte */ + + /* + * I'm not convinced we need to try quite this hard to get VPD, but + * all the existing users tried this hard. + */ + result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer, + len + 4, NULL, 30 * HZ, 3, NULL); + if (result) + return result; + + /* Sanity check that we got the page back that we asked for */ + if (buffer[1] != page) + return -EIO; + + return 0; +} + +/** + * scsi_get_vpd_page - Get Vital Product Data from a SCSI device + * @sdev: The device to ask + * @page: Which Vital Product Data to return + * + * SCSI devices may optionally supply Vital Product Data. Each 'page' + * of VPD is defined in the appropriate SCSI document (eg SPC, SBC). + * If the device supports this VPD page, this routine returns a pointer + * to a buffer containing the data from that page. The caller is + * responsible for calling kfree() on this pointer when it is no longer + * needed. If we cannot retrieve the VPD page this routine returns %NULL. + */ +unsigned char *scsi_get_vpd_page(struct scsi_device *sdev, u8 page) +{ + int i, result; + unsigned int len; + unsigned char *buf = kmalloc(259, GFP_KERNEL); + + if (!buf) + return NULL; + + /* Ask for all the pages supported by this device */ + result = scsi_vpd_inquiry(sdev, buf, 0, 255); + if (result) + goto fail; + + /* If the user actually wanted this page, we can skip the rest */ + if (page == 0) + return buf; + + for (i = 0; i < buf[3]; i++) + if (buf[i + 4] == page) + goto found; + /* The device claims it doesn't support the requested page */ + goto fail; + + found: + result = scsi_vpd_inquiry(sdev, buf, page, 255); + if (result) + goto fail; + + /* + * Some pages are longer than 255 bytes. The actual length of + * the page is returned in the header. + */ + len = (buf[2] << 8) | buf[3]; + if (len <= 255) + return buf; + + kfree(buf); + buf = kmalloc(len + 4, GFP_KERNEL); + result = scsi_vpd_inquiry(sdev, buf, page, len); + if (result) + goto fail; + + return buf; + + fail: + kfree(buf); + return NULL; +} +EXPORT_SYMBOL_GPL(scsi_get_vpd_page); + /** * scsi_device_get - get an additional reference to a scsi_device * @sdev: device to get a reference to -- cgit v1.2.3-18-g5258 From 40c3460f3cad1672f22baadcdbe20b9b3200cc20 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 31 Dec 2008 12:11:17 -0700 Subject: [SCSI] ses: Use new scsi VPD helper SES had its own code to retrieve VPD from devices; convert it to use the new scsi_get_vpd_page helper. Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley --- drivers/scsi/ses.c | 31 ++++--------------------------- 1 file changed, 4 insertions(+), 27 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c index e946e05db7f..f2cf9523554 100644 --- a/drivers/scsi/ses.c +++ b/drivers/scsi/ses.c @@ -345,44 +345,21 @@ static int ses_enclosure_find_by_addr(struct enclosure_device *edev, return 0; } -#define VPD_INQUIRY_SIZE 36 - static void ses_match_to_enclosure(struct enclosure_device *edev, struct scsi_device *sdev) { - unsigned char *buf = kmalloc(VPD_INQUIRY_SIZE, GFP_KERNEL); + unsigned char *buf; unsigned char *desc; - u16 vpd_len; + unsigned int vpd_len; struct efd efd = { .addr = 0, }; - unsigned char cmd[] = { - INQUIRY, - 1, - 0x83, - VPD_INQUIRY_SIZE >> 8, - VPD_INQUIRY_SIZE & 0xff, - 0 - }; + buf = scsi_get_vpd_page(sdev, 0x83); if (!buf) return; - if (scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buf, - VPD_INQUIRY_SIZE, NULL, SES_TIMEOUT, SES_RETRIES, - NULL)) - goto free; - - vpd_len = (buf[2] << 8) + buf[3]; - kfree(buf); - buf = kmalloc(vpd_len, GFP_KERNEL); - if (!buf) - return; - cmd[3] = vpd_len >> 8; - cmd[4] = vpd_len & 0xff; - if (scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buf, - vpd_len, NULL, SES_TIMEOUT, SES_RETRIES, NULL)) - goto free; + vpd_len = ((buf[2] << 8) | buf[3]) + 4; desc = buf + 4; while (desc < buf + vpd_len) { -- cgit v1.2.3-18-g5258 From 59d3270326fcba29226c28df27cb43fefd8c58d0 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 9 Jan 2009 15:28:13 -0800 Subject: [SCSI] scsi_sysfs: delete extra kernel-doc Warning(linux-2.6.28-git13//drivers/scsi/scsi_sysfs.c:1049): Excess function parameter 'dev' description in 'scsi_sysfs_add_host' Signed-off-by: Randy Dunlap Signed-off-by: James Bottomley --- drivers/scsi/scsi_sysfs.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index da63802cbf9..fa4711d1274 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -1043,7 +1043,6 @@ EXPORT_SYMBOL(scsi_register_interface); /** * scsi_sysfs_add_host - add scsi host to subsystem * @shost: scsi host struct to add to subsystem - * @dev: parent struct device pointer **/ int scsi_sysfs_add_host(struct Scsi_Host *shost) { -- cgit v1.2.3-18-g5258 From c6a44287417de1625a59f1d4ae52d033c03b9dab Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Sun, 4 Jan 2009 03:08:19 -0500 Subject: [SCSI] scsi_debug: DIF/DIX support This patch adds support for DIX and DIF in scsi_debug. A separate buffer is allocated for the protection information. - The dix parameter indicates whether the controller supports DIX (protection information DMA) - The dif parameter indicates whether the simulated storage device supports DIF - The guard parameter switches between T10 CRC(0) and IP checksum(1) - The ato parameter indicates whether the application tag is owned by the disk(0) or the OS(1) - DIF and DIX errors can be triggered using the scsi_debug_opts mask Signed-off-by: Martin K. Petersen Acked-by: Douglas Gilbert Signed-off-by: James Bottomley --- drivers/scsi/scsi_debug.c | 443 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 436 insertions(+), 7 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 6eebd0bbe8a..213123b0486 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -40,6 +40,9 @@ #include #include #include +#include + +#include #include #include @@ -48,8 +51,7 @@ #include #include -#include - +#include "sd.h" #include "scsi_logging.h" #define SCSI_DEBUG_VERSION "1.81" @@ -95,6 +97,10 @@ static const char * scsi_debug_version_date = "20070104"; #define DEF_FAKE_RW 0 #define DEF_VPD_USE_HOSTNO 1 #define DEF_SECTOR_SIZE 512 +#define DEF_DIX 0 +#define DEF_DIF 0 +#define DEF_GUARD 0 +#define DEF_ATO 1 /* bit mask values for scsi_debug_opts */ #define SCSI_DEBUG_OPT_NOISE 1 @@ -102,6 +108,8 @@ static const char * scsi_debug_version_date = "20070104"; #define SCSI_DEBUG_OPT_TIMEOUT 4 #define SCSI_DEBUG_OPT_RECOVERED_ERR 8 #define SCSI_DEBUG_OPT_TRANSPORT_ERR 16 +#define SCSI_DEBUG_OPT_DIF_ERR 32 +#define SCSI_DEBUG_OPT_DIX_ERR 64 /* When "every_nth" > 0 then modulo "every_nth" commands: * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set * - a RECOVERED_ERROR is simulated on successful read and write @@ -144,6 +152,10 @@ static int scsi_debug_virtual_gb = DEF_VIRTUAL_GB; static int scsi_debug_fake_rw = DEF_FAKE_RW; static int scsi_debug_vpd_use_hostno = DEF_VPD_USE_HOSTNO; static int scsi_debug_sector_size = DEF_SECTOR_SIZE; +static int scsi_debug_dix = DEF_DIX; +static int scsi_debug_dif = DEF_DIF; +static int scsi_debug_guard = DEF_GUARD; +static int scsi_debug_ato = DEF_ATO; static int scsi_debug_cmnd_count = 0; @@ -204,11 +216,15 @@ struct sdebug_queued_cmd { static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE]; static unsigned char * fake_storep; /* ramdisk storage */ +static unsigned char *dif_storep; /* protection info */ static int num_aborts = 0; static int num_dev_resets = 0; static int num_bus_resets = 0; static int num_host_resets = 0; +static int dix_writes; +static int dix_reads; +static int dif_errors; static DEFINE_SPINLOCK(queued_arr_lock); static DEFINE_RWLOCK(atomic_rw); @@ -217,6 +233,11 @@ static char sdebug_proc_name[] = "scsi_debug"; static struct bus_type pseudo_lld_bus; +static inline sector_t dif_offset(sector_t sector) +{ + return sector << 3; +} + static struct device_driver sdebug_driverfs_driver = { .name = sdebug_proc_name, .bus = &pseudo_lld_bus, @@ -225,6 +246,9 @@ static struct device_driver sdebug_driverfs_driver = { static const int check_condition_result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; +static const int illegal_condition_result = + (DRIVER_SENSE << 24) | (DID_ABORT << 16) | SAM_STAT_CHECK_CONDITION; + static unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0, 0, 0, 0x2, 0x4b}; static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0, @@ -726,7 +750,12 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target, } else if (0x86 == cmd[2]) { /* extended inquiry */ arr[1] = cmd[2]; /*sanity */ arr[3] = 0x3c; /* number of following entries */ - arr[4] = 0x0; /* no protection stuff */ + if (scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) + arr[4] = 0x4; /* SPT: GRD_CHK:1 */ + else if (scsi_debug_dif) + arr[4] = 0x5; /* SPT: GRD_CHK:1, REF_CHK:1 */ + else + arr[4] = 0x0; /* no protection stuff */ arr[5] = 0x7; /* head of q, ordered + simple q's */ } else if (0x87 == cmd[2]) { /* mode page policy */ arr[1] = cmd[2]; /*sanity */ @@ -767,6 +796,7 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target, arr[2] = scsi_debug_scsi_level; arr[3] = 2; /* response_data_format==2 */ arr[4] = SDEBUG_LONG_INQ_SZ - 5; + arr[5] = scsi_debug_dif ? 1 : 0; /* PROTECT bit */ if (0 == scsi_debug_vpd_use_hostno) arr[5] = 0x10; /* claim: implicit TGPS */ arr[6] = 0x10; /* claim: MultiP */ @@ -915,6 +945,12 @@ static int resp_readcap16(struct scsi_cmnd * scp, arr[9] = (scsi_debug_sector_size >> 16) & 0xff; arr[10] = (scsi_debug_sector_size >> 8) & 0xff; arr[11] = scsi_debug_sector_size & 0xff; + + if (scsi_debug_dif) { + arr[12] = (scsi_debug_dif - 1) << 1; /* P_TYPE */ + arr[12] |= 1; /* PROT_EN */ + } + return fill_from_dev_buffer(scp, arr, min(alloc_len, SDEBUG_READCAP16_ARR_SZ)); } @@ -1066,6 +1102,10 @@ static int resp_ctrl_m_pg(unsigned char * p, int pcontrol, int target) ctrl_m_pg[2] |= 0x4; else ctrl_m_pg[2] &= ~0x4; + + if (scsi_debug_ato) + ctrl_m_pg[5] |= 0x80; /* ATO=1 */ + memcpy(p, ctrl_m_pg, sizeof(ctrl_m_pg)); if (1 == pcontrol) memcpy(p + 2, ch_ctrl_m_pg, sizeof(ch_ctrl_m_pg)); @@ -1536,6 +1576,87 @@ static int do_device_access(struct scsi_cmnd *scmd, return ret; } +static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec, + unsigned int sectors) +{ + unsigned int i, resid; + struct scatterlist *psgl; + struct sd_dif_tuple *sdt; + sector_t sector; + sector_t tmp_sec = start_sec; + void *paddr; + + start_sec = do_div(tmp_sec, sdebug_store_sectors); + + sdt = (struct sd_dif_tuple *)(dif_storep + dif_offset(start_sec)); + + for (i = 0 ; i < sectors ; i++) { + u16 csum; + + if (sdt[i].app_tag == 0xffff) + continue; + + sector = start_sec + i; + + switch (scsi_debug_guard) { + case 1: + csum = ip_compute_csum(fake_storep + + sector * scsi_debug_sector_size, + scsi_debug_sector_size); + break; + case 0: + csum = crc_t10dif(fake_storep + + sector * scsi_debug_sector_size, + scsi_debug_sector_size); + csum = cpu_to_be16(csum); + break; + default: + BUG(); + } + + if (sdt[i].guard_tag != csum) { + printk(KERN_ERR "%s: GUARD check failed on sector %lu" \ + " rcvd 0x%04x, data 0x%04x\n", __func__, + (unsigned long)sector, + be16_to_cpu(sdt[i].guard_tag), + be16_to_cpu(csum)); + dif_errors++; + return 0x01; + } + + if (scsi_debug_dif != SD_DIF_TYPE3_PROTECTION && + be32_to_cpu(sdt[i].ref_tag) != (sector & 0xffffffff)) { + printk(KERN_ERR "%s: REF check failed on sector %lu\n", + __func__, (unsigned long)sector); + dif_errors++; + return 0x03; + } + } + + resid = sectors * 8; /* Bytes of protection data to copy into sgl */ + sector = start_sec; + + scsi_for_each_prot_sg(SCpnt, psgl, scsi_prot_sg_count(SCpnt), i) { + int len = min(psgl->length, resid); + + paddr = kmap_atomic(sg_page(psgl), KM_IRQ0) + psgl->offset; + memcpy(paddr, dif_storep + dif_offset(sector), len); + + sector += len >> 3; + if (sector >= sdebug_store_sectors) { + /* Force wrap */ + tmp_sec = sector; + sector = do_div(tmp_sec, sdebug_store_sectors); + } + resid -= len; + kunmap_atomic(paddr, KM_IRQ0); + } + + dix_reads++; + + return 0; +} + static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba, unsigned int num, struct sdebug_dev_info *devip) { @@ -1563,12 +1684,162 @@ static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba, } return check_condition_result; } + + /* DIX + T10 DIF */ + if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) { + int prot_ret = prot_verify_read(SCpnt, lba, num); + + if (prot_ret) { + mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, prot_ret); + return illegal_condition_result; + } + } + read_lock_irqsave(&atomic_rw, iflags); ret = do_device_access(SCpnt, devip, lba, num, 0); read_unlock_irqrestore(&atomic_rw, iflags); return ret; } +void dump_sector(unsigned char *buf, int len) +{ + int i, j; + + printk(KERN_ERR ">>> Sector Dump <<<\n"); + + for (i = 0 ; i < len ; i += 16) { + printk(KERN_ERR "%04d: ", i); + + for (j = 0 ; j < 16 ; j++) { + unsigned char c = buf[i+j]; + if (c >= 0x20 && c < 0x7e) + printk(" %c ", buf[i+j]); + else + printk("%02x ", buf[i+j]); + } + + printk("\n"); + } +} + +static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, + unsigned int sectors) +{ + int i, j, ret; + struct sd_dif_tuple *sdt; + struct scatterlist *dsgl = scsi_sglist(SCpnt); + struct scatterlist *psgl = scsi_prot_sglist(SCpnt); + void *daddr, *paddr; + sector_t tmp_sec = start_sec; + sector_t sector; + int ppage_offset; + unsigned short csum; + + sector = do_div(tmp_sec, sdebug_store_sectors); + + if (((SCpnt->cmnd[1] >> 5) & 7) != 1) { + printk(KERN_WARNING "scsi_debug: WRPROTECT != 1\n"); + return 0; + } + + BUG_ON(scsi_sg_count(SCpnt) == 0); + BUG_ON(scsi_prot_sg_count(SCpnt) == 0); + + paddr = kmap_atomic(sg_page(psgl), KM_IRQ1) + psgl->offset; + ppage_offset = 0; + + /* For each data page */ + scsi_for_each_sg(SCpnt, dsgl, scsi_sg_count(SCpnt), i) { + daddr = kmap_atomic(sg_page(dsgl), KM_IRQ0) + dsgl->offset; + + /* For each sector-sized chunk in data page */ + for (j = 0 ; j < dsgl->length ; j += scsi_debug_sector_size) { + + /* If we're at the end of the current + * protection page advance to the next one + */ + if (ppage_offset >= psgl->length) { + kunmap_atomic(paddr, KM_IRQ1); + psgl = sg_next(psgl); + BUG_ON(psgl == NULL); + paddr = kmap_atomic(sg_page(psgl), KM_IRQ1) + + psgl->offset; + ppage_offset = 0; + } + + sdt = paddr + ppage_offset; + + switch (scsi_debug_guard) { + case 1: + csum = ip_compute_csum(daddr, + scsi_debug_sector_size); + break; + case 0: + csum = cpu_to_be16(crc_t10dif(daddr, + scsi_debug_sector_size)); + break; + default: + BUG(); + ret = 0; + goto out; + } + + if (sdt->guard_tag != csum) { + printk(KERN_ERR + "%s: GUARD check failed on sector %lu " \ + "rcvd 0x%04x, calculated 0x%04x\n", + __func__, (unsigned long)sector, + be16_to_cpu(sdt->guard_tag), + be16_to_cpu(csum)); + ret = 0x01; + dump_sector(daddr, scsi_debug_sector_size); + goto out; + } + + if (scsi_debug_dif != SD_DIF_TYPE3_PROTECTION && + be32_to_cpu(sdt->ref_tag) + != (start_sec & 0xffffffff)) { + printk(KERN_ERR + "%s: REF check failed on sector %lu\n", + __func__, (unsigned long)sector); + ret = 0x03; + dump_sector(daddr, scsi_debug_sector_size); + goto out; + } + + /* Would be great to copy this in bigger + * chunks. However, for the sake of + * correctness we need to verify each sector + * before writing it to "stable" storage + */ + memcpy(dif_storep + dif_offset(sector), sdt, 8); + + sector++; + + if (sector == sdebug_store_sectors) + sector = 0; /* Force wrap */ + + start_sec++; + daddr += scsi_debug_sector_size; + ppage_offset += sizeof(struct sd_dif_tuple); + } + + kunmap_atomic(daddr, KM_IRQ0); + } + + kunmap_atomic(paddr, KM_IRQ1); + + dix_writes++; + + return 0; + +out: + dif_errors++; + kunmap_atomic(daddr, KM_IRQ0); + kunmap_atomic(paddr, KM_IRQ1); + return ret; +} + static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba, unsigned int num, struct sdebug_dev_info *devip) { @@ -1579,6 +1850,16 @@ static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba, if (ret) return ret; + /* DIX + T10 DIF */ + if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) { + int prot_ret = prot_verify_write(SCpnt, lba, num); + + if (prot_ret) { + mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, prot_ret); + return illegal_condition_result; + } + } + write_lock_irqsave(&atomic_rw, iflags); ret = do_device_access(SCpnt, devip, lba, num, 1); write_unlock_irqrestore(&atomic_rw, iflags); @@ -2095,6 +2376,10 @@ module_param_named(virtual_gb, scsi_debug_virtual_gb, int, S_IRUGO | S_IWUSR); module_param_named(vpd_use_hostno, scsi_debug_vpd_use_hostno, int, S_IRUGO | S_IWUSR); module_param_named(sector_size, scsi_debug_sector_size, int, S_IRUGO); +module_param_named(dix, scsi_debug_dix, int, S_IRUGO); +module_param_named(dif, scsi_debug_dif, int, S_IRUGO); +module_param_named(guard, scsi_debug_guard, int, S_IRUGO); +module_param_named(ato, scsi_debug_ato, int, S_IRUGO); MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert"); MODULE_DESCRIPTION("SCSI debug adapter driver"); @@ -2117,7 +2402,10 @@ MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=5[SPC-3])"); MODULE_PARM_DESC(virtual_gb, "virtual gigabyte size (def=0 -> use dev_size_mb)"); MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)"); MODULE_PARM_DESC(sector_size, "hardware sector size in bytes (def=512)"); - +MODULE_PARM_DESC(dix, "data integrity extensions mask (def=0)"); +MODULE_PARM_DESC(dif, "data integrity field type: 0-3 (def=0)"); +MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)"); +MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)"); static char sdebug_info[256]; @@ -2164,14 +2452,14 @@ static int scsi_debug_proc_info(struct Scsi_Host *host, char *buffer, char **sta "delay=%d, max_luns=%d, scsi_level=%d\n" "sector_size=%d bytes, cylinders=%d, heads=%d, sectors=%d\n" "number of aborts=%d, device_reset=%d, bus_resets=%d, " - "host_resets=%d\n", + "host_resets=%d\ndix_reads=%d dix_writes=%d dif_errors=%d\n", SCSI_DEBUG_VERSION, scsi_debug_version_date, scsi_debug_num_tgts, scsi_debug_dev_size_mb, scsi_debug_opts, scsi_debug_every_nth, scsi_debug_cmnd_count, scsi_debug_delay, scsi_debug_max_luns, scsi_debug_scsi_level, scsi_debug_sector_size, sdebug_cylinders_per, sdebug_heads, sdebug_sectors_per, num_aborts, num_dev_resets, num_bus_resets, - num_host_resets); + num_host_resets, dix_reads, dix_writes, dif_errors); if (pos < offset) { len = 0; begin = pos; @@ -2452,6 +2740,31 @@ static ssize_t sdebug_sector_size_show(struct device_driver * ddp, char * buf) } DRIVER_ATTR(sector_size, S_IRUGO, sdebug_sector_size_show, NULL); +static ssize_t sdebug_dix_show(struct device_driver *ddp, char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dix); +} +DRIVER_ATTR(dix, S_IRUGO, sdebug_dix_show, NULL); + +static ssize_t sdebug_dif_show(struct device_driver *ddp, char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dif); +} +DRIVER_ATTR(dif, S_IRUGO, sdebug_dif_show, NULL); + +static ssize_t sdebug_guard_show(struct device_driver *ddp, char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_guard); +} +DRIVER_ATTR(guard, S_IRUGO, sdebug_guard_show, NULL); + +static ssize_t sdebug_ato_show(struct device_driver *ddp, char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ato); +} +DRIVER_ATTR(ato, S_IRUGO, sdebug_ato_show, NULL); + + /* Note: The following function creates attribute files in the /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these files (over those found in the /sys/module/scsi_debug/parameters @@ -2478,11 +2791,19 @@ static int do_create_driverfs_files(void) ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_virtual_gb); ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_vpd_use_hostno); ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_sector_size); + ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_dix); + ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_dif); + ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_guard); + ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_ato); return ret; } static void do_remove_driverfs_files(void) { + driver_remove_file(&sdebug_driverfs_driver, &driver_attr_ato); + driver_remove_file(&sdebug_driverfs_driver, &driver_attr_guard); + driver_remove_file(&sdebug_driverfs_driver, &driver_attr_dif); + driver_remove_file(&sdebug_driverfs_driver, &driver_attr_dix); driver_remove_file(&sdebug_driverfs_driver, &driver_attr_sector_size); driver_remove_file(&sdebug_driverfs_driver, &driver_attr_vpd_use_hostno); driver_remove_file(&sdebug_driverfs_driver, &driver_attr_virtual_gb); @@ -2526,11 +2847,33 @@ static int __init scsi_debug_init(void) case 4096: break; default: - printk(KERN_ERR "scsi_debug_init: invalid sector_size %u\n", + printk(KERN_ERR "scsi_debug_init: invalid sector_size %d\n", scsi_debug_sector_size); return -EINVAL; } + switch (scsi_debug_dif) { + + case SD_DIF_TYPE0_PROTECTION: + case SD_DIF_TYPE1_PROTECTION: + case SD_DIF_TYPE3_PROTECTION: + break; + + default: + printk(KERN_ERR "scsi_debug_init: dif must be 0, 1 or 3\n"); + return -EINVAL; + } + + if (scsi_debug_guard > 1) { + printk(KERN_ERR "scsi_debug_init: guard must be 0 or 1\n"); + return -EINVAL; + } + + if (scsi_debug_ato > 1) { + printk(KERN_ERR "scsi_debug_init: ato must be 0 or 1\n"); + return -EINVAL; + } + if (scsi_debug_dev_size_mb < 1) scsi_debug_dev_size_mb = 1; /* force minimum 1 MB ramdisk */ sz = (unsigned long)scsi_debug_dev_size_mb * 1048576; @@ -2563,6 +2906,24 @@ static int __init scsi_debug_init(void) if (scsi_debug_num_parts > 0) sdebug_build_parts(fake_storep, sz); + if (scsi_debug_dif) { + int dif_size; + + dif_size = sdebug_store_sectors * sizeof(struct sd_dif_tuple); + dif_storep = vmalloc(dif_size); + + printk(KERN_ERR "scsi_debug_init: dif_storep %u bytes @ %p\n", + dif_size, dif_storep); + + if (dif_storep == NULL) { + printk(KERN_ERR "scsi_debug_init: out of mem. (DIX)\n"); + ret = -ENOMEM; + goto free_vm; + } + + memset(dif_storep, 0xff, dif_size); + } + ret = device_register(&pseudo_primary); if (ret < 0) { printk(KERN_WARNING "scsi_debug: device_register error: %d\n", @@ -2615,6 +2976,8 @@ bus_unreg: dev_unreg: device_unregister(&pseudo_primary); free_vm: + if (dif_storep) + vfree(dif_storep); vfree(fake_storep); return ret; @@ -2632,6 +2995,9 @@ static void __exit scsi_debug_exit(void) bus_unregister(&pseudo_lld_bus); device_unregister(&pseudo_primary); + if (dif_storep) + vfree(dif_storep); + vfree(fake_storep); } @@ -2732,6 +3098,8 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done) struct sdebug_dev_info *devip = NULL; int inj_recovered = 0; int inj_transport = 0; + int inj_dif = 0; + int inj_dix = 0; int delay_override = 0; scsi_set_resid(SCpnt, 0); @@ -2769,6 +3137,10 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done) inj_recovered = 1; /* to reads and writes below */ else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & scsi_debug_opts) inj_transport = 1; /* to reads and writes below */ + else if (SCSI_DEBUG_OPT_DIF_ERR & scsi_debug_opts) + inj_dif = 1; /* to reads and writes below */ + else if (SCSI_DEBUG_OPT_DIX_ERR & scsi_debug_opts) + inj_dix = 1; /* to reads and writes below */ } if (devip->wlun) { @@ -2870,6 +3242,12 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done) mk_sense_buffer(devip, ABORTED_COMMAND, TRANSPORT_PROBLEM, ACK_NAK_TO); errsts = check_condition_result; + } else if (inj_dif && (0 == errsts)) { + mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, 1); + errsts = illegal_condition_result; + } else if (inj_dix && (0 == errsts)) { + mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, 1); + errsts = illegal_condition_result; } break; case REPORT_LUNS: /* mandatory, ignore unit attention */ @@ -2894,6 +3272,12 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done) mk_sense_buffer(devip, RECOVERED_ERROR, THRESHOLD_EXCEEDED, 0); errsts = check_condition_result; + } else if (inj_dif && (0 == errsts)) { + mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, 1); + errsts = illegal_condition_result; + } else if (inj_dix && (0 == errsts)) { + mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, 1); + errsts = illegal_condition_result; } break; case MODE_SENSE: @@ -2982,6 +3366,7 @@ static int sdebug_driver_probe(struct device * dev) int error = 0; struct sdebug_host_info *sdbg_host; struct Scsi_Host *hpnt; + int host_prot; sdbg_host = to_sdebug_host(dev); @@ -3000,6 +3385,50 @@ static int sdebug_driver_probe(struct device * dev) hpnt->max_id = scsi_debug_num_tgts; hpnt->max_lun = SAM2_WLUN_REPORT_LUNS; /* = scsi_debug_max_luns; */ + host_prot = 0; + + switch (scsi_debug_dif) { + + case SD_DIF_TYPE1_PROTECTION: + host_prot = SHOST_DIF_TYPE1_PROTECTION; + if (scsi_debug_dix) + host_prot |= SHOST_DIX_TYPE1_PROTECTION; + break; + + case SD_DIF_TYPE2_PROTECTION: + host_prot = SHOST_DIF_TYPE2_PROTECTION; + if (scsi_debug_dix) + host_prot |= SHOST_DIX_TYPE2_PROTECTION; + break; + + case SD_DIF_TYPE3_PROTECTION: + host_prot = SHOST_DIF_TYPE3_PROTECTION; + if (scsi_debug_dix) + host_prot |= SHOST_DIX_TYPE3_PROTECTION; + break; + + default: + if (scsi_debug_dix) + host_prot |= SHOST_DIX_TYPE0_PROTECTION; + break; + } + + scsi_host_set_prot(hpnt, host_prot); + + printk(KERN_INFO "scsi_debug: host protection%s%s%s%s%s%s%s\n", + (host_prot & SHOST_DIF_TYPE1_PROTECTION) ? " DIF1" : "", + (host_prot & SHOST_DIF_TYPE2_PROTECTION) ? " DIF2" : "", + (host_prot & SHOST_DIF_TYPE3_PROTECTION) ? " DIF3" : "", + (host_prot & SHOST_DIX_TYPE0_PROTECTION) ? " DIX0" : "", + (host_prot & SHOST_DIX_TYPE1_PROTECTION) ? " DIX1" : "", + (host_prot & SHOST_DIX_TYPE2_PROTECTION) ? " DIX2" : "", + (host_prot & SHOST_DIX_TYPE3_PROTECTION) ? " DIX3" : ""); + + if (scsi_debug_guard == 1) + scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_IP); + else + scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_CRC); + error = scsi_add_host(hpnt, &sdbg_host->dev); if (error) { printk(KERN_ERR "%s: scsi_add_host failed\n", __func__); -- cgit v1.2.3-18-g5258 From d0ace3c5eedff92333de0a5dd00cfb78a18b87cd Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 12 Jan 2009 10:53:04 -0800 Subject: [SCSI] scsi_debug: needs CRC_T10DIF Fix scsi_debug build error: drivers/built-in.o: In function `resp_read': scsi_debug.c:(.text+0x21379a): undefined reference to `crc_t10dif' drivers/built-in.o: In function `resp_write': scsi_debug.c:(.text+0x213fca): undefined reference to `crc_t10dif' Signed-off-by: Randy Dunlap Signed-off-by: James Bottomley --- drivers/scsi/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 256c7bec7bd..8f0a5cbd632 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -1535,6 +1535,7 @@ config SCSI_NSP32 config SCSI_DEBUG tristate "SCSI debugging host simulator" depends on SCSI + select CRC_T10DIF help This is a host adapter simulator that can simulate multiple hosts each with multiple dummy SCSI devices (disks). It defaults to one -- cgit v1.2.3-18-g5258 From d943aeebc5194f3c6a81fb139ba406040324e4f3 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 12 Jan 2009 10:50:58 -0800 Subject: [SCSI] libfc: needs CRC32 libfc uses crc32 functions, so cause it to be built via select: drivers/built-in.o: In function `fc_frame_crc_check': (.text+0x75dae): undefined reference to `crc32_le' drivers/built-in.o: In function `fc_fcp_recv': fc_fcp.c:(.text+0x7b919): undefined reference to `crc32_le' fc_fcp.c:(.text+0x7b9d5): undefined reference to `crc32_le' fc_fcp.c:(.text+0x7ba54): undefined reference to `crc32_le' Signed-off-by: Randy Dunlap Acked-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 8f0a5cbd632..898c2b59592 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -608,6 +608,7 @@ config SCSI_FLASHPOINT config LIBFC tristate "LibFC module" select SCSI_FC_ATTRS + select CRC32 ---help--- Fibre Channel library module -- cgit v1.2.3-18-g5258 From 6e7490c73d8cc48e7084ac976c8be7bbaf530acf Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Sun, 11 Jan 2009 17:38:12 +0900 Subject: [SCSI] libfc: fix compile warning I got the following warnings on IA64: drivers/scsi/libfc/fc_lport.c: In function 'fc_lport_recv_flogi_req': drivers/scsi/libfc/fc_lport.c:788: warning: format '%llx' expects type 'long long unsigned int', but argument 3 has type 'u64' drivers/scsi/libfc/fc_lport.c:792: warning: format '%llx' expects type 'long long unsigned int', but argument 3 has type 'u64' scsi/libfc/fc_rport.c: In function 'fc_rport_recv_plogi_req': /home/fujita/git/linux-2.6/drivers/scsi/libfc/fc_rport.c:968: warning: format '%llx' expects type 'long long unsigned int', but argument 4 has type 'u64' Signed-off-by: FUJITA Tomonori Cc: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_lport.c | 5 +++-- drivers/scsi/libfc/fc_rport.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 2ae50a1188e..7ef44501ecc 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -762,10 +762,11 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in, remote_wwpn = get_unaligned_be64(&flp->fl_wwpn); if (remote_wwpn == lport->wwpn) { FC_DBG("FLOGI from port with same WWPN %llx " - "possible configuration error\n", remote_wwpn); + "possible configuration error\n", + (unsigned long long)remote_wwpn); goto out; } - FC_DBG("FLOGI from port WWPN %llx\n", remote_wwpn); + FC_DBG("FLOGI from port WWPN %llx\n", (unsigned long long)remote_wwpn); /* * XXX what is the right thing to do for FIDs? diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index dae65133a83..0472bb73221 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -988,7 +988,7 @@ static void fc_rport_recv_plogi_req(struct fc_rport *rport, switch (rdata->rp_state) { case RPORT_ST_INIT: FC_DEBUG_RPORT("incoming PLOGI from %6x wwpn %llx state INIT " - "- reject\n", sid, wwpn); + "- reject\n", sid, (unsigned long long)wwpn); reject = ELS_RJT_UNSUP; break; case RPORT_ST_PLOGI: -- cgit v1.2.3-18-g5258 From 71fa7421822a251fc3e9ffb54653395b6b964309 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 11 Jan 2009 10:38:59 +0100 Subject: [SCSI] lpfc: constify virtual function tables Signed-off-by: Jan Engelhardt Acked-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_debugfs.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index b615eda361d..81cdcf46c47 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c @@ -1132,7 +1132,7 @@ lpfc_debugfs_dumpDataDif_release(struct inode *inode, struct file *file) } #undef lpfc_debugfs_op_disc_trc -static struct file_operations lpfc_debugfs_op_disc_trc = { +static const struct file_operations lpfc_debugfs_op_disc_trc = { .owner = THIS_MODULE, .open = lpfc_debugfs_disc_trc_open, .llseek = lpfc_debugfs_lseek, @@ -1141,7 +1141,7 @@ static struct file_operations lpfc_debugfs_op_disc_trc = { }; #undef lpfc_debugfs_op_nodelist -static struct file_operations lpfc_debugfs_op_nodelist = { +static const struct file_operations lpfc_debugfs_op_nodelist = { .owner = THIS_MODULE, .open = lpfc_debugfs_nodelist_open, .llseek = lpfc_debugfs_lseek, @@ -1150,7 +1150,7 @@ static struct file_operations lpfc_debugfs_op_nodelist = { }; #undef lpfc_debugfs_op_hbqinfo -static struct file_operations lpfc_debugfs_op_hbqinfo = { +static const struct file_operations lpfc_debugfs_op_hbqinfo = { .owner = THIS_MODULE, .open = lpfc_debugfs_hbqinfo_open, .llseek = lpfc_debugfs_lseek, @@ -1159,7 +1159,7 @@ static struct file_operations lpfc_debugfs_op_hbqinfo = { }; #undef lpfc_debugfs_op_dumpHBASlim -static struct file_operations lpfc_debugfs_op_dumpHBASlim = { +static const struct file_operations lpfc_debugfs_op_dumpHBASlim = { .owner = THIS_MODULE, .open = lpfc_debugfs_dumpHBASlim_open, .llseek = lpfc_debugfs_lseek, @@ -1168,7 +1168,7 @@ static struct file_operations lpfc_debugfs_op_dumpHBASlim = { }; #undef lpfc_debugfs_op_dumpHostSlim -static struct file_operations lpfc_debugfs_op_dumpHostSlim = { +static const struct file_operations lpfc_debugfs_op_dumpHostSlim = { .owner = THIS_MODULE, .open = lpfc_debugfs_dumpHostSlim_open, .llseek = lpfc_debugfs_lseek, @@ -1177,7 +1177,7 @@ static struct file_operations lpfc_debugfs_op_dumpHostSlim = { }; #undef lpfc_debugfs_op_dumpData -static struct file_operations lpfc_debugfs_op_dumpData = { +static const struct file_operations lpfc_debugfs_op_dumpData = { .owner = THIS_MODULE, .open = lpfc_debugfs_dumpData_open, .llseek = lpfc_debugfs_lseek, @@ -1187,7 +1187,7 @@ static struct file_operations lpfc_debugfs_op_dumpData = { }; #undef lpfc_debugfs_op_dumpDif -static struct file_operations lpfc_debugfs_op_dumpDif = { +static const struct file_operations lpfc_debugfs_op_dumpDif = { .owner = THIS_MODULE, .open = lpfc_debugfs_dumpDif_open, .llseek = lpfc_debugfs_lseek, @@ -1197,7 +1197,7 @@ static struct file_operations lpfc_debugfs_op_dumpDif = { }; #undef lpfc_debugfs_op_slow_ring_trc -static struct file_operations lpfc_debugfs_op_slow_ring_trc = { +static const struct file_operations lpfc_debugfs_op_slow_ring_trc = { .owner = THIS_MODULE, .open = lpfc_debugfs_slow_ring_trc_open, .llseek = lpfc_debugfs_lseek, -- cgit v1.2.3-18-g5258 From 5ef074161b5bcd84acfe19f0ecd72b74765d8770 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Wed, 14 Jan 2009 11:14:32 -0800 Subject: [SCSI] Improve SCSI_LOGGING Kconfig entry The Kconfig entry for SCSI_LOGGING refers the reader to drivers/scsi/scsi.c, but I didn't find any useful information there. There is certainly logging code in that file, but the logging types and logging levels are described in drivers/scsi/scsi_logging.h. Also, the procfs file referred to in the section is incorrect. It should be /proc/sys/dev/scsi/logging_level and not /proc/scsi/scsi. Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/Kconfig | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 898c2b59592..601c2a8ec24 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -224,14 +224,15 @@ config SCSI_LOGGING can enable logging by saying Y to "/proc file system support" and "Sysctl support" below and executing the command - echo "scsi log token [level]" > /proc/scsi/scsi + echo > /proc/sys/dev/scsi/logging_level - at boot time after the /proc file system has been mounted. + where is a four byte value representing the logging type + and logging level for each type of logging selected. - There are a number of things that can be used for 'token' (you can - find them in the source: ), and this - allows you to select the types of information you want, and the - level allows you to select the level of verbosity. + There are a number of logging types and you can find them in the + source at . The logging levels + are also described in that file and they determine the verbosity of + the logging for each logging type. If you say N here, it may be harder to track down some types of SCSI problems. If you say Y here your kernel will be somewhat larger, but -- cgit v1.2.3-18-g5258 From 49799fee82b4f78c45b1926be24e45b5cf667083 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Thu, 15 Jan 2009 17:13:36 +0200 Subject: [SCSI] sym53c8xx: Keep transfer negotiations valid (The patch updated based on testing and comments from Tony Battersby.) Change the sym53c8xx_2 driver negotiation logic so that the driver will tolerate better device removals. Negotiation message(s) will be sent with every INQUIRY and REQUEST SENSE command, and whenever there is a change in goals or when the device reports check condition. The patch was made specifically to address the case where you hotswap the disk using remove-single-device/add-single-device commands through /proc/scsi/scsi. Without the patch the driver keeps using old transfer parameters even though the target is reset and reports check condition, so the data transfer of the very first INQUIRY will fail. Signed-off-by: Aaro Koskinen Tested-by: Tony Battersby Signed-off-by: James Bottomley --- drivers/scsi/sym53c8xx_2/sym_hipd.c | 35 ++++++++++++++++++++++++++--------- drivers/scsi/sym53c8xx_2/sym_hipd.h | 1 + 2 files changed, 27 insertions(+), 9 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index 98df1651404..fe6359d4e1e 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -1433,13 +1433,12 @@ static int sym_prepare_nego(struct sym_hcb *np, struct sym_ccb *cp, u_char *msgp * Many devices implement PPR in a buggy way, so only use it if we * really want to. */ - if (goal->offset && - (goal->iu || goal->dt || goal->qas || (goal->period < 0xa))) { + if (goal->renego == NS_PPR || (goal->offset && + (goal->iu || goal->dt || goal->qas || (goal->period < 0xa)))) { nego = NS_PPR; - } else if (spi_width(starget) != goal->width) { + } else if (goal->renego == NS_WIDE || goal->width) { nego = NS_WIDE; - } else if (spi_period(starget) != goal->period || - spi_offset(starget) != goal->offset) { + } else if (goal->renego == NS_SYNC || goal->offset) { nego = NS_SYNC; } else { goal->check_nego = 0; @@ -2049,11 +2048,13 @@ static void sym_setwide(struct sym_hcb *np, int target, u_char wide) struct sym_tcb *tp = &np->target[target]; struct scsi_target *starget = tp->starget; - if (spi_width(starget) == wide) - return; - sym_settrans(np, target, 0, 0, 0, wide, 0, 0); + if (wide) + tp->tgoal.renego = NS_WIDE; + else + tp->tgoal.renego = 0; + tp->tgoal.check_nego = 0; tp->tgoal.width = wide; spi_offset(starget) = 0; spi_period(starget) = 0; @@ -2080,6 +2081,12 @@ sym_setsync(struct sym_hcb *np, int target, sym_settrans(np, target, 0, ofs, per, wide, div, fak); + if (wide) + tp->tgoal.renego = NS_WIDE; + else if (ofs) + tp->tgoal.renego = NS_SYNC; + else + tp->tgoal.renego = 0; spi_period(starget) = per; spi_offset(starget) = ofs; spi_iu(starget) = spi_dt(starget) = spi_qas(starget) = 0; @@ -2106,6 +2113,10 @@ sym_setpprot(struct sym_hcb *np, int target, u_char opts, u_char ofs, sym_settrans(np, target, opts, ofs, per, wide, div, fak); + if (wide || ofs) + tp->tgoal.renego = NS_PPR; + else + tp->tgoal.renego = 0; spi_width(starget) = tp->tgoal.width = wide; spi_period(starget) = tp->tgoal.period = per; spi_offset(starget) = tp->tgoal.offset = ofs; @@ -3516,6 +3527,7 @@ static void sym_sir_task_recovery(struct sym_hcb *np, int num) spi_dt(starget) = 0; spi_qas(starget) = 0; tp->tgoal.check_nego = 1; + tp->tgoal.renego = 0; } /* @@ -5135,9 +5147,14 @@ int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *cmd, struct sym_ccb * /* * Build a negotiation message if needed. * (nego_status is filled by sym_prepare_nego()) + * + * Always negotiate on INQUIRY and REQUEST SENSE. + * */ cp->nego_status = 0; - if (tp->tgoal.check_nego && !tp->nego_cp && lp) { + if ((tp->tgoal.check_nego || + cmd->cmnd[0] == INQUIRY || cmd->cmnd[0] == REQUEST_SENSE) && + !tp->nego_cp && lp) { msglen += sym_prepare_nego(np, cp, msgptr + msglen); } diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h index ad078805e62..233a3d0b2ce 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.h +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h @@ -354,6 +354,7 @@ struct sym_trans { unsigned int dt:1; unsigned int qas:1; unsigned int check_nego:1; + unsigned int renego:2; }; /* -- cgit v1.2.3-18-g5258 From 951948a397e3ddc96658efd648b9d66622965b19 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Thu, 15 Jan 2009 16:51:48 +0100 Subject: [SCSI] scsi_transport_fc: Add missing parenthesis to Point-To-Point description Fix typo by adding closing parenthesis. Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_fc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 5f77417ed58..2df75295921 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -95,7 +95,7 @@ static struct { { FC_PORTTYPE_NPORT, "NPort (fabric via point-to-point)" }, { FC_PORTTYPE_NLPORT, "NLPort (fabric via loop)" }, { FC_PORTTYPE_LPORT, "LPort (private loop)" }, - { FC_PORTTYPE_PTP, "Point-To-Point (direct nport connection" }, + { FC_PORTTYPE_PTP, "Point-To-Point (direct nport connection)" }, { FC_PORTTYPE_NPIV, "NPIV VPORT" }, }; fc_enum_name_search(port_type, fc_port_type, fc_port_type_names) -- cgit v1.2.3-18-g5258 From 5a9ef25b14d39b8413364df12cb8d9bb7a673a32 Mon Sep 17 00:00:00 2001 From: Wayne Boyer Date: Fri, 23 Jan 2009 09:17:35 -0800 Subject: [SCSI] ipr: add MSI support Enable MSI if available/supported. Signed-off-by: Wayne Boyer Acked-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 7 +++++++ drivers/scsi/ipr.h | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 07829009a8b..3f47cd1c46e 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -7147,6 +7147,7 @@ static void ipr_free_all_resources(struct ipr_ioa_cfg *ioa_cfg) ENTER; free_irq(pdev->irq, ioa_cfg); + pci_disable_msi(pdev); iounmap(ioa_cfg->hdw_dma_regs); pci_release_regions(pdev); ipr_free_mem(ioa_cfg); @@ -7432,6 +7433,11 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev, goto out; } + if (!(rc = pci_enable_msi(pdev))) + dev_info(&pdev->dev, "MSI enabled\n"); + else if (ipr_debug) + dev_info(&pdev->dev, "Cannot enable MSI\n"); + dev_info(&pdev->dev, "Found IOA with IRQ: %d\n", pdev->irq); host = scsi_host_alloc(&driver_template, sizeof(*ioa_cfg)); @@ -7574,6 +7580,7 @@ out_release_regions: out_scsi_host_put: scsi_host_put(host); out_disable: + pci_disable_msi(pdev); pci_disable_device(pdev); goto out; } diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index 8f872f816fe..79a3ae4fb2c 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -37,8 +37,8 @@ /* * Literals */ -#define IPR_DRIVER_VERSION "2.4.1" -#define IPR_DRIVER_DATE "(April 24, 2007)" +#define IPR_DRIVER_VERSION "2.4.2" +#define IPR_DRIVER_DATE "(January 21, 2009)" /* * IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding -- cgit v1.2.3-18-g5258 From 1c9fbafc8c629c89183d6dccec67a8415513b0d1 Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Sun, 4 Jan 2009 03:14:11 -0500 Subject: [SCSI] Remove SUGGEST flags The SUGGEST_* flags in the SCSI command result have been out of fashion for a while and we don't actually use them in the error handling. Remove the remaining occurrences. Signed-off-by: Martin K. Petersen Signed-off-by: James Bottomley --- drivers/scsi/constants.c | 13 +++---------- drivers/scsi/hptiop.c | 3 +-- drivers/scsi/ips.c | 3 +-- drivers/scsi/libfc/fc_fcp.c | 6 +++--- drivers/scsi/lpfc/lpfc_scsi.c | 6 +++--- drivers/scsi/st.c | 6 +++--- 6 files changed, 14 insertions(+), 23 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index 4003deefb7d..e79e18101f8 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -1373,21 +1373,14 @@ static const char * const driverbyte_table[]={ "DRIVER_INVALID", "DRIVER_TIMEOUT", "DRIVER_HARD", "DRIVER_SENSE"}; #define NUM_DRIVERBYTE_STRS ARRAY_SIZE(driverbyte_table) -static const char * const driversuggest_table[]={"SUGGEST_OK", -"SUGGEST_RETRY", "SUGGEST_ABORT", "SUGGEST_REMAP", "SUGGEST_DIE", -"SUGGEST_5", "SUGGEST_6", "SUGGEST_7", "SUGGEST_SENSE"}; -#define NUM_SUGGEST_STRS ARRAY_SIZE(driversuggest_table) - void scsi_show_result(int result) { int hb = host_byte(result); - int db = (driver_byte(result) & DRIVER_MASK); - int su = ((driver_byte(result) & SUGGEST_MASK) >> 4); + int db = driver_byte(result); - printk("Result: hostbyte=%s driverbyte=%s,%s\n", + printk("Result: hostbyte=%s driverbyte=%s\n", (hb < NUM_HOSTBYTE_STRS ? hostbyte_table[hb] : "invalid"), - (db < NUM_DRIVERBYTE_STRS ? driverbyte_table[db] : "invalid"), - (su < NUM_SUGGEST_STRS ? driversuggest_table[su] : "invalid")); + (db < NUM_DRIVERBYTE_STRS ? driverbyte_table[db] : "invalid")); } #else diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c index 34be88d7afa..af1f0af0c5a 100644 --- a/drivers/scsi/hptiop.c +++ b/drivers/scsi/hptiop.c @@ -580,8 +580,7 @@ static void hptiop_finish_scsi_req(struct hptiop_hba *hba, u32 tag, break; default: - scp->result = ((DRIVER_INVALID|SUGGEST_ABORT)<<24) | - (DID_ABORT<<16); + scp->result = DRIVER_INVALID << 24 | DID_ABORT << 16; break; } diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index ef683f0d2b5..457d76a4cfe 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -1004,8 +1004,7 @@ static int __ips_eh_reset(struct scsi_cmnd *SC) DEBUG_VAR(1, "(%s%d) Failing active commands", ips_name, ha->host_num); while ((scb = ips_removeq_scb_head(&ha->scb_activelist))) { - scb->scsi_cmd->result = - (DID_RESET << 16) | (SUGGEST_RETRY << 24); + scb->scsi_cmd->result = DID_RESET << 16; scb->scsi_cmd->scsi_done(scb->scsi_cmd); ips_freescb(ha, scb); } diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 2a631d7dbce..a070e571243 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -259,7 +259,7 @@ static void fc_fcp_retry_cmd(struct fc_fcp_pkt *fsp) } fsp->state &= ~FC_SRB_ABORT_PENDING; - fsp->io_status = SUGGEST_RETRY << 24; + fsp->io_status = 0; fsp->status_code = FC_ERROR; fc_fcp_complete_locked(fsp); } @@ -859,7 +859,7 @@ static void fc_fcp_complete_locked(struct fc_fcp_pkt *fsp) (!(fsp->scsi_comp_flags & FCP_RESID_UNDER) || fsp->xfer_len < fsp->data_len - fsp->scsi_resid)) { fsp->status_code = FC_DATA_UNDRUN; - fsp->io_status = SUGGEST_RETRY << 24; + fsp->io_status = 0; } } @@ -1267,7 +1267,7 @@ static void fc_fcp_rec(struct fc_fcp_pkt *fsp) rp = rport->dd_data; if (!fsp->seq_ptr || rp->rp_state != RPORT_ST_READY) { fsp->status_code = FC_HRD_ERROR; - fsp->io_status = SUGGEST_RETRY << 24; + fsp->io_status = 0; fc_fcp_complete_locked(fsp); return; } diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index b103b6ed497..b1bd3fc7bae 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -1357,7 +1357,7 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd, scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, 0x10, 0x1); - cmd->result = (DRIVER_SENSE|SUGGEST_DIE) << 24 + cmd->result = DRIVER_SENSE << 24 | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); phba->bg_guard_err_cnt++; printk(KERN_ERR "BLKGRD: guard_tag error\n"); @@ -1368,7 +1368,7 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd, scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, 0x10, 0x3); - cmd->result = (DRIVER_SENSE|SUGGEST_DIE) << 24 + cmd->result = DRIVER_SENSE << 24 | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); phba->bg_reftag_err_cnt++; @@ -1380,7 +1380,7 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd, scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, 0x10, 0x2); - cmd->result = (DRIVER_SENSE|SUGGEST_DIE) << 24 + cmd->result = DRIVER_SENSE << 24 | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); phba->bg_apptag_err_cnt++; diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index c6f19ee8f2c..eb24efea8f1 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -374,9 +374,9 @@ static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt) if (!debugging) { /* Abnormal conditions for tape */ if (!cmdstatp->have_sense) printk(KERN_WARNING - "%s: Error %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n", - name, result, suggestion(result), - driver_byte(result) & DRIVER_MASK, host_byte(result)); + "%s: Error %x (driver bt 0x%x, host bt 0x%x).\n", + name, result, driver_byte(result), + host_byte(result)); else if (cmdstatp->have_sense && scode != NO_SENSE && scode != RECOVERED_ERROR && -- cgit v1.2.3-18-g5258 From a4976d688650b4593831fbffbb217f2d916b1aa0 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sun, 25 Jan 2009 15:09:42 -0600 Subject: [SCSI] osst: Remove SUGGEST flags Fix up remaining bit of SUGGEST flag removal done by patch commit 0f10274300857d98ea5ea4c800c561a9ad9ac89f Author: Martin K. Petersen Date: Sun Jan 4 03:14:11 2009 -0500 [SCSI] Remove SUGGEST flags Signed-off-by: James Bottomley --- drivers/scsi/osst.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index 0ea78d9a37d..8f21cbbd7aa 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -280,8 +280,8 @@ static int osst_chk_result(struct osst_tape * STp, struct osst_request * SRpnt) static int notyetprinted = 1; printk(KERN_WARNING - "%s:W: Warning %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n", - name, result, suggestion(result), driver_byte(result) & DRIVER_MASK, + "%s:W: Warning %x (driver bt 0x%x, host bt 0x%x).\n", + name, result, driver_byte(result), host_byte(result)); if (notyetprinted) { notyetprinted = 0; -- cgit v1.2.3-18-g5258 From dd48ebf7ca4a6e60e6787e443f5316724309865b Mon Sep 17 00:00:00 2001 From: Ed Lin - PTU Date: Mon, 26 Jan 2009 02:40:11 -0800 Subject: [SCSI] stex: Fix for potential invalid response The interrupt routine is good for normal cases. However, if the firmware is abnormal and returns an invalid response, the driver may reuse a ccb structure that has already been handled. This may cause problem. Fix this by setting the req member to NULL. Next time we know the response is invalid and handle accordingly if req is NULL. Signed-off-by: Ed Lin Signed-off-by: James Bottomley --- drivers/scsi/stex.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c index a3a18ad7312..6129db4a6a3 100644 --- a/drivers/scsi/stex.c +++ b/drivers/scsi/stex.c @@ -746,6 +746,7 @@ static void stex_mu_intr(struct st_hba *hba, u32 doorbell) stex_copy_data(ccb, resp, size); } + ccb->req = NULL; ccb->srb_status = resp->srb_status; ccb->scsi_status = resp->scsi_status; -- cgit v1.2.3-18-g5258 From 62e5b3d850f76190633e5a3cc8d6cc611ef96cfc Mon Sep 17 00:00:00 2001 From: Ed Lin - PTU Date: Mon, 26 Jan 2009 02:40:29 -0800 Subject: [SCSI] stex: Add new device id Add new device id for controller type st_seq. Signed-off-by: Ed Lin Signed-off-by: James Bottomley --- drivers/scsi/stex.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c index 6129db4a6a3..12dc0d176f3 100644 --- a/drivers/scsi/stex.c +++ b/drivers/scsi/stex.c @@ -119,6 +119,7 @@ enum { st_vsc = 1, st_vsc1 = 2, st_yosemite = 3, + st_seq = 4, PASSTHRU_REQ_TYPE = 0x00000001, PASSTHRU_REQ_NO_WAKEUP = 0x00000100, @@ -1127,7 +1128,7 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id) hba->cardtype = (unsigned int) id->driver_data; if (hba->cardtype == st_vsc && (pdev->subsystem_device & 0xf) == 0x1) hba->cardtype = st_vsc1; - hba->dma_size = (hba->cardtype == st_vsc1) ? + hba->dma_size = (hba->cardtype == st_vsc1 || hba->cardtype == st_seq) ? (STEX_BUFFER_SIZE + ST_ADDITIONAL_MEM) : (STEX_BUFFER_SIZE); hba->dma_mem = dma_alloc_coherent(&pdev->dev, hba->dma_size, &hba->dma_handle, GFP_KERNEL); @@ -1150,7 +1151,7 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id) host->max_lun = 128; host->max_id = 1 + 1; } else { - /* st_vsc and st_vsc1 */ + /* st_vsc , st_vsc1 and st_seq */ host->max_lun = 1; host->max_id = 128 + 1; } @@ -1312,6 +1313,9 @@ static struct pci_device_id stex_pci_tbl[] = { st_yosemite }, /* SuperTrak EX8654 */ { 0x105a, 0x8650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_yosemite }, /* generic st_yosemite */ + + /* st_seq */ + { 0x105a, 0x3360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_seq }, { } /* terminate list */ }; MODULE_DEVICE_TABLE(pci, stex_pci_tbl); -- cgit v1.2.3-18-g5258 From e8a091b36cd50faa1276e6934edcc3e8b8e83b5a Mon Sep 17 00:00:00 2001 From: Ed Lin - PTU Date: Mon, 26 Jan 2009 02:40:50 -0800 Subject: [SCSI] stex: Fix for controller type st_yosemite This is the fix for controller type st_yosemite, including - max_lun is 256 (backward compatible) - remove unneeded special handling of INQUIRY - remove unnecessary listing of sub device ids Signed-off-by: Ed Lin Signed-off-by: James Bottomley --- drivers/scsi/stex.c | 64 +++-------------------------------------------------- 1 file changed, 3 insertions(+), 61 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c index 12dc0d176f3..425a61c79bb 100644 --- a/drivers/scsi/stex.c +++ b/drivers/scsi/stex.c @@ -153,35 +153,6 @@ enum { ST_ADDITIONAL_MEM = 0x200000, }; -/* SCSI inquiry data */ -typedef struct st_inq { - u8 DeviceType :5; - u8 DeviceTypeQualifier :3; - u8 DeviceTypeModifier :7; - u8 RemovableMedia :1; - u8 Versions; - u8 ResponseDataFormat :4; - u8 HiSupport :1; - u8 NormACA :1; - u8 ReservedBit :1; - u8 AERC :1; - u8 AdditionalLength; - u8 Reserved[2]; - u8 SoftReset :1; - u8 CommandQueue :1; - u8 Reserved2 :1; - u8 LinkedCommands :1; - u8 Synchronous :1; - u8 Wide16Bit :1; - u8 Wide32Bit :1; - u8 RelativeAddressing :1; - u8 VendorId[8]; - u8 ProductId[16]; - u8 ProductRevisionLevel[4]; - u8 VendorSpecific[20]; - u8 Reserved3[40]; -} ST_INQ; - struct st_sgitem { u8 ctrl; /* SG_CF_xxx */ u8 reserved[3]; @@ -285,7 +256,7 @@ struct st_drvver { #define MU_REQ_BUFFER_SIZE (MU_REQ_COUNT * sizeof(struct req_msg)) #define MU_STATUS_BUFFER_SIZE (MU_STATUS_COUNT * sizeof(struct status_msg)) #define MU_BUFFER_SIZE (MU_REQ_BUFFER_SIZE + MU_STATUS_BUFFER_SIZE) -#define STEX_EXTRA_SIZE max(sizeof(struct st_frame), sizeof(ST_INQ)) +#define STEX_EXTRA_SIZE sizeof(struct st_frame) #define STEX_BUFFER_SIZE (MU_BUFFER_SIZE + STEX_EXTRA_SIZE) struct st_ccb { @@ -662,24 +633,6 @@ static void stex_ys_commands(struct st_hba *hba, resp->scsi_status != SAM_STAT_CHECK_CONDITION) { scsi_set_resid(ccb->cmd, scsi_bufflen(ccb->cmd) - le32_to_cpu(*(__le32 *)&resp->variable[0])); - return; - } - - if (resp->srb_status != 0) - return; - - /* determine inquiry command status by DeviceTypeQualifier */ - if (ccb->cmd->cmnd[0] == INQUIRY && - resp->scsi_status == SAM_STAT_GOOD) { - ST_INQ *inq_data; - - scsi_sg_copy_to_buffer(ccb->cmd, hba->copy_buffer, - STEX_EXTRA_SIZE); - inq_data = (ST_INQ *)hba->copy_buffer; - if (inq_data->DeviceTypeQualifier != 0) - ccb->srb_status = SRB_STATUS_SELECTION_TIMEOUT; - else - ccb->srb_status = SRB_STATUS_SUCCESS; } } @@ -1148,7 +1101,7 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id) host->max_lun = 8; host->max_id = 16 + 1; } else if (hba->cardtype == st_yosemite) { - host->max_lun = 128; + host->max_lun = 256; host->max_id = 1 + 1; } else { /* st_vsc , st_vsc1 and st_seq */ @@ -1301,18 +1254,7 @@ static struct pci_device_id stex_pci_tbl[] = { { 0x105a, 0x7250, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_vsc }, /* st_yosemite */ - { 0x105a, 0x8650, PCI_ANY_ID, 0x4600, 0, 0, - st_yosemite }, /* SuperTrak EX4650 */ - { 0x105a, 0x8650, PCI_ANY_ID, 0x4610, 0, 0, - st_yosemite }, /* SuperTrak EX4650o */ - { 0x105a, 0x8650, PCI_ANY_ID, 0x8600, 0, 0, - st_yosemite }, /* SuperTrak EX8650EL */ - { 0x105a, 0x8650, PCI_ANY_ID, 0x8601, 0, 0, - st_yosemite }, /* SuperTrak EX8650 */ - { 0x105a, 0x8650, PCI_ANY_ID, 0x8602, 0, 0, - st_yosemite }, /* SuperTrak EX8654 */ - { 0x105a, 0x8650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - st_yosemite }, /* generic st_yosemite */ + { 0x105a, 0x8650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_yosemite }, /* st_seq */ { 0x105a, 0x3360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_seq }, -- cgit v1.2.3-18-g5258 From 7cfe99a526b92e30df19673b3533f827bbe93821 Mon Sep 17 00:00:00 2001 From: Ed Lin - PTU Date: Mon, 26 Jan 2009 02:41:53 -0800 Subject: [SCSI] stex: Small fixes Some small fixes, including: - add data direction in req_msg because new firmware version may require this (backward compatible) - change internal timeout value - change judgment of type st_vsc1 - blank line handling, etc. Signed-off-by: Ed Lin Signed-off-by: James Bottomley --- drivers/scsi/stex.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c index 425a61c79bb..c1a79c3f471 100644 --- a/drivers/scsi/stex.c +++ b/drivers/scsi/stex.c @@ -103,7 +103,7 @@ enum { MU_REQ_COUNT = (MU_MAX_REQUEST + 1), MU_STATUS_COUNT = (MU_MAX_REQUEST + 1), - STEX_CDB_LENGTH = MAX_COMMAND_SIZE, + STEX_CDB_LENGTH = 16, REQ_VARIABLE_LEN = 1024, STATUS_VAR_LEN = 128, ST_CAN_QUEUE = MU_MAX_REQUEST, @@ -114,6 +114,9 @@ enum { SG_CF_EOT = 0x80, /* end of table */ SG_CF_64B = 0x40, /* 64 bit item */ SG_CF_HOST = 0x20, /* sg in host memory */ + MSG_DATA_DIR_ND = 0, + MSG_DATA_DIR_IN = 1, + MSG_DATA_DIR_OUT = 2, st_shasta = 0, st_vsc = 1, @@ -123,7 +126,7 @@ enum { PASSTHRU_REQ_TYPE = 0x00000001, PASSTHRU_REQ_NO_WAKEUP = 0x00000100, - ST_INTERNAL_TIMEOUT = 30, + ST_INTERNAL_TIMEOUT = 180, ST_TO_CMD = 0, ST_FROM_CMD = 1, @@ -194,7 +197,7 @@ struct req_msg { u8 target; u8 task_attr; u8 task_manage; - u8 prd_entry; + u8 data_dir; u8 payload_sz; /* payload size in 4-byte, not used */ u8 cdb[STEX_CDB_LENGTH]; u8 variable[REQ_VARIABLE_LEN]; @@ -318,8 +321,8 @@ MODULE_VERSION(ST_DRIVER_VERSION); static void stex_gettime(__le32 *time) { struct timeval tv; - do_gettimeofday(&tv); + do_gettimeofday(&tv); *time = cpu_to_le32(tv.tv_sec & 0xffffffff); *(time + 1) = cpu_to_le32((tv.tv_sec >> 16) >> 16); } @@ -340,7 +343,7 @@ static void stex_invalid_field(struct scsi_cmnd *cmd, { cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; - /* "Invalid field in cbd" */ + /* "Invalid field in cdb" */ scsi_build_sense_buffer(0, cmd->sense_buffer, ILLEGAL_REQUEST, 0x24, 0x0); done(cmd); @@ -469,6 +472,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *)) unsigned int id,lun; struct req_msg *req; u16 tag; + host = cmd->device->host; id = cmd->device->id; lun = cmd->device->lun; @@ -480,6 +484,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *)) static char ms10_caching_page[12] = { 0, 0x12, 0, 0, 0, 0, 0, 0, 0x8, 0xa, 0x4, 0 };