]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/scsi/ipr.c
[SCSI] FC transport: fixes for workq deadlocks
[linux-2.6-omap-h63xx.git] / drivers / scsi / ipr.c
index dd5c96239e06f83fce0fb85ca70332def020b027..8b80e59c8c524c39a8d268b84393de0808555130 100644 (file)
@@ -1333,8 +1333,8 @@ static void ipr_handle_log_data(struct ipr_ioa_cfg *ioa_cfg,
                return;
 
        if (ipr_is_device(&hostrcb->hcam.u.error.failing_dev_res_addr)) {
-               ipr_res_err(ioa_cfg, hostrcb->hcam.u.error.failing_dev_res_addr,
-                           "%s\n", ipr_error_table[error_index].error);
+               ipr_ra_err(ioa_cfg, hostrcb->hcam.u.error.failing_dev_res_addr,
+                          "%s\n", ipr_error_table[error_index].error);
        } else {
                dev_err(&ioa_cfg->pdev->dev, "%s\n",
                        ipr_error_table[error_index].error);
@@ -3280,6 +3280,44 @@ static int ipr_eh_host_reset(struct scsi_cmnd * cmd)
        return rc;
 }
 
+/**
+ * ipr_device_reset - Reset the device
+ * @ioa_cfg:   ioa config struct
+ * @res:               resource entry struct
+ *
+ * This function issues a device reset to the affected device.
+ * If the device is a SCSI device, a LUN reset will be sent
+ * to the device first. If that does not work, a target reset
+ * will be sent.
+ *
+ * Return value:
+ *     0 on success / non-zero on failure
+ **/
+static int ipr_device_reset(struct ipr_ioa_cfg *ioa_cfg,
+                           struct ipr_resource_entry *res)
+{
+       struct ipr_cmnd *ipr_cmd;
+       struct ipr_ioarcb *ioarcb;
+       struct ipr_cmd_pkt *cmd_pkt;
+       u32 ioasc;
+
+       ENTER;
+       ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
+       ioarcb = &ipr_cmd->ioarcb;
+       cmd_pkt = &ioarcb->cmd_pkt;
+
+       ioarcb->res_handle = res->cfgte.res_handle;
+       cmd_pkt->request_type = IPR_RQTYPE_IOACMD;
+       cmd_pkt->cdb[0] = IPR_RESET_DEVICE;
+
+       ipr_send_blocking_cmd(ipr_cmd, ipr_timeout, IPR_DEVICE_RESET_TIMEOUT);
+       ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
+       list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
+
+       LEAVE;
+       return (IPR_IOASC_SENSE_KEY(ioasc) ? -EIO : 0);
+}
+
 /**
  * ipr_eh_dev_reset - Reset the device
  * @scsi_cmd:  scsi command struct
@@ -3296,8 +3334,7 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd * scsi_cmd)
        struct ipr_cmnd *ipr_cmd;
        struct ipr_ioa_cfg *ioa_cfg;
        struct ipr_resource_entry *res;
-       struct ipr_cmd_pkt *cmd_pkt;
-       u32 ioasc;
+       int rc;
 
        ENTER;
        ioa_cfg = (struct ipr_ioa_cfg *) scsi_cmd->device->host->hostdata;
@@ -3324,25 +3361,12 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd * scsi_cmd)
        }
 
        res->resetting_device = 1;
-
-       ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
-
-       ipr_cmd->ioarcb.res_handle = res->cfgte.res_handle;
-       cmd_pkt = &ipr_cmd->ioarcb.cmd_pkt;
-       cmd_pkt->request_type = IPR_RQTYPE_IOACMD;
-       cmd_pkt->cdb[0] = IPR_RESET_DEVICE;
-
-       ipr_sdev_err(scsi_cmd->device, "Resetting device\n");
-       ipr_send_blocking_cmd(ipr_cmd, ipr_timeout, IPR_DEVICE_RESET_TIMEOUT);
-
-       ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
-
+       scmd_printk(KERN_ERR, scsi_cmd, "Resetting device\n");
+       rc = ipr_device_reset(ioa_cfg, res);
        res->resetting_device = 0;
 
-       list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
-
        LEAVE;
-       return (IPR_IOASC_SENSE_KEY(ioasc) ? FAILED : SUCCESS);
+       return (rc ? FAILED : SUCCESS);
 }
 
 static int ipr_eh_dev_reset(struct scsi_cmnd * cmd)
@@ -3417,7 +3441,7 @@ static void ipr_abort_timeout(struct ipr_cmnd *ipr_cmd)
                return;
        }
 
-       ipr_sdev_err(ipr_cmd->u.sdev, "Abort timed out. Resetting bus\n");
+       sdev_printk(KERN_ERR, ipr_cmd->u.sdev, "Abort timed out. Resetting bus.\n");
        reset_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
        ipr_cmd->sibling = reset_cmd;
        reset_cmd->sibling = ipr_cmd;
@@ -3481,7 +3505,8 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd)
        cmd_pkt->cdb[0] = IPR_CANCEL_ALL_REQUESTS;
        ipr_cmd->u.sdev = scsi_cmd->device;
 
-       ipr_sdev_err(scsi_cmd->device, "Aborting command: %02X\n", scsi_cmd->cmnd[0]);
+       scmd_printk(KERN_ERR, scsi_cmd, "Aborting command: %02X\n",
+                   scsi_cmd->cmnd[0]);
        ipr_send_blocking_cmd(ipr_cmd, ipr_abort_timeout, IPR_CANCEL_ALL_TIMEOUT);
        ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
 
@@ -3792,8 +3817,8 @@ static void ipr_erp_done(struct ipr_cmnd *ipr_cmd)
 
        if (IPR_IOASC_SENSE_KEY(ioasc) > 0) {
                scsi_cmd->result |= (DID_ERROR << 16);
-               ipr_sdev_err(scsi_cmd->device,
-                            "Request Sense failed with IOASC: 0x%08X\n", ioasc);
+               scmd_printk(KERN_ERR, scsi_cmd,
+                           "Request Sense failed with IOASC: 0x%08X\n", ioasc);
        } else {
                memcpy(scsi_cmd->sense_buffer, ipr_cmd->sense_buffer,
                       SCSI_SENSE_BUFFERSIZE);