ipg: use NULL, not zero, for pointers
[cascardo/linux.git] / drivers / scsi / qla2xxx / qla_mbx.c
index beff743..250d2f6 100644 (file)
@@ -681,9 +681,9 @@ qla2x00_verify_checksum(scsi_qla_host_t *ha, uint32_t risc_addr)
  * Context:
  *     Kernel context.
  */
-int
-qla2x00_issue_iocb(scsi_qla_host_t *ha, void*  buffer, dma_addr_t phys_addr,
-    size_t size)
+static int
+qla2x00_issue_iocb_timeout(scsi_qla_host_t *ha, void *buffer,
+    dma_addr_t phys_addr, size_t size, uint32_t tov)
 {
        int             rval;
        mbx_cmd_t       mc;
@@ -697,7 +697,7 @@ qla2x00_issue_iocb(scsi_qla_host_t *ha, void*  buffer, dma_addr_t phys_addr,
        mcp->mb[7] = LSW(MSD(phys_addr));
        mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
        mcp->in_mb = MBX_2|MBX_0;
-       mcp->tov = MBX_TOV_SECONDS;
+       mcp->tov = tov;
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(ha, mcp);
 
@@ -718,6 +718,14 @@ qla2x00_issue_iocb(scsi_qla_host_t *ha, void*  buffer, dma_addr_t phys_addr,
        return rval;
 }
 
+int
+qla2x00_issue_iocb(scsi_qla_host_t *ha, void *buffer, dma_addr_t phys_addr,
+    size_t size)
+{
+       return qla2x00_issue_iocb_timeout(ha, buffer, phys_addr, size,
+           MBX_TOV_SECONDS);
+}
+
 /*
  * qla2x00_abort_command
  *     Abort command aborts a specified IOCB.
@@ -776,7 +784,6 @@ qla2x00_abort_command(scsi_qla_host_t *ha, srb_t *sp)
                DEBUG2_3_11(printk("qla2x00_abort_command(%ld): failed=%x.\n",
                    ha->host_no, rval));
        } else {
-               sp->flags |= SRB_ABORT_PENDING;
                DEBUG11(printk("qla2x00_abort_command(%ld): done.\n",
                    ha->host_no));
        }
@@ -1208,7 +1215,7 @@ gpd_error_out:
  *     Kernel context.
  */
 int
-qla2x00_get_firmware_state(scsi_qla_host_t *ha, uint16_t *dptr)
+qla2x00_get_firmware_state(scsi_qla_host_t *ha, uint16_t *states)
 {
        int rval;
        mbx_cmd_t mc;
@@ -1219,13 +1226,15 @@ qla2x00_get_firmware_state(scsi_qla_host_t *ha, uint16_t *dptr)
 
        mcp->mb[0] = MBC_GET_FIRMWARE_STATE;
        mcp->out_mb = MBX_0;
-       mcp->in_mb = MBX_2|MBX_1|MBX_0;
+       mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0;
        mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(ha, mcp);
 
-       /* Return firmware state. */
-       *dptr = mcp->mb[1];
+       /* Return firmware states. */
+       states[0] = mcp->mb[1];
+       states[1] = mcp->mb[2];
+       states[2] = mcp->mb[3];
 
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
@@ -1459,7 +1468,7 @@ qla24xx_login_fabric(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
        lg->port_id[0] = al_pa;
        lg->port_id[1] = area;
        lg->port_id[2] = domain;
-       lg->vp_index = cpu_to_le16(ha->vp_idx);
+       lg->vp_index = ha->vp_idx;
        rval = qla2x00_issue_iocb(ha, lg, lg_dma, 0);
        if (rval != QLA_SUCCESS) {
                DEBUG2_3_11(printk("%s(%ld): failed to issue Login IOCB "
@@ -1714,7 +1723,7 @@ qla24xx_fabric_logout(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
        lg->port_id[0] = al_pa;
        lg->port_id[1] = area;
        lg->port_id[2] = domain;
-       lg->vp_index = cpu_to_le16(ha->vp_idx);
+       lg->vp_index = ha->vp_idx;
        rval = qla2x00_issue_iocb(ha, lg, lg_dma, 0);
        if (rval != QLA_SUCCESS) {
                DEBUG2_3_11(printk("%s(%ld): failed to issue Logout IOCB "
@@ -2200,7 +2209,6 @@ qla24xx_abort_command(scsi_qla_host_t *ha, srb_t *sp)
                rval = QLA_FUNCTION_FAILED;
        } else {
                DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
-               sp->flags |= SRB_ABORT_PENDING;
        }
 
        dma_pool_free(ha->s_dma_pool, abt, abt_dma);
@@ -2295,8 +2303,6 @@ qla24xx_lun_reset(struct fc_port *fcport, unsigned int l)
        return __qla24xx_issue_tmf("Lun", TCF_LUN_RESET, fcport, l);
 }
 
-#if 0
-
 int
 qla2x00_system_error(scsi_qla_host_t *ha)
 {
@@ -2304,7 +2310,7 @@ qla2x00_system_error(scsi_qla_host_t *ha)
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
-       if (!IS_FWI2_CAPABLE(ha))
+       if (!IS_QLA23XX(ha) && !IS_FWI2_CAPABLE(ha))
                return QLA_FUNCTION_FAILED;
 
        DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
@@ -2326,8 +2332,6 @@ qla2x00_system_error(scsi_qla_host_t *ha)
        return rval;
 }
 
-#endif  /*  0  */
-
 /**
  * qla2x00_set_serdes_params() -
  * @ha: HA context
@@ -2500,7 +2504,7 @@ qla2x00_enable_fce_trace(scsi_qla_host_t *ha, dma_addr_t fce_dma,
                if (mb)
                        memcpy(mb, mcp->mb, 8 * sizeof(*mb));
                if (dwords)
-                       *dwords = mcp->mb[6];
+                       *dwords = buffers;
        }
 
        return rval;
@@ -2634,12 +2638,11 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *ha,
        struct vp_rpt_id_entry_24xx *rptid_entry)
 {
        uint8_t vp_idx;
+       uint16_t stat = le16_to_cpu(rptid_entry->vp_idx);
        scsi_qla_host_t *vha;
 
        if (rptid_entry->entry_status != 0)
                return;
-       if (rptid_entry->entry_status != __constant_cpu_to_le16(CS_COMPLETE))
-               return;
 
        if (rptid_entry->format == 0) {
                DEBUG15(printk("%s:format 0 : scsi(%ld) number of VPs setup %d,"
@@ -2649,17 +2652,17 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *ha,
                        rptid_entry->port_id[2], rptid_entry->port_id[1],
                        rptid_entry->port_id[0]));
        } else if (rptid_entry->format == 1) {
-               vp_idx = LSB(rptid_entry->vp_idx);
+               vp_idx = LSB(stat);
                DEBUG15(printk("%s:format 1: scsi(%ld): VP[%d] enabled "
                    "- status %d - "
                    "with port id %02x%02x%02x\n",__func__,ha->host_no,
-                   vp_idx, MSB(rptid_entry->vp_idx),
+                   vp_idx, MSB(stat),
                    rptid_entry->port_id[2], rptid_entry->port_id[1],
                    rptid_entry->port_id[0]));
                if (vp_idx == 0)
                        return;
 
-               if (MSB(rptid_entry->vp_idx) == 1)
+               if (MSB(stat) == 1)
                        return;
 
                list_for_each_entry(vha, &ha->vp_list, vp_list)
@@ -2800,9 +2803,9 @@ qla24xx_control_vp(scsi_qla_host_t *vha, int cmd)
         */
        map = (vp_index - 1) / 8;
        pos = (vp_index - 1) & 7;
-       down(&ha->vport_sem);
+       mutex_lock(&ha->vport_lock);
        vce->vp_idx_map[map] |= 1 << pos;
-       up(&ha->vport_sem);
+       mutex_unlock(&ha->vport_lock);
 
        rval = qla2x00_issue_iocb(ha, vce, vce_dma, 0);
        if (rval != QLA_SUCCESS) {
@@ -2937,3 +2940,104 @@ qla2x00_dump_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t addr,
 
        return rval;
 }
+
+/* 84XX Support **************************************************************/
+
+struct cs84xx_mgmt_cmd {
+       union {
+               struct verify_chip_entry_84xx req;
+               struct verify_chip_rsp_84xx rsp;
+       } p;
+};
+
+int
+qla84xx_verify_chip(struct scsi_qla_host *ha, uint16_t *status)
+{
+       int rval, retry;
+       struct cs84xx_mgmt_cmd *mn;
+       dma_addr_t mn_dma;
+       uint16_t options;
+       unsigned long flags;
+
+       DEBUG16(printk("%s(%ld): entered.\n", __func__, ha->host_no));
+
+       mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma);
+       if (mn == NULL) {
+               DEBUG2_3(printk("%s(%ld): failed to allocate Verify ISP84XX "
+                   "IOCB.\n", __func__, ha->host_no));
+               return QLA_MEMORY_ALLOC_FAILED;
+       }
+
+       /* Force Update? */
+       options = ha->cs84xx->fw_update ? VCO_FORCE_UPDATE : 0;
+       /* Diagnostic firmware? */
+       /* options |= MENLO_DIAG_FW; */
+       /* We update the firmware with only one data sequence. */
+       options |= VCO_END_OF_DATA;
+
+       do {
+               retry = 0;
+               memset(mn, 0, sizeof(*mn));
+               mn->p.req.entry_type = VERIFY_CHIP_IOCB_TYPE;
+               mn->p.req.entry_count = 1;
+               mn->p.req.options = cpu_to_le16(options);
+
+               DEBUG16(printk("%s(%ld): Dump of Verify Request.\n", __func__,
+                   ha->host_no));
+               DEBUG16(qla2x00_dump_buffer((uint8_t *)mn,
+                   sizeof(*mn)));
+
+               rval = qla2x00_issue_iocb_timeout(ha, mn, mn_dma, 0, 120);
+               if (rval != QLA_SUCCESS) {
+                       DEBUG2_16(printk("%s(%ld): failed to issue Verify "
+                           "IOCB (%x).\n", __func__, ha->host_no, rval));
+                       goto verify_done;
+               }
+
+               DEBUG16(printk("%s(%ld): Dump of Verify Response.\n", __func__,
+                   ha->host_no));
+               DEBUG16(qla2x00_dump_buffer((uint8_t *)mn,
+                   sizeof(*mn)));
+
+               status[0] = le16_to_cpu(mn->p.rsp.comp_status);
+               status[1] = status[0] == CS_VCS_CHIP_FAILURE ?
+                   le16_to_cpu(mn->p.rsp.failure_code) : 0;
+               DEBUG2_16(printk("%s(%ld): cs=%x fc=%x\n", __func__,
+                   ha->host_no, status[0], status[1]));
+
+               if (status[0] != CS_COMPLETE) {
+                       rval = QLA_FUNCTION_FAILED;
+                       if (!(options & VCO_DONT_UPDATE_FW)) {
+                               DEBUG2_16(printk("%s(%ld): Firmware update "
+                                   "failed. Retrying without update "
+                                   "firmware.\n", __func__, ha->host_no));
+                               options |= VCO_DONT_UPDATE_FW;
+                               options &= ~VCO_FORCE_UPDATE;
+                               retry = 1;
+                       }
+               } else {
+                       DEBUG2_16(printk("%s(%ld): firmware updated to %x.\n",
+                           __func__, ha->host_no,
+                           le32_to_cpu(mn->p.rsp.fw_ver)));
+
+                       /* NOTE: we only update OP firmware. */
+                       spin_lock_irqsave(&ha->cs84xx->access_lock, flags);
+                       ha->cs84xx->op_fw_version =
+                           le32_to_cpu(mn->p.rsp.fw_ver);
+                       spin_unlock_irqrestore(&ha->cs84xx->access_lock,
+                           flags);
+               }
+       } while (retry);
+
+verify_done:
+       dma_pool_free(ha->s_dma_pool, mn, mn_dma);
+
+       if (rval != QLA_SUCCESS) {
+               DEBUG2_16(printk("%s(%ld): failed=%x.\n", __func__,
+                   ha->host_no, rval));
+       } else {
+               DEBUG16(printk("%s(%ld): done.\n", __func__, ha->host_no));
+       }
+
+       return rval;
+}