SCSI: Disable WRITE SAME for RAID and virtual host adapter drivers
authorMartin K. Petersen <martin.petersen@oracle.com>
Wed, 23 Oct 2013 10:25:40 +0000 (06:25 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 12 Dec 2013 06:37:55 +0000 (22:37 -0800)
commit 54b2b50c20a61b51199bedb6e5d2f8ec2568fb43 upstream.

Some host adapters do not pass commands through to the target disk
directly. Instead they provide an emulated target which may or may not
accurately report its capabilities. In some cases the physical device
characteristics are reported even when the host adapter is processing
commands on the device's behalf. This can lead to adapter firmware hangs
or excessive I/O errors.

This patch disables WRITE SAME for devices connected to host adapters
that provide an emulated target. Driver writers can disable WRITE SAME
by setting the no_write_same flag in the host adapter template.

[jejb: fix up rejections due to eh_deadline patch]
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
19 files changed:
drivers/ata/libata-scsi.c
drivers/firewire/sbp2.c
drivers/scsi/3w-9xxx.c
drivers/scsi/3w-sas.c
drivers/scsi/3w-xxxx.c
drivers/scsi/aacraid/linit.c
drivers/scsi/arcmsr/arcmsr_hba.c
drivers/scsi/gdth.c
drivers/scsi/hosts.c
drivers/scsi/hpsa.c
drivers/scsi/ipr.c
drivers/scsi/ips.c
drivers/scsi/megaraid.c
drivers/scsi/megaraid/megaraid_mbox.c
drivers/scsi/megaraid/megaraid_sas_base.c
drivers/scsi/pmcraid.c
drivers/scsi/sd.c
drivers/scsi/storvsc_drv.c
include/scsi/scsi_host.h

index db6dfcfa3e2ee932190069290814f2a71bc8f3f6..ab58556d347c19120c9724389583c2ae67a2d81e 100644 (file)
@@ -3625,6 +3625,7 @@ int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht)
                shost->max_lun = 1;
                shost->max_channel = 1;
                shost->max_cmd_len = 16;
+               shost->no_write_same = 1;
 
                /* Schedule policy is determined by ->qc_defer()
                 * callback and it needs to see every deferred qc.
index 281029daf98c7ea291886d46ecf05378bfa98718..b0bb056458a363b0ee457beea13a8b926a63d483 100644 (file)
@@ -1623,6 +1623,7 @@ static struct scsi_host_template scsi_driver_template = {
        .cmd_per_lun            = 1,
        .can_queue              = 1,
        .sdev_attrs             = sbp2_scsi_sysfs_attrs,
+       .no_write_same          = 1,
 };
 
 MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>");
index 5e1e12c0cf4220796112d2d6dd9d9e102fdf537d..0a7325361d2958dceeae99da5959e518f8490985 100644 (file)
@@ -2025,7 +2025,8 @@ static struct scsi_host_template driver_template = {
        .cmd_per_lun            = TW_MAX_CMDS_PER_LUN,
        .use_clustering         = ENABLE_CLUSTERING,
        .shost_attrs            = twa_host_attrs,
-       .emulated               = 1
+       .emulated               = 1,
+       .no_write_same          = 1,
 };
 
 /* This function will probe and initialize a card */
index c845bdbeb6c06f971923300e7f8e11182d18d84c..4de346017e9ff91b43aed80d48231ac60f23a4e3 100644 (file)
@@ -1600,7 +1600,8 @@ static struct scsi_host_template driver_template = {
        .cmd_per_lun            = TW_MAX_CMDS_PER_LUN,
        .use_clustering         = ENABLE_CLUSTERING,
        .shost_attrs            = twl_host_attrs,
-       .emulated               = 1
+       .emulated               = 1,
+       .no_write_same          = 1,
 };
 
 /* This function will probe and initialize a card */
index b9276d10b25c2e277c05e1b6e48e196a11b38fa4..752624e6bc0022807c6265539cad6d8b42d1611f 100644 (file)
@@ -2279,7 +2279,8 @@ static struct scsi_host_template driver_template = {
        .cmd_per_lun            = TW_MAX_CMDS_PER_LUN,  
        .use_clustering         = ENABLE_CLUSTERING,
        .shost_attrs            = tw_host_attrs,
-       .emulated               = 1
+       .emulated               = 1,
+       .no_write_same          = 1,
 };
 
 /* This function will probe and initialize a card */
index f0d432c139d0cecedf51295562c858d22a9f44f0..4921ed19a027f819b731271c4804be74d2426e5a 100644 (file)
@@ -1081,6 +1081,7 @@ static struct scsi_host_template aac_driver_template = {
 #endif
        .use_clustering                 = ENABLE_CLUSTERING,
        .emulated                       = 1,
+       .no_write_same                  = 1,
 };
 
 static void __aac_shutdown(struct aac_dev * aac)
index 33c52bc2c7b461033b8845e7e538f072f9ab671f..278c9fa62067352ee7e36678795e90c646df953d 100644 (file)
@@ -137,6 +137,7 @@ static struct scsi_host_template arcmsr_scsi_host_template = {
        .cmd_per_lun            = ARCMSR_MAX_CMD_PERLUN,
        .use_clustering         = ENABLE_CLUSTERING,
        .shost_attrs            = arcmsr_host_attrs,
+       .no_write_same          = 1,
 };
 static struct pci_device_id arcmsr_device_id_table[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1110)},
index 6d55b4e7e7923121d58535ab1a7ff83c50298c8c..aec3d4da276fc1489880f901b3a43f997073bc98 100644 (file)
@@ -4686,6 +4686,7 @@ static struct scsi_host_template gdth_template = {
         .cmd_per_lun            = GDTH_MAXC_P_L,
         .unchecked_isa_dma      = 1,
         .use_clustering         = ENABLE_CLUSTERING,
+       .no_write_same          = 1,
 };
 
 #ifdef CONFIG_ISA
index df0c3c71ea43977bf04355cbd4b5a0eaab54bbb7..3cafe0d784b895f0fe0dda4552c7443acedb9432 100644 (file)
@@ -388,6 +388,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
        shost->unchecked_isa_dma = sht->unchecked_isa_dma;
        shost->use_clustering = sht->use_clustering;
        shost->ordered_tag = sht->ordered_tag;
+       shost->no_write_same = sht->no_write_same;
 
        if (sht->supported_mode == MODE_UNKNOWN)
                /* means we didn't set it ... default to INITIATOR */
index 42cac70b05bfdbf3add4e6b0fa511028674ce438..0eb09403680cb7e571b52e56f334c387773fc219 100644 (file)
@@ -562,6 +562,7 @@ static struct scsi_host_template hpsa_driver_template = {
        .sdev_attrs = hpsa_sdev_attrs,
        .shost_attrs = hpsa_shost_attrs,
        .max_sectors = 8192,
+       .no_write_same = 1,
 };
 
 
index 36ac1c34ce97eb53374f55451b8b42f4752b88f2..573f4128b6b68018f43a3263d166232ef39601fc 100644 (file)
@@ -6305,7 +6305,8 @@ static struct scsi_host_template driver_template = {
        .use_clustering = ENABLE_CLUSTERING,
        .shost_attrs = ipr_ioa_attrs,
        .sdev_attrs = ipr_dev_attrs,
-       .proc_name = IPR_NAME
+       .proc_name = IPR_NAME,
+       .no_write_same = 1,
 };
 
 /**
index 8d5ea8a1e5a6f33ab8235b300417d7ba352f84f7..52a216f21ae579644b97c093e89e12306a265595 100644 (file)
@@ -374,6 +374,7 @@ static struct scsi_host_template ips_driver_template = {
        .sg_tablesize           = IPS_MAX_SG,
        .cmd_per_lun            = 3,
        .use_clustering         = ENABLE_CLUSTERING,
+       .no_write_same          = 1,
 };
 
 
index 90c95a3385d18bb52f93093da10c8d400514f712..816db12ef5d555159226c5eb618b110ebb790776 100644 (file)
@@ -4244,6 +4244,7 @@ static struct scsi_host_template megaraid_template = {
        .eh_device_reset_handler        = megaraid_reset,
        .eh_bus_reset_handler           = megaraid_reset,
        .eh_host_reset_handler          = megaraid_reset,
+       .no_write_same                  = 1,
 };
 
 static int
index 515c9629e9fedf0679257a762b553045858070c1..8844d5c179af4dff7a51f2eb4a5da66d7c13772d 100644 (file)
@@ -367,6 +367,7 @@ static struct scsi_host_template megaraid_template_g = {
        .eh_host_reset_handler          = megaraid_reset_handler,
        .change_queue_depth             = megaraid_change_queue_depth,
        .use_clustering                 = ENABLE_CLUSTERING,
+       .no_write_same                  = 1,
        .sdev_attrs                     = megaraid_sdev_attrs,
        .shost_attrs                    = megaraid_shost_attrs,
 };
index 3020921a474671e6c9845ba26979d56c389a96c3..a59a5526a318b27cc0784dcf3d3048dd210551a6 100644 (file)
@@ -2148,6 +2148,7 @@ static struct scsi_host_template megasas_template = {
        .bios_param = megasas_bios_param,
        .use_clustering = ENABLE_CLUSTERING,
        .change_queue_depth = megasas_change_queue_depth,
+       .no_write_same = 1,
 };
 
 /**
index 1eb7b0280a45447fc1855ce0a653488cf1591002..a38f71bbe7b6cef38fd5ed2db25ef2f4fbce1b68 100644 (file)
@@ -4314,6 +4314,7 @@ static struct scsi_host_template pmcraid_host_template = {
        .this_id = -1,
        .sg_tablesize = PMCRAID_MAX_IOADLS,
        .max_sectors = PMCRAID_IOA_MAX_SECTORS,
+       .no_write_same = 1,
        .cmd_per_lun = PMCRAID_MAX_CMD_PER_LUN,
        .use_clustering = ENABLE_CLUSTERING,
        .shost_attrs = pmcraid_host_attrs,
index 5693f6d7eddb8b20cd9b3e0374a4e73e60ab7aa2..2634d691ec17607f7676cd12877450ade19e8bec 100644 (file)
@@ -2638,6 +2638,12 @@ static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer)
 {
        struct scsi_device *sdev = sdkp->device;
 
+       if (sdev->host->no_write_same) {
+               sdev->no_write_same = 1;
+
+               return;
+       }
+
        if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, INQUIRY) < 0) {
                sdev->no_report_opcodes = 1;
 
index 1a28f5632797ed2da2f27c0752013e3c7e4dde5d..17d7404272400dd1a76989a3965e0c4b85343036 100644 (file)
@@ -1697,6 +1697,7 @@ static struct scsi_host_template scsi_driver = {
        .use_clustering =       DISABLE_CLUSTERING,
        /* Make sure we dont get a sg segment crosses a page boundary */
        .dma_boundary =         PAGE_SIZE-1,
+       .no_write_same =        1,
 };
 
 enum {
index 755243572219da23383d1bab92ff42584766ba8c..50769a72166b56473065c4921519638ee1ed29e0 100644 (file)
@@ -475,6 +475,9 @@ struct scsi_host_template {
         */
        unsigned ordered_tag:1;
 
+       /* True if the controller does not support WRITE SAME */
+       unsigned no_write_same:1;
+
        /*
         * Countdown for host blocking with no commands outstanding.
         */
@@ -674,6 +677,9 @@ struct Scsi_Host {
        /* Don't resume host in EH */
        unsigned eh_noresume:1;
 
+       /* The controller does not support WRITE SAME */
+       unsigned no_write_same:1;
+
        /*
         * Optional work queue to be utilized by the transport
         */