[SCSI] qla2xxx: Add reset capabilities for application support.
authorLalit Chandivade <lalit.chandivade@qlogic.com>
Thu, 26 Mar 2009 15:49:17 +0000 (08:49 -0700)
committerJames Bottomley <James.Bottomley@HansenPartnership.com>
Fri, 3 Apr 2009 14:22:49 +0000 (09:22 -0500)
Signed-off-by: Lalit Chandivade <lalit.chandivade@qlogic.com>
Additional cleanups and
Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_fw.h
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_mbx.c

index 117517d..1f1a7c0 100644 (file)
@@ -479,6 +479,61 @@ static struct bin_attribute sysfs_sfp_attr = {
        .read = qla2x00_sysfs_read_sfp,
 };
 
+static ssize_t
+qla2x00_sysfs_write_reset(struct kobject *kobj,
+                       struct bin_attribute *bin_attr,
+                       char *buf, loff_t off, size_t count)
+{
+       struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
+           struct device, kobj)));
+       struct qla_hw_data *ha = vha->hw;
+       int type;
+
+       if (off != 0)
+               return 0;
+
+       type = simple_strtol(buf, NULL, 10);
+       switch (type) {
+       case 0x2025c:
+               qla_printk(KERN_INFO, ha,
+                   "Issuing ISP reset on (%ld).\n", vha->host_no);
+
+               scsi_block_requests(vha->host);
+               set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+               qla2xxx_wake_dpc(vha);
+               qla2x00_wait_for_chip_reset(vha);
+               scsi_unblock_requests(vha->host);
+               break;
+       case 0x2025d:
+               if (!IS_QLA81XX(ha))
+                       break;
+
+               qla_printk(KERN_INFO, ha,
+                   "Issuing MPI reset on (%ld).\n", vha->host_no);
+
+               /* Make sure FC side is not in reset */
+               qla2x00_wait_for_hba_online(vha);
+
+               /* Issue MPI reset */
+               scsi_block_requests(vha->host);
+               if (qla81xx_restart_mpi_firmware(vha) != QLA_SUCCESS)
+                       qla_printk(KERN_WARNING, ha,
+                           "MPI reset failed on (%ld).\n", vha->host_no);
+               scsi_unblock_requests(vha->host);
+               break;
+       }
+       return count;
+}
+
+static struct bin_attribute sysfs_reset_attr = {
+       .attr = {
+               .name = "reset",
+               .mode = S_IWUSR,
+       },
+       .size = 0,
+       .write = qla2x00_sysfs_write_reset,
+};
+
 static struct sysfs_entry {
        char *name;
        struct bin_attribute *attr;
@@ -490,6 +545,7 @@ static struct sysfs_entry {
        { "optrom_ctl", &sysfs_optrom_ctl_attr, },
        { "vpd", &sysfs_vpd_attr, 1 },
        { "sfp", &sysfs_sfp_attr, 1 },
+       { "reset", &sysfs_reset_attr, },
        { NULL },
 };
 
index 9830193..e47c4c3 100644 (file)
@@ -1403,6 +1403,7 @@ struct access_chip_rsp_84xx {
 #define MBA_IDC_TIME_EXT       0x8102
 
 #define MBC_IDC_ACK            0x101
+#define MBC_RESTART_MPI_FW     0x3d
 #define MBC_FLASH_ACCESS_CTRL  0x3e    /* Control flash access. */
 
 /* Flash access control option field bit definitions */
index c75e7f9..41c3f41 100644 (file)
@@ -73,6 +73,7 @@ extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
 extern int qla2x00_post_aen_work(struct scsi_qla_host *, enum
     fc_host_event_code, u32);
 extern int qla2x00_post_idc_ack_work(struct scsi_qla_host *, uint16_t *);
+extern int qla81xx_restart_mpi_firmware(scsi_qla_host_t *);
 
 extern void qla2x00_abort_fcport_cmds(fc_port_t *);
 extern struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *,
index 2bc08d3..dc5e5d9 100644 (file)
@@ -3325,3 +3325,29 @@ qla81xx_fac_erase_sector(scsi_qla_host_t *vha, uint32_t start, uint32_t finish)
 
        return rval;
 }
+
+int
+qla81xx_restart_mpi_firmware(scsi_qla_host_t *vha)
+{
+       int rval = 0;
+       mbx_cmd_t mc;
+       mbx_cmd_t *mcp = &mc;
+
+       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+
+       mcp->mb[0] = MBC_RESTART_MPI_FW;
+       mcp->out_mb = MBX_0;
+       mcp->in_mb = MBX_0|MBX_1;
+       mcp->tov = MBX_TOV_SECONDS;
+       mcp->flags = 0;
+       rval = qla2x00_mailbox_command(vha, mcp);
+
+       if (rval != QLA_SUCCESS) {
+               DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=0x%x mb[1]=0x%x.\n",
+                   __func__, vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
+       } else {
+               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+       }
+
+       return rval;
+}