]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - drivers/scsi/mpt3sas/mpt3sas_scsih.c
Merge branches 'uaccess.alpha', 'uaccess.arc', 'uaccess.arm', 'uaccess.arm64', 'uacce...
[mirror_ubuntu-artful-kernel.git] / drivers / scsi / mpt3sas / mpt3sas_scsih.c
index 0b5b423b1db0d19a1a1dfb6fc38e168af4559d71..919ba2bb15f110f4619a72646d170f87ad985237 100644 (file)
@@ -1074,6 +1074,26 @@ _scsih_scsi_lookup_get(struct MPT3SAS_ADAPTER *ioc, u16 smid)
        return ioc->scsi_lookup[smid - 1].scmd;
 }
 
+/**
+ * __scsih_scsi_lookup_get_clear - returns scmd entry without
+ *                                             holding any lock.
+ * @ioc: per adapter object
+ * @smid: system request message index
+ *
+ * Returns the smid stored scmd pointer.
+ * Then will dereference the stored scmd pointer.
+ */
+static inline struct scsi_cmnd *
+__scsih_scsi_lookup_get_clear(struct MPT3SAS_ADAPTER *ioc,
+               u16 smid)
+{
+       struct scsi_cmnd *scmd = NULL;
+
+       swap(scmd, ioc->scsi_lookup[smid - 1].scmd);
+
+       return scmd;
+}
+
 /**
  * _scsih_scsi_lookup_get_clear - returns scmd entry
  * @ioc: per adapter object
@@ -1089,8 +1109,7 @@ _scsih_scsi_lookup_get_clear(struct MPT3SAS_ADAPTER *ioc, u16 smid)
        struct scsi_cmnd *scmd;
 
        spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
-       scmd = ioc->scsi_lookup[smid - 1].scmd;
-       ioc->scsi_lookup[smid - 1].scmd = NULL;
+       scmd = __scsih_scsi_lookup_get_clear(ioc, smid);
        spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
 
        return scmd;
@@ -2840,7 +2859,7 @@ _scsih_internal_device_block(struct scsi_device *sdev,
            sas_device_priv_data->sas_target->handle);
        sas_device_priv_data->block = 1;
 
-       r = scsi_internal_device_block(sdev);
+       r = scsi_internal_device_block(sdev, false);
        if (r == -EINVAL)
                sdev_printk(KERN_WARNING, sdev,
                    "device_block failed with return(%d) for handle(0x%04x)\n",
@@ -2876,7 +2895,7 @@ _scsih_internal_device_unblock(struct scsi_device *sdev,
                    "performing a block followed by an unblock\n",
                    r, sas_device_priv_data->sas_target->handle);
                sas_device_priv_data->block = 1;
-               r = scsi_internal_device_block(sdev);
+               r = scsi_internal_device_block(sdev, false);
                if (r)
                        sdev_printk(KERN_WARNING, sdev, "retried device_block "
                            "failed with return(%d) for handle(0x%04x)\n",
@@ -4658,10 +4677,15 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
        struct MPT3SAS_DEVICE *sas_device_priv_data;
        u32 response_code = 0;
        unsigned long flags;
-       unsigned int sector_sz;
 
        mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
-       scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
+
+       if (ioc->broadcast_aen_busy || ioc->pci_error_recovery ||
+                       ioc->got_task_abort_from_ioctl)
+               scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
+       else
+               scmd = __scsih_scsi_lookup_get_clear(ioc, smid);
+
        if (scmd == NULL)
                return 1;
 
@@ -4717,20 +4741,6 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
        }
 
        xfer_cnt = le32_to_cpu(mpi_reply->TransferCount);
-
-       /* In case of bogus fw or device, we could end up having
-        * unaligned partial completion. We can force alignment here,
-        * then scsi-ml does not need to handle this misbehavior.
-        */
-       sector_sz = scmd->device->sector_size;
-       if (unlikely(scmd->request->cmd_type == REQ_TYPE_FS && sector_sz &&
-                    xfer_cnt % sector_sz)) {
-               sdev_printk(KERN_INFO, scmd->device,
-                   "unaligned partial completion avoided (xfer_cnt=%u, sector_sz=%u)\n",
-                           xfer_cnt, sector_sz);
-               xfer_cnt = round_down(xfer_cnt, sector_sz);
-       }
-
        scsi_set_resid(scmd, scsi_bufflen(scmd) - xfer_cnt);
        if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
                log_info =  le32_to_cpu(mpi_reply->IOCLogInfo);
@@ -8044,15 +8054,24 @@ mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
        case MPI2_EVENT_ACTIVE_CABLE_EXCEPTION:
                ActiveCableEventData =
                    (Mpi26EventDataActiveCableExcept_t *) mpi_reply->EventData;
-               if (ActiveCableEventData->ReasonCode ==
-                               MPI26_EVENT_ACTIVE_CABLE_INSUFFICIENT_POWER) {
-                       pr_info(MPT3SAS_FMT "Currently an active cable with ReceptacleID %d",
-                           ioc->name, ActiveCableEventData->ReceptacleID);
-                       pr_info("cannot be powered and devices connected to this active cable");
-                       pr_info("will not be seen. This active cable");
-                       pr_info("requires %d mW of power",
-                           ActiveCableEventData->ActiveCablePowerRequirement);
+               switch (ActiveCableEventData->ReasonCode) {
+               case MPI26_EVENT_ACTIVE_CABLE_INSUFFICIENT_POWER:
+                       pr_notice(MPT3SAS_FMT "Receptacle ID %d: This active cable"
+                                 " requires %d mW of power\n", ioc->name,
+                            ActiveCableEventData->ReceptacleID,
+                            ActiveCableEventData->ActiveCablePowerRequirement);
+                       pr_notice(MPT3SAS_FMT "Receptacle ID %d: Devices connected"
+                                 " to this active cable will not be seen\n",
+                            ioc->name, ActiveCableEventData->ReceptacleID);
+                       break;
+
+               case MPI26_EVENT_ACTIVE_CABLE_DEGRADED:
+                       pr_notice(MPT3SAS_FMT "ReceptacleID %d: This cable",
+                               ioc->name, ActiveCableEventData->ReceptacleID);
+                       pr_notice(" is not running at an optimal speed(12 Gb/s)\n");
+                       break;
                }
+
                break;
 
        default: /* ignore the rest */