Merge tag 'scsi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 14 Jul 2013 00:41:21 +0000 (17:41 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 14 Jul 2013 00:41:21 +0000 (17:41 -0700)
Pull final round of SCSI updates from James Bottomley:
 "This is the remaining set of SCSI patches for the merge window.  It's
  mostly driver updates (scsi_debug, qla2xxx, storvsc, mp3sas).  There
  are also several bug fixes in fcoe, libfc, and megaraid_sas.  We also
  have a couple of core changes to try to make device destruction more
  deterministic"

* tag 'scsi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (46 commits)
  [SCSI] scsi constants: command, sense key + additional sense strings
  fcoe: Reduce number of sparse warnings
  fcoe: Stop fc_rport_priv structure leak
  libfcoe: Fix meaningless log statement
  libfc: Differentiate echange timer cancellation debug statements
  libfc: Remove extra space in fc_exch_timer_cancel definition
  fcoe: fix the link error status block sparse warnings
  fcoe: Fix smatch warning in fcoe_fdmi_info function
  libfc: Reject PLOGI from nodes with incompatible role
  [SCSI] enable destruction of blocked devices which fail LUN scanning
  [SCSI] Fix race between starved list and device removal
  [SCSI] megaraid_sas: fix a bug for 64 bit arches
  [SCSI] scsi_debug: reduce duplication between prot_verify_read and prot_verify_write
  [SCSI] scsi_debug: simplify offset calculation for dif_storep
  [SCSI] scsi_debug: invalidate protection info for unmapped region
  [SCSI] scsi_debug: fix NULL pointer dereference with parameters dif=0 dix=1
  [SCSI] scsi_debug: fix incorrectly nested kmap_atomic()
  [SCSI] scsi_debug: fix invalid address passed to kunmap_atomic()
  [SCSI] mpt3sas: Bump driver version to v02.100.00.00
  [SCSI] mpt3sas: when async scanning is enabled then while scanning, devices are removed but their transport layer entries are not removed
  ...

1  2 
drivers/scsi/fcoe/fcoe.c
drivers/scsi/fcoe/fcoe_transport.c
drivers/scsi/scsi_debug.c

diff --combined drivers/scsi/fcoe/fcoe.c
@@@ -774,7 -774,6 +774,6 @@@ static void fcoe_fdmi_info(struct fc_lp
        struct fcoe_port *port;
        struct net_device *realdev;
        int rc;
-       struct netdev_fcoe_hbainfo fdmi;
  
        port = lport_priv(lport);
        fcoe = port->priv;
                return;
  
        if (realdev->netdev_ops->ndo_fcoe_get_hbainfo) {
-               memset(&fdmi, 0, sizeof(fdmi));
+               struct netdev_fcoe_hbainfo *fdmi;
+               fdmi = kzalloc(sizeof(*fdmi), GFP_KERNEL);
+               if (!fdmi)
+                       return;
                rc = realdev->netdev_ops->ndo_fcoe_get_hbainfo(realdev,
-                                                              &fdmi);
+                                                              fdmi);
                if (rc) {
                        printk(KERN_INFO "fcoe: Failed to retrieve FDMI "
                                        "information from netdev.\n");
                snprintf(fc_host_serial_number(lport->host),
                         FC_SERIAL_NUMBER_SIZE,
                         "%s",
-                        fdmi.serial_number);
+                        fdmi->serial_number);
                snprintf(fc_host_manufacturer(lport->host),
                         FC_SERIAL_NUMBER_SIZE,
                         "%s",
-                        fdmi.manufacturer);
+                        fdmi->manufacturer);
                snprintf(fc_host_model(lport->host),
                         FC_SYMBOLIC_NAME_SIZE,
                         "%s",
-                        fdmi.model);
+                        fdmi->model);
                snprintf(fc_host_model_description(lport->host),
                         FC_SYMBOLIC_NAME_SIZE,
                         "%s",
-                        fdmi.model_description);
+                        fdmi->model_description);
                snprintf(fc_host_hardware_version(lport->host),
                         FC_VERSION_STRING_SIZE,
                         "%s",
-                        fdmi.hardware_version);
+                        fdmi->hardware_version);
                snprintf(fc_host_driver_version(lport->host),
                         FC_VERSION_STRING_SIZE,
                         "%s",
-                        fdmi.driver_version);
+                        fdmi->driver_version);
                snprintf(fc_host_optionrom_version(lport->host),
                         FC_VERSION_STRING_SIZE,
                         "%s",
-                        fdmi.optionrom_version);
+                        fdmi->optionrom_version);
                snprintf(fc_host_firmware_version(lport->host),
                         FC_VERSION_STRING_SIZE,
                         "%s",
-                        fdmi.firmware_version);
+                        fdmi->firmware_version);
  
                /* Enable FDMI lport states */
                lport->fdmi_enabled = 1;
+               kfree(fdmi);
        } else {
                lport->fdmi_enabled = 0;
                printk(KERN_INFO "fcoe: No FDMI support.\n");
@@@ -1978,7 -1982,7 +1982,7 @@@ static int fcoe_device_notification(str
  {
        struct fcoe_ctlr_device *cdev;
        struct fc_lport *lport = NULL;
 -      struct net_device *netdev = ptr;
 +      struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
        struct fcoe_ctlr *ctlr;
        struct fcoe_interface *fcoe;
        struct fcoe_port *port;
@@@ -180,24 -180,10 +180,10 @@@ void fcoe_ctlr_get_lesb(struct fcoe_ctl
  {
        struct fcoe_ctlr *fip = fcoe_ctlr_device_priv(ctlr_dev);
        struct net_device *netdev = fcoe_get_netdev(fip->lp);
-       struct fcoe_fc_els_lesb *fcoe_lesb;
-       struct fc_els_lesb fc_lesb;
-       __fcoe_get_lesb(fip->lp, &fc_lesb, netdev);
-       fcoe_lesb = (struct fcoe_fc_els_lesb *)(&fc_lesb);
-       ctlr_dev->lesb.lesb_link_fail =
-               ntohl(fcoe_lesb->lesb_link_fail);
-       ctlr_dev->lesb.lesb_vlink_fail =
-               ntohl(fcoe_lesb->lesb_vlink_fail);
-       ctlr_dev->lesb.lesb_miss_fka =
-               ntohl(fcoe_lesb->lesb_miss_fka);
-       ctlr_dev->lesb.lesb_symb_err =
-               ntohl(fcoe_lesb->lesb_symb_err);
-       ctlr_dev->lesb.lesb_err_block =
-               ntohl(fcoe_lesb->lesb_err_block);
-       ctlr_dev->lesb.lesb_fcs_error =
-               ntohl(fcoe_lesb->lesb_fcs_error);
+       struct fc_els_lesb *fc_lesb;
+       fc_lesb = (struct fc_els_lesb *)(&ctlr_dev->lesb);
+       __fcoe_get_lesb(fip->lp, fc_lesb, netdev);
  }
  EXPORT_SYMBOL_GPL(fcoe_ctlr_get_lesb);
  
@@@ -704,7 -690,7 +690,7 @@@ static struct net_device *fcoe_if_to_ne
  static int libfcoe_device_notification(struct notifier_block *notifier,
                                    ulong event, void *ptr)
  {
 -      struct net_device *netdev = ptr;
 +      struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
  
        switch (event) {
        case NETDEV_UNREGISTER:
@@@ -721,7 -707,6 +707,6 @@@ ssize_t fcoe_ctlr_create_store(struct b
  {
        struct net_device *netdev = NULL;
        struct fcoe_transport *ft = NULL;
-       struct fcoe_ctlr_device *ctlr_dev = NULL;
        int rc = 0;
        int err;
  
                goto out_putdev;
        }
  
-       LIBFCOE_TRANSPORT_DBG("transport %s %s to create fcoe on %s.\n",
-                             ft->name, (ctlr_dev) ? "succeeded" : "failed",
-                             netdev->name);
+       LIBFCOE_TRANSPORT_DBG("transport %s succeeded to create fcoe on %s.\n",
+                             ft->name, netdev->name);
  
  out_putdev:
        dev_put(netdev);
@@@ -258,7 -258,7 +258,7 @@@ 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 struct sd_dif_tuple *dif_storep;       /* protection info */
  static void *map_storep;              /* provisioning map */
  
  static unsigned long map_size;
@@@ -277,11 -277,6 +277,6 @@@ static char sdebug_proc_name[] = "scsi_
  
  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,
@@@ -439,7 -434,10 +434,7 @@@ static int fill_from_dev_buffer(struct 
  
        act_len = sg_copy_from_buffer(sdb->table.sgl, sdb->table.nents,
                                      arr, arr_len);
 -      if (sdb->resid)
 -              sdb->resid -= act_len;
 -      else
 -              sdb->resid = scsi_bufflen(scp) - act_len;
 +      sdb->resid = scsi_bufflen(scp) - act_len;
  
        return 0;
  }
@@@ -1690,52 -1688,72 +1685,96 @@@ static int check_device_access_params(s
        return 0;
  }
  
 +/* Returns number of bytes copied or -1 if error. */
  static int do_device_access(struct scsi_cmnd *scmd,
                            struct sdebug_dev_info *devi,
                            unsigned long long lba, unsigned int num, int write)
  {
        int ret;
        unsigned long long block, rest = 0;
 -      int (*func)(struct scsi_cmnd *, unsigned char *, int);
 +      struct scsi_data_buffer *sdb;
 +      enum dma_data_direction dir;
 +      size_t (*func)(struct scatterlist *, unsigned int, void *, size_t,
 +                     off_t);
 +
 +      if (write) {
 +              sdb = scsi_out(scmd);
 +              dir = DMA_TO_DEVICE;
 +              func = sg_pcopy_to_buffer;
 +      } else {
 +              sdb = scsi_in(scmd);
 +              dir = DMA_FROM_DEVICE;
 +              func = sg_pcopy_from_buffer;
 +      }
  
 -      func = write ? fetch_to_dev_buffer : fill_from_dev_buffer;
 +      if (!sdb->length)
 +              return 0;
 +      if (!(scsi_bidi_cmnd(scmd) || scmd->sc_data_direction == dir))
 +              return -1;
  
        block = do_div(lba, sdebug_store_sectors);
        if (block + num > sdebug_store_sectors)
                rest = block + num - sdebug_store_sectors;
  
 -      ret = func(scmd, fake_storep + (block * scsi_debug_sector_size),
 -                 (num - rest) * scsi_debug_sector_size);
 -      if (!ret && rest)
 -              ret = func(scmd, fake_storep, rest * scsi_debug_sector_size);
 +      ret = func(sdb->table.sgl, sdb->table.nents,
 +                 fake_storep + (block * scsi_debug_sector_size),
 +                 (num - rest) * scsi_debug_sector_size, 0);
 +      if (ret != (num - rest) * scsi_debug_sector_size)
 +              return ret;
 +
 +      if (rest) {
 +              ret += func(sdb->table.sgl, sdb->table.nents,
 +                          fake_storep, rest * scsi_debug_sector_size,
 +                          (num - rest) * scsi_debug_sector_size);
 +      }
  
        return ret;
  }
  
+ static u16 dif_compute_csum(const void *buf, int len)
+ {
+       u16 csum;
+       switch (scsi_debug_guard) {
+       case 1:
+               csum = ip_compute_csum(buf, len);
+               break;
+       case 0:
+               csum = cpu_to_be16(crc_t10dif(buf, len));
+               break;
+       }
+       return csum;
+ }
+ static int dif_verify(struct sd_dif_tuple *sdt, const void *data,
+                     sector_t sector, u32 ei_lba)
+ {
+       u16 csum = dif_compute_csum(data, scsi_debug_sector_size);
+       if (sdt->guard_tag != csum) {
+               pr_err("%s: GUARD check failed on sector %lu rcvd 0x%04x, data 0x%04x\n",
+                       __func__,
+                       (unsigned long)sector,
+                       be16_to_cpu(sdt->guard_tag),
+                       be16_to_cpu(csum));
+               return 0x01;
+       }
+       if (scsi_debug_dif == SD_DIF_TYPE1_PROTECTION &&
+           be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) {
+               pr_err("%s: REF check failed on sector %lu\n",
+                       __func__, (unsigned long)sector);
+               return 0x03;
+       }
+       if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
+           be32_to_cpu(sdt->ref_tag) != ei_lba) {
+               pr_err("%s: REF check failed on sector %lu\n",
+                       __func__, (unsigned long)sector);
+                       dif_errors++;
+               return 0x03;
+       }
+       return 0;
+ }
  static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec,
                            unsigned int sectors, u32 ei_lba)
  {
  
        start_sec = do_div(tmp_sec, sdebug_store_sectors);
  
-       sdt = (struct sd_dif_tuple *)(dif_storep + dif_offset(start_sec));
+       sdt = dif_storep + start_sec;
  
        for (i = 0 ; i < sectors ; i++) {
-               u16 csum;
+               int ret;
  
                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_TYPE1_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);
+               ret = dif_verify(&sdt[i],
+                                fake_storep + sector * scsi_debug_sector_size,
+                                sector, ei_lba);
+               if (ret) {
                        dif_errors++;
-                       return 0x03;
-               }
-               if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
-                   be32_to_cpu(sdt[i].ref_tag) != ei_lba) {
-                       printk(KERN_ERR "%s: REF check failed on sector %lu\n",
-                              __func__, (unsigned long)sector);
-                       dif_errors++;
-                       return 0x03;
+                       return ret;
                }
  
                ei_lba++;
        }
  
-       resid = sectors * 8; /* Bytes of protection data to copy into sgl */
+       /* Bytes of protection data to copy into sgl */
+       resid = sectors * sizeof(*dif_storep);
        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)) + psgl->offset;
-               memcpy(paddr, dif_storep + dif_offset(sector), len);
+               memcpy(paddr, dif_storep + sector, len);
  
-               sector += len >> 3;
+               sector += len / sizeof(*dif_storep);
                if (sector >= sdebug_store_sectors) {
                        /* Force wrap */
                        tmp_sec = sector;
@@@ -1870,12 -1855,7 +1876,12 @@@ static int resp_read(struct scsi_cmnd *
        read_lock_irqsave(&atomic_rw, iflags);
        ret = do_device_access(SCpnt, devip, lba, num, 0);
        read_unlock_irqrestore(&atomic_rw, iflags);
 -      return ret;
 +      if (ret == -1)
 +              return DID_ERROR << 16;
 +
 +      scsi_in(SCpnt)->resid = scsi_bufflen(SCpnt) - ret;
 +
 +      return 0;
  }
  
  void dump_sector(unsigned char *buf, int len)
@@@ -1910,22 -1890,21 +1916,21 @@@ static int prot_verify_write(struct scs
        sector_t tmp_sec = start_sec;
        sector_t sector;
        int ppage_offset;
-       unsigned short csum;
  
        sector = do_div(tmp_sec, sdebug_store_sectors);
  
        BUG_ON(scsi_sg_count(SCpnt) == 0);
        BUG_ON(scsi_prot_sg_count(SCpnt) == 0);
  
-       paddr = kmap_atomic(sg_page(psgl)) + 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)) + dsgl->offset;
+               paddr = kmap_atomic(sg_page(psgl)) + psgl->offset;
  
                /* For each sector-sized chunk in data page */
-               for (j = 0 ; j < dsgl->length ; j += scsi_debug_sector_size) {
+               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
  
                        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_TYPE1_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;
-                       }
-                       if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
-                           be32_to_cpu(sdt->ref_tag) != ei_lba) {
-                               printk(KERN_ERR
-                                      "%s: REF check failed on sector %lu\n",
-                                      __func__, (unsigned long)sector);
-                               ret = 0x03;
-                               dump_sector(daddr, scsi_debug_sector_size);
+                       ret = dif_verify(sdt, daddr + j, start_sec, ei_lba);
+                       if (ret) {
+                               dump_sector(daddr + j, scsi_debug_sector_size);
                                goto out;
                        }
  
                         * correctness we need to verify each sector
                         * before writing it to "stable" storage
                         */
-                       memcpy(dif_storep + dif_offset(sector), sdt, 8);
+                       memcpy(dif_storep + sector, sdt, sizeof(*sdt));
  
                        sector++;
  
  
                        start_sec++;
                        ei_lba++;
-                       daddr += scsi_debug_sector_size;
                        ppage_offset += sizeof(struct sd_dif_tuple);
                }
  
+               kunmap_atomic(paddr);
                kunmap_atomic(daddr);
        }
  
-       kunmap_atomic(paddr);
        dix_writes++;
  
        return 0;
  
  out:
        dif_errors++;
-       kunmap_atomic(daddr);
        kunmap_atomic(paddr);
+       kunmap_atomic(daddr);
        return ret;
  }
  
@@@ -2092,6 -2027,11 +2053,11 @@@ static void unmap_region(sector_t lba, 
                                       scsi_debug_sector_size *
                                       scsi_debug_unmap_granularity);
                        }
+                       if (dif_storep) {
+                               memset(dif_storep + lba, 0xff,
+                                      sizeof(*dif_storep) *
+                                      scsi_debug_unmap_granularity);
+                       }
                }
                lba = map_index_to_lba(index + 1);
        }
@@@ -3400,7 -3340,7 +3366,7 @@@ static int __init scsi_debug_init(void
        if (scsi_debug_num_parts > 0)
                sdebug_build_parts(fake_storep, sz);
  
-       if (scsi_debug_dif) {
+       if (scsi_debug_dix) {
                int dif_size;
  
                dif_size = sdebug_store_sectors * sizeof(struct sd_dif_tuple);