power_supply: lp8788-charger: Fix leaked power supply on probe fail
[firefly-linux-kernel-4.4.55.git] / drivers / scsi / ipr.c
index 2197b57fb2251f541e0bfc0eab626ce670b66504..f7732f3b98042fd4f476d3159c11d6b397d2350d 100644 (file)
@@ -645,6 +645,7 @@ static void ipr_init_ipr_cmnd(struct ipr_cmnd *ipr_cmd,
        ipr_reinit_ipr_cmnd(ipr_cmd);
        ipr_cmd->u.scratch = 0;
        ipr_cmd->sibling = NULL;
+       ipr_cmd->eh_comp = NULL;
        ipr_cmd->fast_done = fast_done;
        init_timer(&ipr_cmd->timer);
 }
@@ -810,6 +811,8 @@ static void ipr_scsi_eh_done(struct ipr_cmnd *ipr_cmd)
 
        scsi_dma_unmap(ipr_cmd->scsi_cmd);
        scsi_cmd->scsi_done(scsi_cmd);
+       if (ipr_cmd->eh_comp)
+               complete(ipr_cmd->eh_comp);
        list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
 }
 
@@ -4767,6 +4770,84 @@ static int ipr_slave_alloc(struct scsi_device *sdev)
        return rc;
 }
 
+/**
+ * ipr_match_lun - Match function for specified LUN
+ * @ipr_cmd:   ipr command struct
+ * @device:            device to match (sdev)
+ *
+ * Returns:
+ *     1 if command matches sdev / 0 if command does not match sdev
+ **/
+static int ipr_match_lun(struct ipr_cmnd *ipr_cmd, void *device)
+{
+       if (ipr_cmd->scsi_cmd && ipr_cmd->scsi_cmd->device == device)
+               return 1;
+       return 0;
+}
+
+/**
+ * ipr_wait_for_ops - Wait for matching commands to complete
+ * @ipr_cmd:   ipr command struct
+ * @device:            device to match (sdev)
+ * @match:             match function to use
+ *
+ * Returns:
+ *     SUCCESS / FAILED
+ **/
+static int ipr_wait_for_ops(struct ipr_ioa_cfg *ioa_cfg, void *device,
+                           int (*match)(struct ipr_cmnd *, void *))
+{
+       struct ipr_cmnd *ipr_cmd;
+       int wait;
+       unsigned long flags;
+       struct ipr_hrr_queue *hrrq;
+       signed long timeout = IPR_ABORT_TASK_TIMEOUT;
+       DECLARE_COMPLETION_ONSTACK(comp);
+
+       ENTER;
+       do {
+               wait = 0;
+
+               for_each_hrrq(hrrq, ioa_cfg) {
+                       spin_lock_irqsave(hrrq->lock, flags);
+                       list_for_each_entry(ipr_cmd, &hrrq->hrrq_pending_q, queue) {
+                               if (match(ipr_cmd, device)) {
+                                       ipr_cmd->eh_comp = ∁
+                                       wait++;
+                               }
+                       }
+                       spin_unlock_irqrestore(hrrq->lock, flags);
+               }
+
+               if (wait) {
+                       timeout = wait_for_completion_timeout(&comp, timeout);
+
+                       if (!timeout) {
+                               wait = 0;
+
+                               for_each_hrrq(hrrq, ioa_cfg) {
+                                       spin_lock_irqsave(hrrq->lock, flags);
+                                       list_for_each_entry(ipr_cmd, &hrrq->hrrq_pending_q, queue) {
+                                               if (match(ipr_cmd, device)) {
+                                                       ipr_cmd->eh_comp = NULL;
+                                                       wait++;
+                                               }
+                                       }
+                                       spin_unlock_irqrestore(hrrq->lock, flags);
+                               }
+
+                               if (wait)
+                                       dev_err(&ioa_cfg->pdev->dev, "Timed out waiting for aborted commands\n");
+                               LEAVE;
+                               return wait ? FAILED : SUCCESS;
+                       }
+               }
+       } while (wait);
+
+       LEAVE;
+       return SUCCESS;
+}
+
 static int ipr_eh_host_reset(struct scsi_cmnd *cmd)
 {
        struct ipr_ioa_cfg *ioa_cfg;
@@ -4777,7 +4858,7 @@ static int ipr_eh_host_reset(struct scsi_cmnd *cmd)
        ioa_cfg = (struct ipr_ioa_cfg *) cmd->device->host->hostdata;
        spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
 
-       if (!ioa_cfg->in_reset_reload) {
+       if (!ioa_cfg->in_reset_reload && !ioa_cfg->hrrq[IPR_INIT_HRRQ].ioa_is_dead) {
                ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_ABBREV);
                dev_err(&ioa_cfg->pdev->dev,
                        "Adapter being reset as a result of error recovery.\n");
@@ -4985,11 +5066,17 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd *scsi_cmd)
 static int ipr_eh_dev_reset(struct scsi_cmnd *cmd)
 {
        int rc;
+       struct ipr_ioa_cfg *ioa_cfg;
+
+       ioa_cfg = (struct ipr_ioa_cfg *) cmd->device->host->hostdata;
 
        spin_lock_irq(cmd->device->host->host_lock);
        rc = __ipr_eh_dev_reset(cmd);
        spin_unlock_irq(cmd->device->host->host_lock);
 
+       if (rc == SUCCESS)
+               rc = ipr_wait_for_ops(ioa_cfg, cmd->device, ipr_match_lun);
+
        return rc;
 }
 
@@ -5167,13 +5254,18 @@ static int ipr_eh_abort(struct scsi_cmnd *scsi_cmd)
 {
        unsigned long flags;
        int rc;
+       struct ipr_ioa_cfg *ioa_cfg;
 
        ENTER;
 
+       ioa_cfg = (struct ipr_ioa_cfg *) scsi_cmd->device->host->hostdata;
+
        spin_lock_irqsave(scsi_cmd->device->host->host_lock, flags);
        rc = ipr_cancel_op(scsi_cmd);
        spin_unlock_irqrestore(scsi_cmd->device->host->host_lock, flags);
 
+       if (rc == SUCCESS)
+               rc = ipr_wait_for_ops(ioa_cfg, scsi_cmd->device, ipr_match_lun);
        LEAVE;
        return rc;
 }
@@ -6267,7 +6359,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,
 };
 
 /**
@@ -6421,7 +6514,7 @@ static void ipr_build_ata_ioadl64(struct ipr_cmnd *ipr_cmd,
 {
        u32 ioadl_flags = 0;
        struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb;
-       struct ipr_ioadl64_desc *ioadl64 = ipr_cmd->i.ioadl64;
+       struct ipr_ioadl64_desc *ioadl64 = ipr_cmd->i.ata_ioadl.ioadl64;
        struct ipr_ioadl64_desc *last_ioadl64 = NULL;
        int len = qc->nbytes;
        struct scatterlist *sg;
@@ -6441,7 +6534,7 @@ static void ipr_build_ata_ioadl64(struct ipr_cmnd *ipr_cmd,
        ioarcb->ioadl_len =
                cpu_to_be32(sizeof(struct ipr_ioadl64_desc) * ipr_cmd->dma_use_sg);
        ioarcb->u.sis64_addr_data.data_ioadl_addr =
-               cpu_to_be64(dma_addr + offsetof(struct ipr_cmnd, i.ata_ioadl));
+               cpu_to_be64(dma_addr + offsetof(struct ipr_cmnd, i.ata_ioadl.ioadl64));
 
        for_each_sg(qc->sg, sg, qc->n_elem, si) {
                ioadl64->flags = cpu_to_be32(ioadl_flags);
@@ -6739,6 +6832,7 @@ static int ipr_invalid_adapter(struct ipr_ioa_cfg *ioa_cfg)
 static int ipr_ioa_bringdown_done(struct ipr_cmnd *ipr_cmd)
 {
        struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
+       int i;
 
        ENTER;
        if (!ioa_cfg->hrrq[IPR_INIT_HRRQ].removing_ioa) {
@@ -6750,6 +6844,13 @@ static int ipr_ioa_bringdown_done(struct ipr_cmnd *ipr_cmd)
 
        ioa_cfg->in_reset_reload = 0;
        ioa_cfg->reset_retries = 0;
+       for (i = 0; i < ioa_cfg->hrrq_num; i++) {
+               spin_lock(&ioa_cfg->hrrq[i]._lock);
+               ioa_cfg->hrrq[i].ioa_is_dead = 1;
+               spin_unlock(&ioa_cfg->hrrq[i]._lock);
+       }
+       wmb();
+
        list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
        wake_up_all(&ioa_cfg->reset_wait_q);
        LEAVE;
@@ -8651,7 +8752,7 @@ static void ipr_pci_perm_failure(struct pci_dev *pdev)
        spin_lock_irqsave(ioa_cfg->host->host_lock, flags);
        if (ioa_cfg->sdt_state == WAIT_FOR_DUMP)
                ioa_cfg->sdt_state = ABORT_DUMP;
-       ioa_cfg->reset_retries = IPR_NUM_RESET_RELOAD_RETRIES;
+       ioa_cfg->reset_retries = IPR_NUM_RESET_RELOAD_RETRIES - 1;
        ioa_cfg->in_ioa_bringdown = 1;
        for (i = 0; i < ioa_cfg->hrrq_num; i++) {
                spin_lock(&ioa_cfg->hrrq[i]._lock);
@@ -8972,19 +9073,6 @@ static int ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
        if (!ioa_cfg->res_entries)
                goto out;
 
-       if (ioa_cfg->sis64) {
-               ioa_cfg->target_ids = kzalloc(sizeof(unsigned long) *
-                                             BITS_TO_LONGS(ioa_cfg->max_devs_supported), GFP_KERNEL);
-               ioa_cfg->array_ids = kzalloc(sizeof(unsigned long) *
-                                            BITS_TO_LONGS(ioa_cfg->max_devs_supported), GFP_KERNEL);
-               ioa_cfg->vset_ids = kzalloc(sizeof(unsigned long) *
-                                           BITS_TO_LONGS(ioa_cfg->max_devs_supported), GFP_KERNEL);
-
-               if (!ioa_cfg->target_ids || !ioa_cfg->array_ids
-                       || !ioa_cfg->vset_ids)
-                       goto out_free_res_entries;
-       }
-
        for (i = 0; i < ioa_cfg->max_devs_supported; i++) {
                list_add_tail(&ioa_cfg->res_entries[i].queue, &ioa_cfg->free_res_q);
                ioa_cfg->res_entries[i].ioa_cfg = ioa_cfg;
@@ -9081,9 +9169,6 @@ out_free_vpd_cbs:
                            ioa_cfg->vpd_cbs, ioa_cfg->vpd_cbs_dma);
 out_free_res_entries:
        kfree(ioa_cfg->res_entries);
-       kfree(ioa_cfg->target_ids);
-       kfree(ioa_cfg->array_ids);
-       kfree(ioa_cfg->vset_ids);
        goto out;
 }