1afaf5a2dSDavid Somayajulu /* 2afaf5a2dSDavid Somayajulu * QLogic iSCSI HBA Driver 3c68cdbf0SVikas Chaudhary * Copyright (c) 2003-2012 QLogic Corporation 4afaf5a2dSDavid Somayajulu * 5afaf5a2dSDavid Somayajulu * See LICENSE.qla4xxx for copyright and licensing details. 6afaf5a2dSDavid Somayajulu */ 7afaf5a2dSDavid Somayajulu 8afaf5a2dSDavid Somayajulu #include "ql4_def.h" 9c0e344c9SDavid C Somayajulu #include "ql4_glbl.h" 10c0e344c9SDavid C Somayajulu #include "ql4_dbg.h" 11c0e344c9SDavid C Somayajulu #include "ql4_inline.h" 12*cfb27874SManish Dusane #include "ql4_version.h" 13afaf5a2dSDavid Somayajulu 1433693c7aSVikas Chaudhary void qla4xxx_queue_mbox_cmd(struct scsi_qla_host *ha, uint32_t *mbx_cmd, 1533693c7aSVikas Chaudhary int in_count) 1633693c7aSVikas Chaudhary { 1733693c7aSVikas Chaudhary int i; 1833693c7aSVikas Chaudhary 1933693c7aSVikas Chaudhary /* Load all mailbox registers, except mailbox 0. */ 2033693c7aSVikas Chaudhary for (i = 1; i < in_count; i++) 2133693c7aSVikas Chaudhary writel(mbx_cmd[i], &ha->reg->mailbox[i]); 2233693c7aSVikas Chaudhary 2333693c7aSVikas Chaudhary /* Wakeup firmware */ 2433693c7aSVikas Chaudhary writel(mbx_cmd[0], &ha->reg->mailbox[0]); 2533693c7aSVikas Chaudhary readl(&ha->reg->mailbox[0]); 2633693c7aSVikas Chaudhary writel(set_rmask(CSR_INTR_RISC), &ha->reg->ctrl_status); 2733693c7aSVikas Chaudhary readl(&ha->reg->ctrl_status); 2833693c7aSVikas Chaudhary } 2933693c7aSVikas Chaudhary 3033693c7aSVikas Chaudhary void qla4xxx_process_mbox_intr(struct scsi_qla_host *ha, int out_count) 3133693c7aSVikas Chaudhary { 3233693c7aSVikas Chaudhary int intr_status; 3333693c7aSVikas Chaudhary 3433693c7aSVikas Chaudhary intr_status = readl(&ha->reg->ctrl_status); 3533693c7aSVikas Chaudhary if (intr_status & INTR_PENDING) { 3633693c7aSVikas Chaudhary /* 3733693c7aSVikas Chaudhary * Service the interrupt. 3833693c7aSVikas Chaudhary * The ISR will save the mailbox status registers 3933693c7aSVikas Chaudhary * to a temporary storage location in the adapter structure. 4033693c7aSVikas Chaudhary */ 4133693c7aSVikas Chaudhary ha->mbox_status_count = out_count; 4233693c7aSVikas Chaudhary ha->isp_ops->interrupt_service_routine(ha, intr_status); 4333693c7aSVikas Chaudhary } 4433693c7aSVikas Chaudhary } 45afaf5a2dSDavid Somayajulu 46afaf5a2dSDavid Somayajulu /** 47afaf5a2dSDavid Somayajulu * qla4xxx_mailbox_command - issues mailbox commands 48afaf5a2dSDavid Somayajulu * @ha: Pointer to host adapter structure. 49afaf5a2dSDavid Somayajulu * @inCount: number of mailbox registers to load. 50afaf5a2dSDavid Somayajulu * @outCount: number of mailbox registers to return. 51afaf5a2dSDavid Somayajulu * @mbx_cmd: data pointer for mailbox in registers. 52afaf5a2dSDavid Somayajulu * @mbx_sts: data pointer for mailbox out registers. 53afaf5a2dSDavid Somayajulu * 5470f23fd6SJustin P. Mattock * This routine issue mailbox commands and waits for completion. 55afaf5a2dSDavid Somayajulu * If outCount is 0, this routine completes successfully WITHOUT waiting 56afaf5a2dSDavid Somayajulu * for the mailbox command to complete. 57afaf5a2dSDavid Somayajulu **/ 58f4f5df23SVikas Chaudhary int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, 59afaf5a2dSDavid Somayajulu uint8_t outCount, uint32_t *mbx_cmd, 60afaf5a2dSDavid Somayajulu uint32_t *mbx_sts) 61afaf5a2dSDavid Somayajulu { 62afaf5a2dSDavid Somayajulu int status = QLA_ERROR; 63afaf5a2dSDavid Somayajulu uint8_t i; 64afaf5a2dSDavid Somayajulu u_long wait_count; 65afaf5a2dSDavid Somayajulu unsigned long flags = 0; 6699b53bf5SPrasanna Mumbai uint32_t dev_state; 67afaf5a2dSDavid Somayajulu 68afaf5a2dSDavid Somayajulu /* Make sure that pointers are valid */ 69afaf5a2dSDavid Somayajulu if (!mbx_cmd || !mbx_sts) { 70afaf5a2dSDavid Somayajulu DEBUG2(printk("scsi%ld: %s: Invalid mbx_cmd or mbx_sts " 71afaf5a2dSDavid Somayajulu "pointer\n", ha->host_no, __func__)); 72477ffb9dSDavid C Somayajulu return status; 73477ffb9dSDavid C Somayajulu } 7421033639SNilesh Javali 7513483730SMike Christie if (is_qla40XX(ha)) { 7613483730SMike Christie if (test_bit(AF_HA_REMOVAL, &ha->flags)) { 7713483730SMike Christie DEBUG2(ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: " 7813483730SMike Christie "prematurely completing mbx cmd as " 7913483730SMike Christie "adapter removal detected\n", 8013483730SMike Christie ha->host_no, __func__)); 8113483730SMike Christie return status; 8213483730SMike Christie } 8313483730SMike Christie } 8413483730SMike Christie 852232be0dSLalit Chandivade if ((is_aer_supported(ha)) && 862232be0dSLalit Chandivade (test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags))) { 872232be0dSLalit Chandivade DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Perm failure on EEH, " 882232be0dSLalit Chandivade "timeout MBX Exiting.\n", ha->host_no, __func__)); 892232be0dSLalit Chandivade return status; 902232be0dSLalit Chandivade } 912232be0dSLalit Chandivade 92477ffb9dSDavid C Somayajulu /* Mailbox code active */ 93477ffb9dSDavid C Somayajulu wait_count = MBOX_TOV * 100; 94477ffb9dSDavid C Somayajulu 95477ffb9dSDavid C Somayajulu while (wait_count--) { 96477ffb9dSDavid C Somayajulu mutex_lock(&ha->mbox_sem); 97477ffb9dSDavid C Somayajulu if (!test_bit(AF_MBOX_COMMAND, &ha->flags)) { 98477ffb9dSDavid C Somayajulu set_bit(AF_MBOX_COMMAND, &ha->flags); 99477ffb9dSDavid C Somayajulu mutex_unlock(&ha->mbox_sem); 100477ffb9dSDavid C Somayajulu break; 101477ffb9dSDavid C Somayajulu } 102477ffb9dSDavid C Somayajulu mutex_unlock(&ha->mbox_sem); 103477ffb9dSDavid C Somayajulu if (!wait_count) { 104477ffb9dSDavid C Somayajulu DEBUG2(printk("scsi%ld: %s: mbox_sem failed\n", 105477ffb9dSDavid C Somayajulu ha->host_no, __func__)); 106477ffb9dSDavid C Somayajulu return status; 107477ffb9dSDavid C Somayajulu } 108477ffb9dSDavid C Somayajulu msleep(10); 109afaf5a2dSDavid Somayajulu } 110afaf5a2dSDavid Somayajulu 1116e7b4292SVikas Chaudhary if (is_qla80XX(ha)) { 1125f50aa3aSLalit Chandivade if (test_bit(AF_FW_RECOVERY, &ha->flags)) { 1135f50aa3aSLalit Chandivade DEBUG2(ql4_printk(KERN_WARNING, ha, 1145f50aa3aSLalit Chandivade "scsi%ld: %s: prematurely completing mbx cmd as firmware recovery detected\n", 1155f50aa3aSLalit Chandivade ha->host_no, __func__)); 1165f50aa3aSLalit Chandivade goto mbox_exit; 1175f50aa3aSLalit Chandivade } 1185f50aa3aSLalit Chandivade /* Do not send any mbx cmd if h/w is in failed state*/ 11933693c7aSVikas Chaudhary ha->isp_ops->idc_lock(ha); 12033693c7aSVikas Chaudhary dev_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DEV_STATE); 12133693c7aSVikas Chaudhary ha->isp_ops->idc_unlock(ha); 122de8c72daSVikas Chaudhary if (dev_state == QLA8XXX_DEV_FAILED) { 1235f50aa3aSLalit Chandivade ql4_printk(KERN_WARNING, ha, 1245f50aa3aSLalit Chandivade "scsi%ld: %s: H/W is in failed state, do not send any mailbox commands\n", 1255f50aa3aSLalit Chandivade ha->host_no, __func__); 1265f50aa3aSLalit Chandivade goto mbox_exit; 1275f50aa3aSLalit Chandivade } 1285f50aa3aSLalit Chandivade } 1295f50aa3aSLalit Chandivade 130afaf5a2dSDavid Somayajulu spin_lock_irqsave(&ha->hardware_lock, flags); 131f4f5df23SVikas Chaudhary 132afaf5a2dSDavid Somayajulu ha->mbox_status_count = outCount; 133afaf5a2dSDavid Somayajulu for (i = 0; i < outCount; i++) 134afaf5a2dSDavid Somayajulu ha->mbox_status[i] = 0; 135afaf5a2dSDavid Somayajulu 13633693c7aSVikas Chaudhary /* Queue the mailbox command to the firmware */ 13733693c7aSVikas Chaudhary ha->isp_ops->queue_mailbox_command(ha, mbx_cmd, inCount); 138f4f5df23SVikas Chaudhary 139afaf5a2dSDavid Somayajulu spin_unlock_irqrestore(&ha->hardware_lock, flags); 140afaf5a2dSDavid Somayajulu 141afaf5a2dSDavid Somayajulu /* Wait for completion */ 142afaf5a2dSDavid Somayajulu 143afaf5a2dSDavid Somayajulu /* 144afaf5a2dSDavid Somayajulu * If we don't want status, don't wait for the mailbox command to 145afaf5a2dSDavid Somayajulu * complete. For example, MBOX_CMD_RESET_FW doesn't return status, 146afaf5a2dSDavid Somayajulu * you must poll the inbound Interrupt Mask for completion. 147afaf5a2dSDavid Somayajulu */ 148afaf5a2dSDavid Somayajulu if (outCount == 0) { 149afaf5a2dSDavid Somayajulu status = QLA_SUCCESS; 150afaf5a2dSDavid Somayajulu goto mbox_exit; 151afaf5a2dSDavid Somayajulu } 152f4f5df23SVikas Chaudhary 153f4f5df23SVikas Chaudhary /* 154f4f5df23SVikas Chaudhary * Wait for completion: Poll or completion queue 155f4f5df23SVikas Chaudhary */ 156f4f5df23SVikas Chaudhary if (test_bit(AF_IRQ_ATTACHED, &ha->flags) && 157f4f5df23SVikas Chaudhary test_bit(AF_INTERRUPTS_ON, &ha->flags) && 158f4f5df23SVikas Chaudhary test_bit(AF_ONLINE, &ha->flags) && 1597eece5a0SKaren Higgins !test_bit(AF_HA_REMOVAL, &ha->flags)) { 160f4f5df23SVikas Chaudhary /* Do not poll for completion. Use completion queue */ 161f4f5df23SVikas Chaudhary set_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags); 162f4f5df23SVikas Chaudhary wait_for_completion_timeout(&ha->mbx_intr_comp, MBOX_TOV * HZ); 163f4f5df23SVikas Chaudhary clear_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags); 164f4f5df23SVikas Chaudhary } else { 165f4f5df23SVikas Chaudhary /* Poll for command to complete */ 166afaf5a2dSDavid Somayajulu wait_count = jiffies + MBOX_TOV * HZ; 167afaf5a2dSDavid Somayajulu while (test_bit(AF_MBOX_COMMAND_DONE, &ha->flags) == 0) { 168afaf5a2dSDavid Somayajulu if (time_after_eq(jiffies, wait_count)) 169afaf5a2dSDavid Somayajulu break; 1702232be0dSLalit Chandivade 171afaf5a2dSDavid Somayajulu /* 172afaf5a2dSDavid Somayajulu * Service the interrupt. 173afaf5a2dSDavid Somayajulu * The ISR will save the mailbox status registers 174afaf5a2dSDavid Somayajulu * to a temporary storage location in the adapter 175afaf5a2dSDavid Somayajulu * structure. 176afaf5a2dSDavid Somayajulu */ 177f4f5df23SVikas Chaudhary 178f4f5df23SVikas Chaudhary spin_lock_irqsave(&ha->hardware_lock, flags); 17933693c7aSVikas Chaudhary ha->isp_ops->process_mailbox_interrupt(ha, outCount); 180afaf5a2dSDavid Somayajulu spin_unlock_irqrestore(&ha->hardware_lock, flags); 181afaf5a2dSDavid Somayajulu msleep(10); 182afaf5a2dSDavid Somayajulu } 183f4f5df23SVikas Chaudhary } 184afaf5a2dSDavid Somayajulu 185afaf5a2dSDavid Somayajulu /* Check for mailbox timeout. */ 186afaf5a2dSDavid Somayajulu if (!test_bit(AF_MBOX_COMMAND_DONE, &ha->flags)) { 1876e7b4292SVikas Chaudhary if (is_qla80XX(ha) && 18821033639SNilesh Javali test_bit(AF_FW_RECOVERY, &ha->flags)) { 18921033639SNilesh Javali DEBUG2(ql4_printk(KERN_INFO, ha, 19021033639SNilesh Javali "scsi%ld: %s: prematurely completing mbx cmd as " 19121033639SNilesh Javali "firmware recovery detected\n", 19221033639SNilesh Javali ha->host_no, __func__)); 19321033639SNilesh Javali goto mbox_exit; 19421033639SNilesh Javali } 195afaf5a2dSDavid Somayajulu DEBUG2(printk("scsi%ld: Mailbox Cmd 0x%08X timed out ...," 196afaf5a2dSDavid Somayajulu " Scheduling Adapter Reset\n", ha->host_no, 197afaf5a2dSDavid Somayajulu mbx_cmd[0])); 198afaf5a2dSDavid Somayajulu ha->mailbox_timeout_count++; 199afaf5a2dSDavid Somayajulu mbx_sts[0] = (-1); 200afaf5a2dSDavid Somayajulu set_bit(DPC_RESET_HA, &ha->dpc_flags); 201e6bd0ebdSGiridhar Malavali if (is_qla8022(ha)) { 202e6bd0ebdSGiridhar Malavali ql4_printk(KERN_INFO, ha, 203e6bd0ebdSGiridhar Malavali "disabling pause transmit on port 0 & 1.\n"); 204f8086f4fSVikas Chaudhary qla4_82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x98, 205e6bd0ebdSGiridhar Malavali CRB_NIU_XG_PAUSE_CTL_P0 | 206e6bd0ebdSGiridhar Malavali CRB_NIU_XG_PAUSE_CTL_P1); 207e6bd0ebdSGiridhar Malavali } 208afaf5a2dSDavid Somayajulu goto mbox_exit; 209afaf5a2dSDavid Somayajulu } 210afaf5a2dSDavid Somayajulu 211afaf5a2dSDavid Somayajulu /* 212afaf5a2dSDavid Somayajulu * Copy the mailbox out registers to the caller's mailbox in/out 213afaf5a2dSDavid Somayajulu * structure. 214afaf5a2dSDavid Somayajulu */ 215afaf5a2dSDavid Somayajulu spin_lock_irqsave(&ha->hardware_lock, flags); 216afaf5a2dSDavid Somayajulu for (i = 0; i < outCount; i++) 217afaf5a2dSDavid Somayajulu mbx_sts[i] = ha->mbox_status[i]; 218afaf5a2dSDavid Somayajulu 219afaf5a2dSDavid Somayajulu /* Set return status and error flags (if applicable). */ 220afaf5a2dSDavid Somayajulu switch (ha->mbox_status[0]) { 221afaf5a2dSDavid Somayajulu case MBOX_STS_COMMAND_COMPLETE: 222afaf5a2dSDavid Somayajulu status = QLA_SUCCESS; 223afaf5a2dSDavid Somayajulu break; 224afaf5a2dSDavid Somayajulu 225afaf5a2dSDavid Somayajulu case MBOX_STS_INTERMEDIATE_COMPLETION: 226afaf5a2dSDavid Somayajulu status = QLA_SUCCESS; 227afaf5a2dSDavid Somayajulu break; 228afaf5a2dSDavid Somayajulu 229afaf5a2dSDavid Somayajulu case MBOX_STS_BUSY: 230afaf5a2dSDavid Somayajulu DEBUG2( printk("scsi%ld: %s: Cmd = %08X, ISP BUSY\n", 231afaf5a2dSDavid Somayajulu ha->host_no, __func__, mbx_cmd[0])); 232afaf5a2dSDavid Somayajulu ha->mailbox_timeout_count++; 233afaf5a2dSDavid Somayajulu break; 234afaf5a2dSDavid Somayajulu 235afaf5a2dSDavid Somayajulu default: 236afaf5a2dSDavid Somayajulu DEBUG2(printk("scsi%ld: %s: **** FAILED, cmd = %08X, " 237afaf5a2dSDavid Somayajulu "sts = %08X ****\n", ha->host_no, __func__, 238afaf5a2dSDavid Somayajulu mbx_cmd[0], mbx_sts[0])); 239afaf5a2dSDavid Somayajulu break; 240afaf5a2dSDavid Somayajulu } 241afaf5a2dSDavid Somayajulu spin_unlock_irqrestore(&ha->hardware_lock, flags); 242afaf5a2dSDavid Somayajulu 243afaf5a2dSDavid Somayajulu mbox_exit: 244477ffb9dSDavid C Somayajulu mutex_lock(&ha->mbox_sem); 245afaf5a2dSDavid Somayajulu clear_bit(AF_MBOX_COMMAND, &ha->flags); 246afaf5a2dSDavid Somayajulu mutex_unlock(&ha->mbox_sem); 247477ffb9dSDavid C Somayajulu clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags); 248afaf5a2dSDavid Somayajulu 249afaf5a2dSDavid Somayajulu return status; 250afaf5a2dSDavid Somayajulu } 251afaf5a2dSDavid Somayajulu 252068237c8STej Parkash /** 253068237c8STej Parkash * qla4xxx_get_minidump_template - Get the firmware template 254068237c8STej Parkash * @ha: Pointer to host adapter structure. 255068237c8STej Parkash * @phys_addr: dma address for template 256068237c8STej Parkash * 257068237c8STej Parkash * Obtain the minidump template from firmware during initialization 258068237c8STej Parkash * as it may not be available when minidump is desired. 259068237c8STej Parkash **/ 260068237c8STej Parkash int qla4xxx_get_minidump_template(struct scsi_qla_host *ha, 261068237c8STej Parkash dma_addr_t phys_addr) 262068237c8STej Parkash { 263068237c8STej Parkash uint32_t mbox_cmd[MBOX_REG_COUNT]; 264068237c8STej Parkash uint32_t mbox_sts[MBOX_REG_COUNT]; 265068237c8STej Parkash int status; 266068237c8STej Parkash 267068237c8STej Parkash memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 268068237c8STej Parkash memset(&mbox_sts, 0, sizeof(mbox_sts)); 269068237c8STej Parkash 270068237c8STej Parkash mbox_cmd[0] = MBOX_CMD_MINIDUMP; 271068237c8STej Parkash mbox_cmd[1] = MINIDUMP_GET_TMPLT_SUBCOMMAND; 272068237c8STej Parkash mbox_cmd[2] = LSDW(phys_addr); 273068237c8STej Parkash mbox_cmd[3] = MSDW(phys_addr); 274068237c8STej Parkash mbox_cmd[4] = ha->fw_dump_tmplt_size; 275068237c8STej Parkash mbox_cmd[5] = 0; 276068237c8STej Parkash 277068237c8STej Parkash status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0], 278068237c8STej Parkash &mbox_sts[0]); 279068237c8STej Parkash if (status != QLA_SUCCESS) { 280068237c8STej Parkash DEBUG2(ql4_printk(KERN_INFO, ha, 281068237c8STej Parkash "scsi%ld: %s: Cmd = %08X, mbx[0] = 0x%04x, mbx[1] = 0x%04x\n", 282068237c8STej Parkash ha->host_no, __func__, mbox_cmd[0], 283068237c8STej Parkash mbox_sts[0], mbox_sts[1])); 284068237c8STej Parkash } 285068237c8STej Parkash return status; 286068237c8STej Parkash } 287068237c8STej Parkash 288068237c8STej Parkash /** 289068237c8STej Parkash * qla4xxx_req_template_size - Get minidump template size from firmware. 290068237c8STej Parkash * @ha: Pointer to host adapter structure. 291068237c8STej Parkash **/ 292068237c8STej Parkash int qla4xxx_req_template_size(struct scsi_qla_host *ha) 293068237c8STej Parkash { 294068237c8STej Parkash uint32_t mbox_cmd[MBOX_REG_COUNT]; 295068237c8STej Parkash uint32_t mbox_sts[MBOX_REG_COUNT]; 296068237c8STej Parkash int status; 297068237c8STej Parkash 298068237c8STej Parkash memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 299068237c8STej Parkash memset(&mbox_sts, 0, sizeof(mbox_sts)); 300068237c8STej Parkash 301068237c8STej Parkash mbox_cmd[0] = MBOX_CMD_MINIDUMP; 302068237c8STej Parkash mbox_cmd[1] = MINIDUMP_GET_SIZE_SUBCOMMAND; 303068237c8STej Parkash 304068237c8STej Parkash status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 8, &mbox_cmd[0], 305068237c8STej Parkash &mbox_sts[0]); 306068237c8STej Parkash if (status == QLA_SUCCESS) { 307068237c8STej Parkash ha->fw_dump_tmplt_size = mbox_sts[1]; 308068237c8STej Parkash DEBUG2(ql4_printk(KERN_INFO, ha, 309068237c8STej Parkash "%s: sts[0]=0x%04x, template size=0x%04x, size_cm_02=0x%04x, size_cm_04=0x%04x, size_cm_08=0x%04x, size_cm_10=0x%04x, size_cm_FF=0x%04x, version=0x%04x\n", 310068237c8STej Parkash __func__, mbox_sts[0], mbox_sts[1], 311068237c8STej Parkash mbox_sts[2], mbox_sts[3], mbox_sts[4], 312068237c8STej Parkash mbox_sts[5], mbox_sts[6], mbox_sts[7])); 313068237c8STej Parkash if (ha->fw_dump_tmplt_size == 0) 314068237c8STej Parkash status = QLA_ERROR; 315068237c8STej Parkash } else { 316068237c8STej Parkash ql4_printk(KERN_WARNING, ha, 317068237c8STej Parkash "%s: Error sts[0]=0x%04x, mbx[1]=0x%04x\n", 318068237c8STej Parkash __func__, mbox_sts[0], mbox_sts[1]); 319068237c8STej Parkash status = QLA_ERROR; 320068237c8STej Parkash } 321068237c8STej Parkash 322068237c8STej Parkash return status; 323068237c8STej Parkash } 324068237c8STej Parkash 32521033639SNilesh Javali void qla4xxx_mailbox_premature_completion(struct scsi_qla_host *ha) 32621033639SNilesh Javali { 32721033639SNilesh Javali set_bit(AF_FW_RECOVERY, &ha->flags); 32821033639SNilesh Javali ql4_printk(KERN_INFO, ha, "scsi%ld: %s: set FW RECOVERY!\n", 32921033639SNilesh Javali ha->host_no, __func__); 33021033639SNilesh Javali 33121033639SNilesh Javali if (test_bit(AF_MBOX_COMMAND, &ha->flags)) { 33221033639SNilesh Javali if (test_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags)) { 33321033639SNilesh Javali complete(&ha->mbx_intr_comp); 33421033639SNilesh Javali ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Due to fw " 33521033639SNilesh Javali "recovery, doing premature completion of " 33621033639SNilesh Javali "mbx cmd\n", ha->host_no, __func__); 33721033639SNilesh Javali 33821033639SNilesh Javali } else { 33921033639SNilesh Javali set_bit(AF_MBOX_COMMAND_DONE, &ha->flags); 34021033639SNilesh Javali ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Due to fw " 34121033639SNilesh Javali "recovery, doing premature completion of " 34221033639SNilesh Javali "polling mbx cmd\n", ha->host_no, __func__); 34321033639SNilesh Javali } 34421033639SNilesh Javali } 34521033639SNilesh Javali } 34621033639SNilesh Javali 347f4f5df23SVikas Chaudhary static uint8_t 3482a49a78eSVikas Chaudhary qla4xxx_set_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, 3492a49a78eSVikas Chaudhary uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma) 3502a49a78eSVikas Chaudhary { 3512a49a78eSVikas Chaudhary memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT); 3522a49a78eSVikas Chaudhary memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT); 3532657c800SShyam Sundar 3542657c800SShyam Sundar if (is_qla8022(ha)) 355f8086f4fSVikas Chaudhary qla4_82xx_wr_32(ha, ha->nx_db_wr_ptr, 0); 3562657c800SShyam Sundar 3572a49a78eSVikas Chaudhary mbox_cmd[0] = MBOX_CMD_INITIALIZE_FIRMWARE; 3582a49a78eSVikas Chaudhary mbox_cmd[1] = 0; 3592a49a78eSVikas Chaudhary mbox_cmd[2] = LSDW(init_fw_cb_dma); 3602a49a78eSVikas Chaudhary mbox_cmd[3] = MSDW(init_fw_cb_dma); 3612a49a78eSVikas Chaudhary mbox_cmd[4] = sizeof(struct addr_ctrl_blk); 3622a49a78eSVikas Chaudhary mbox_cmd[5] = (IFCB_VER_MAX << 8) | IFCB_VER_MIN; 3632a49a78eSVikas Chaudhary 3642a49a78eSVikas Chaudhary if (qla4xxx_mailbox_command(ha, 6, 6, mbox_cmd, mbox_sts) != 3652a49a78eSVikas Chaudhary QLA_SUCCESS) { 3662a49a78eSVikas Chaudhary DEBUG2(printk(KERN_WARNING "scsi%ld: %s: " 3672a49a78eSVikas Chaudhary "MBOX_CMD_INITIALIZE_FIRMWARE" 3682a49a78eSVikas Chaudhary " failed w/ status %04X\n", 3692a49a78eSVikas Chaudhary ha->host_no, __func__, mbox_sts[0])); 3702a49a78eSVikas Chaudhary return QLA_ERROR; 3712a49a78eSVikas Chaudhary } 3722a49a78eSVikas Chaudhary return QLA_SUCCESS; 3732a49a78eSVikas Chaudhary } 3742a49a78eSVikas Chaudhary 375d00efe3fSMike Christie uint8_t 3762a49a78eSVikas Chaudhary qla4xxx_get_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, 3772a49a78eSVikas Chaudhary uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma) 3782a49a78eSVikas Chaudhary { 3792a49a78eSVikas Chaudhary memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT); 3802a49a78eSVikas Chaudhary memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT); 3812a49a78eSVikas Chaudhary mbox_cmd[0] = MBOX_CMD_GET_INIT_FW_CTRL_BLOCK; 3822a49a78eSVikas Chaudhary mbox_cmd[2] = LSDW(init_fw_cb_dma); 3832a49a78eSVikas Chaudhary mbox_cmd[3] = MSDW(init_fw_cb_dma); 3842a49a78eSVikas Chaudhary mbox_cmd[4] = sizeof(struct addr_ctrl_blk); 3852a49a78eSVikas Chaudhary 3862a49a78eSVikas Chaudhary if (qla4xxx_mailbox_command(ha, 5, 5, mbox_cmd, mbox_sts) != 3872a49a78eSVikas Chaudhary QLA_SUCCESS) { 3882a49a78eSVikas Chaudhary DEBUG2(printk(KERN_WARNING "scsi%ld: %s: " 3892a49a78eSVikas Chaudhary "MBOX_CMD_GET_INIT_FW_CTRL_BLOCK" 3902a49a78eSVikas Chaudhary " failed w/ status %04X\n", 3912a49a78eSVikas Chaudhary ha->host_no, __func__, mbox_sts[0])); 3922a49a78eSVikas Chaudhary return QLA_ERROR; 3932a49a78eSVikas Chaudhary } 3942a49a78eSVikas Chaudhary return QLA_SUCCESS; 3952a49a78eSVikas Chaudhary } 3962a49a78eSVikas Chaudhary 397f4f5df23SVikas Chaudhary static void 3982a49a78eSVikas Chaudhary qla4xxx_update_local_ip(struct scsi_qla_host *ha, 3992a49a78eSVikas Chaudhary struct addr_ctrl_blk *init_fw_cb) 4002a49a78eSVikas Chaudhary { 4012bab08fcSVikas Chaudhary ha->ip_config.tcp_options = le16_to_cpu(init_fw_cb->ipv4_tcp_opts); 4022bab08fcSVikas Chaudhary ha->ip_config.ipv4_options = le16_to_cpu(init_fw_cb->ipv4_ip_opts); 4032bab08fcSVikas Chaudhary ha->ip_config.ipv4_addr_state = 4042bab08fcSVikas Chaudhary le16_to_cpu(init_fw_cb->ipv4_addr_state); 405943c157bSVikas Chaudhary ha->ip_config.eth_mtu_size = 406943c157bSVikas Chaudhary le16_to_cpu(init_fw_cb->eth_mtu_size); 4072ada7fc5SVikas Chaudhary ha->ip_config.ipv4_port = le16_to_cpu(init_fw_cb->ipv4_port); 4082bab08fcSVikas Chaudhary 4092bab08fcSVikas Chaudhary if (ha->acb_version == ACB_SUPPORTED) { 4102bab08fcSVikas Chaudhary ha->ip_config.ipv6_options = le16_to_cpu(init_fw_cb->ipv6_opts); 4112bab08fcSVikas Chaudhary ha->ip_config.ipv6_addl_options = 4122bab08fcSVikas Chaudhary le16_to_cpu(init_fw_cb->ipv6_addtl_opts); 4132bab08fcSVikas Chaudhary } 4142bab08fcSVikas Chaudhary 4152a49a78eSVikas Chaudhary /* Save IPv4 Address Info */ 4162bab08fcSVikas Chaudhary memcpy(ha->ip_config.ip_address, init_fw_cb->ipv4_addr, 4172bab08fcSVikas Chaudhary min(sizeof(ha->ip_config.ip_address), 4182bab08fcSVikas Chaudhary sizeof(init_fw_cb->ipv4_addr))); 4192bab08fcSVikas Chaudhary memcpy(ha->ip_config.subnet_mask, init_fw_cb->ipv4_subnet, 4202bab08fcSVikas Chaudhary min(sizeof(ha->ip_config.subnet_mask), 4212bab08fcSVikas Chaudhary sizeof(init_fw_cb->ipv4_subnet))); 4222bab08fcSVikas Chaudhary memcpy(ha->ip_config.gateway, init_fw_cb->ipv4_gw_addr, 4232bab08fcSVikas Chaudhary min(sizeof(ha->ip_config.gateway), 4242bab08fcSVikas Chaudhary sizeof(init_fw_cb->ipv4_gw_addr))); 4252a49a78eSVikas Chaudhary 4266ac73e8cSVikas Chaudhary ha->ip_config.ipv4_vlan_tag = be16_to_cpu(init_fw_cb->ipv4_vlan_tag); 4276ac73e8cSVikas Chaudhary 4282a49a78eSVikas Chaudhary if (is_ipv6_enabled(ha)) { 4292a49a78eSVikas Chaudhary /* Save IPv6 Address */ 4302bab08fcSVikas Chaudhary ha->ip_config.ipv6_link_local_state = 4312bab08fcSVikas Chaudhary le16_to_cpu(init_fw_cb->ipv6_lnk_lcl_addr_state); 4322bab08fcSVikas Chaudhary ha->ip_config.ipv6_addr0_state = 4332bab08fcSVikas Chaudhary le16_to_cpu(init_fw_cb->ipv6_addr0_state); 4342bab08fcSVikas Chaudhary ha->ip_config.ipv6_addr1_state = 4352bab08fcSVikas Chaudhary le16_to_cpu(init_fw_cb->ipv6_addr1_state); 4362bab08fcSVikas Chaudhary ha->ip_config.ipv6_default_router_state = 4372bab08fcSVikas Chaudhary le16_to_cpu(init_fw_cb->ipv6_dflt_rtr_state); 4382bab08fcSVikas Chaudhary ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[0] = 0xFE; 4392bab08fcSVikas Chaudhary ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[1] = 0x80; 4402a49a78eSVikas Chaudhary 4412bab08fcSVikas Chaudhary memcpy(&ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[8], 4422a49a78eSVikas Chaudhary init_fw_cb->ipv6_if_id, 4432bab08fcSVikas Chaudhary min(sizeof(ha->ip_config.ipv6_link_local_addr)/2, 4442a49a78eSVikas Chaudhary sizeof(init_fw_cb->ipv6_if_id))); 4452bab08fcSVikas Chaudhary memcpy(&ha->ip_config.ipv6_addr0, init_fw_cb->ipv6_addr0, 4462bab08fcSVikas Chaudhary min(sizeof(ha->ip_config.ipv6_addr0), 4472a49a78eSVikas Chaudhary sizeof(init_fw_cb->ipv6_addr0))); 4482bab08fcSVikas Chaudhary memcpy(&ha->ip_config.ipv6_addr1, init_fw_cb->ipv6_addr1, 4492bab08fcSVikas Chaudhary min(sizeof(ha->ip_config.ipv6_addr1), 4502a49a78eSVikas Chaudhary sizeof(init_fw_cb->ipv6_addr1))); 4512bab08fcSVikas Chaudhary memcpy(&ha->ip_config.ipv6_default_router_addr, 4522a49a78eSVikas Chaudhary init_fw_cb->ipv6_dflt_rtr_addr, 4532bab08fcSVikas Chaudhary min(sizeof(ha->ip_config.ipv6_default_router_addr), 4542a49a78eSVikas Chaudhary sizeof(init_fw_cb->ipv6_dflt_rtr_addr))); 4556ac73e8cSVikas Chaudhary ha->ip_config.ipv6_vlan_tag = 4566ac73e8cSVikas Chaudhary be16_to_cpu(init_fw_cb->ipv6_vlan_tag); 4572ada7fc5SVikas Chaudhary ha->ip_config.ipv6_port = le16_to_cpu(init_fw_cb->ipv6_port); 4582a49a78eSVikas Chaudhary } 4592a49a78eSVikas Chaudhary } 4602a49a78eSVikas Chaudhary 461d00efe3fSMike Christie uint8_t 4622a49a78eSVikas Chaudhary qla4xxx_update_local_ifcb(struct scsi_qla_host *ha, 4632a49a78eSVikas Chaudhary uint32_t *mbox_cmd, 4642a49a78eSVikas Chaudhary uint32_t *mbox_sts, 4652a49a78eSVikas Chaudhary struct addr_ctrl_blk *init_fw_cb, 4662a49a78eSVikas Chaudhary dma_addr_t init_fw_cb_dma) 4672a49a78eSVikas Chaudhary { 4682a49a78eSVikas Chaudhary if (qla4xxx_get_ifcb(ha, mbox_cmd, mbox_sts, init_fw_cb_dma) 4692a49a78eSVikas Chaudhary != QLA_SUCCESS) { 4702a49a78eSVikas Chaudhary DEBUG2(printk(KERN_WARNING 4712a49a78eSVikas Chaudhary "scsi%ld: %s: Failed to get init_fw_ctrl_blk\n", 4722a49a78eSVikas Chaudhary ha->host_no, __func__)); 4732a49a78eSVikas Chaudhary return QLA_ERROR; 4742a49a78eSVikas Chaudhary } 4752a49a78eSVikas Chaudhary 4762a49a78eSVikas Chaudhary DEBUG2(qla4xxx_dump_buffer(init_fw_cb, sizeof(struct addr_ctrl_blk))); 4772a49a78eSVikas Chaudhary 4782a49a78eSVikas Chaudhary /* Save some info in adapter structure. */ 4792a49a78eSVikas Chaudhary ha->acb_version = init_fw_cb->acb_version; 4802a49a78eSVikas Chaudhary ha->firmware_options = le16_to_cpu(init_fw_cb->fw_options); 4812a49a78eSVikas Chaudhary ha->heartbeat_interval = init_fw_cb->hb_interval; 4822a49a78eSVikas Chaudhary memcpy(ha->name_string, init_fw_cb->iscsi_name, 4832a49a78eSVikas Chaudhary min(sizeof(ha->name_string), 4842a49a78eSVikas Chaudhary sizeof(init_fw_cb->iscsi_name))); 48513483730SMike Christie ha->def_timeout = le16_to_cpu(init_fw_cb->def_timeout); 4862a49a78eSVikas Chaudhary /*memcpy(ha->alias, init_fw_cb->Alias, 4872a49a78eSVikas Chaudhary min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));*/ 4882a49a78eSVikas Chaudhary 4892a49a78eSVikas Chaudhary qla4xxx_update_local_ip(ha, init_fw_cb); 4902a49a78eSVikas Chaudhary 4912a49a78eSVikas Chaudhary return QLA_SUCCESS; 4922a49a78eSVikas Chaudhary } 4932a49a78eSVikas Chaudhary 494afaf5a2dSDavid Somayajulu /** 495afaf5a2dSDavid Somayajulu * qla4xxx_initialize_fw_cb - initializes firmware control block. 496afaf5a2dSDavid Somayajulu * @ha: Pointer to host adapter structure. 497afaf5a2dSDavid Somayajulu **/ 498afaf5a2dSDavid Somayajulu int qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha) 499afaf5a2dSDavid Somayajulu { 5002a49a78eSVikas Chaudhary struct addr_ctrl_blk *init_fw_cb; 501afaf5a2dSDavid Somayajulu dma_addr_t init_fw_cb_dma; 502afaf5a2dSDavid Somayajulu uint32_t mbox_cmd[MBOX_REG_COUNT]; 503afaf5a2dSDavid Somayajulu uint32_t mbox_sts[MBOX_REG_COUNT]; 504afaf5a2dSDavid Somayajulu int status = QLA_ERROR; 505afaf5a2dSDavid Somayajulu 506afaf5a2dSDavid Somayajulu init_fw_cb = dma_alloc_coherent(&ha->pdev->dev, 5072a49a78eSVikas Chaudhary sizeof(struct addr_ctrl_blk), 508afaf5a2dSDavid Somayajulu &init_fw_cb_dma, GFP_KERNEL); 509afaf5a2dSDavid Somayajulu if (init_fw_cb == NULL) { 510afaf5a2dSDavid Somayajulu DEBUG2(printk("scsi%ld: %s: Unable to alloc init_cb\n", 511afaf5a2dSDavid Somayajulu ha->host_no, __func__)); 512beabe7c1SPrasanna Mumbai goto exit_init_fw_cb_no_free; 513afaf5a2dSDavid Somayajulu } 5142a49a78eSVikas Chaudhary memset(init_fw_cb, 0, sizeof(struct addr_ctrl_blk)); 515afaf5a2dSDavid Somayajulu 516afaf5a2dSDavid Somayajulu /* Get Initialize Firmware Control Block. */ 517afaf5a2dSDavid Somayajulu memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 518afaf5a2dSDavid Somayajulu memset(&mbox_sts, 0, sizeof(mbox_sts)); 519c0e344c9SDavid C Somayajulu 5202a49a78eSVikas Chaudhary if (qla4xxx_get_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma) != 521afaf5a2dSDavid Somayajulu QLA_SUCCESS) { 522afaf5a2dSDavid Somayajulu dma_free_coherent(&ha->pdev->dev, 5232a49a78eSVikas Chaudhary sizeof(struct addr_ctrl_blk), 524afaf5a2dSDavid Somayajulu init_fw_cb, init_fw_cb_dma); 5252a49a78eSVikas Chaudhary goto exit_init_fw_cb; 526afaf5a2dSDavid Somayajulu } 527afaf5a2dSDavid Somayajulu 528afaf5a2dSDavid Somayajulu /* Initialize request and response queues. */ 529afaf5a2dSDavid Somayajulu qla4xxx_init_rings(ha); 530afaf5a2dSDavid Somayajulu 531afaf5a2dSDavid Somayajulu /* Fill in the request and response queue information. */ 5322a49a78eSVikas Chaudhary init_fw_cb->rqq_consumer_idx = cpu_to_le16(ha->request_out); 5332a49a78eSVikas Chaudhary init_fw_cb->compq_producer_idx = cpu_to_le16(ha->response_in); 5342a49a78eSVikas Chaudhary init_fw_cb->rqq_len = __constant_cpu_to_le16(REQUEST_QUEUE_DEPTH); 5352a49a78eSVikas Chaudhary init_fw_cb->compq_len = __constant_cpu_to_le16(RESPONSE_QUEUE_DEPTH); 5362a49a78eSVikas Chaudhary init_fw_cb->rqq_addr_lo = cpu_to_le32(LSDW(ha->request_dma)); 5372a49a78eSVikas Chaudhary init_fw_cb->rqq_addr_hi = cpu_to_le32(MSDW(ha->request_dma)); 5382a49a78eSVikas Chaudhary init_fw_cb->compq_addr_lo = cpu_to_le32(LSDW(ha->response_dma)); 5392a49a78eSVikas Chaudhary init_fw_cb->compq_addr_hi = cpu_to_le32(MSDW(ha->response_dma)); 5402a49a78eSVikas Chaudhary init_fw_cb->shdwreg_addr_lo = cpu_to_le32(LSDW(ha->shadow_regs_dma)); 5412a49a78eSVikas Chaudhary init_fw_cb->shdwreg_addr_hi = cpu_to_le32(MSDW(ha->shadow_regs_dma)); 542afaf5a2dSDavid Somayajulu 543afaf5a2dSDavid Somayajulu /* Set up required options. */ 5442a49a78eSVikas Chaudhary init_fw_cb->fw_options |= 545afaf5a2dSDavid Somayajulu __constant_cpu_to_le16(FWOPT_SESSION_MODE | 546afaf5a2dSDavid Somayajulu FWOPT_INITIATOR_MODE); 5472657c800SShyam Sundar 5486e7b4292SVikas Chaudhary if (is_qla80XX(ha)) 5492657c800SShyam Sundar init_fw_cb->fw_options |= 5502657c800SShyam Sundar __constant_cpu_to_le16(FWOPT_ENABLE_CRBDB); 5512657c800SShyam Sundar 5522a49a78eSVikas Chaudhary init_fw_cb->fw_options &= __constant_cpu_to_le16(~FWOPT_TARGET_MODE); 553afaf5a2dSDavid Somayajulu 554d32cee3cSPrasanna Mumbai init_fw_cb->add_fw_options = 0; 555d32cee3cSPrasanna Mumbai init_fw_cb->add_fw_options |= 556b3a271a9SManish Rangankar __constant_cpu_to_le16(ADFWOPT_SERIALIZE_TASK_MGMT); 557b3a271a9SManish Rangankar init_fw_cb->add_fw_options |= 558b3a271a9SManish Rangankar __constant_cpu_to_le16(ADFWOPT_AUTOCONN_DISABLE); 559d32cee3cSPrasanna Mumbai 5602a49a78eSVikas Chaudhary if (qla4xxx_set_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma) 5612a49a78eSVikas Chaudhary != QLA_SUCCESS) { 5622a49a78eSVikas Chaudhary DEBUG2(printk(KERN_WARNING 5632a49a78eSVikas Chaudhary "scsi%ld: %s: Failed to set init_fw_ctrl_blk\n", 5642a49a78eSVikas Chaudhary ha->host_no, __func__)); 5652a49a78eSVikas Chaudhary goto exit_init_fw_cb; 566afaf5a2dSDavid Somayajulu } 5672a49a78eSVikas Chaudhary 5682a49a78eSVikas Chaudhary if (qla4xxx_update_local_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], 5692a49a78eSVikas Chaudhary init_fw_cb, init_fw_cb_dma) != QLA_SUCCESS) { 5702a49a78eSVikas Chaudhary DEBUG2(printk("scsi%ld: %s: Failed to update local ifcb\n", 5712a49a78eSVikas Chaudhary ha->host_no, __func__)); 5722a49a78eSVikas Chaudhary goto exit_init_fw_cb; 5732a49a78eSVikas Chaudhary } 5742a49a78eSVikas Chaudhary status = QLA_SUCCESS; 5752a49a78eSVikas Chaudhary 5762a49a78eSVikas Chaudhary exit_init_fw_cb: 5772a49a78eSVikas Chaudhary dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk), 578afaf5a2dSDavid Somayajulu init_fw_cb, init_fw_cb_dma); 579beabe7c1SPrasanna Mumbai exit_init_fw_cb_no_free: 580afaf5a2dSDavid Somayajulu return status; 581afaf5a2dSDavid Somayajulu } 582afaf5a2dSDavid Somayajulu 583afaf5a2dSDavid Somayajulu /** 584afaf5a2dSDavid Somayajulu * qla4xxx_get_dhcp_ip_address - gets HBA ip address via DHCP 585afaf5a2dSDavid Somayajulu * @ha: Pointer to host adapter structure. 586afaf5a2dSDavid Somayajulu **/ 587afaf5a2dSDavid Somayajulu int qla4xxx_get_dhcp_ip_address(struct scsi_qla_host * ha) 588afaf5a2dSDavid Somayajulu { 5892a49a78eSVikas Chaudhary struct addr_ctrl_blk *init_fw_cb; 590afaf5a2dSDavid Somayajulu dma_addr_t init_fw_cb_dma; 591afaf5a2dSDavid Somayajulu uint32_t mbox_cmd[MBOX_REG_COUNT]; 592afaf5a2dSDavid Somayajulu uint32_t mbox_sts[MBOX_REG_COUNT]; 593afaf5a2dSDavid Somayajulu 594afaf5a2dSDavid Somayajulu init_fw_cb = dma_alloc_coherent(&ha->pdev->dev, 5952a49a78eSVikas Chaudhary sizeof(struct addr_ctrl_blk), 596afaf5a2dSDavid Somayajulu &init_fw_cb_dma, GFP_KERNEL); 597afaf5a2dSDavid Somayajulu if (init_fw_cb == NULL) { 598afaf5a2dSDavid Somayajulu printk("scsi%ld: %s: Unable to alloc init_cb\n", ha->host_no, 599afaf5a2dSDavid Somayajulu __func__); 600beabe7c1SPrasanna Mumbai return QLA_ERROR; 601afaf5a2dSDavid Somayajulu } 602afaf5a2dSDavid Somayajulu 603afaf5a2dSDavid Somayajulu /* Get Initialize Firmware Control Block. */ 6042a49a78eSVikas Chaudhary memset(init_fw_cb, 0, sizeof(struct addr_ctrl_blk)); 6052a49a78eSVikas Chaudhary if (qla4xxx_get_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma) != 606afaf5a2dSDavid Somayajulu QLA_SUCCESS) { 607afaf5a2dSDavid Somayajulu DEBUG2(printk("scsi%ld: %s: Failed to get init_fw_ctrl_blk\n", 608afaf5a2dSDavid Somayajulu ha->host_no, __func__)); 609afaf5a2dSDavid Somayajulu dma_free_coherent(&ha->pdev->dev, 6102a49a78eSVikas Chaudhary sizeof(struct addr_ctrl_blk), 611afaf5a2dSDavid Somayajulu init_fw_cb, init_fw_cb_dma); 612afaf5a2dSDavid Somayajulu return QLA_ERROR; 613afaf5a2dSDavid Somayajulu } 614afaf5a2dSDavid Somayajulu 615afaf5a2dSDavid Somayajulu /* Save IP Address. */ 6162a49a78eSVikas Chaudhary qla4xxx_update_local_ip(ha, init_fw_cb); 6172a49a78eSVikas Chaudhary dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk), 618afaf5a2dSDavid Somayajulu init_fw_cb, init_fw_cb_dma); 619afaf5a2dSDavid Somayajulu 620afaf5a2dSDavid Somayajulu return QLA_SUCCESS; 621afaf5a2dSDavid Somayajulu } 622afaf5a2dSDavid Somayajulu 623afaf5a2dSDavid Somayajulu /** 624afaf5a2dSDavid Somayajulu * qla4xxx_get_firmware_state - gets firmware state of HBA 625afaf5a2dSDavid Somayajulu * @ha: Pointer to host adapter structure. 626afaf5a2dSDavid Somayajulu **/ 627afaf5a2dSDavid Somayajulu int qla4xxx_get_firmware_state(struct scsi_qla_host * ha) 628afaf5a2dSDavid Somayajulu { 629afaf5a2dSDavid Somayajulu uint32_t mbox_cmd[MBOX_REG_COUNT]; 630afaf5a2dSDavid Somayajulu uint32_t mbox_sts[MBOX_REG_COUNT]; 631afaf5a2dSDavid Somayajulu 632afaf5a2dSDavid Somayajulu /* Get firmware version */ 633afaf5a2dSDavid Somayajulu memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 634afaf5a2dSDavid Somayajulu memset(&mbox_sts, 0, sizeof(mbox_sts)); 635c0e344c9SDavid C Somayajulu 636afaf5a2dSDavid Somayajulu mbox_cmd[0] = MBOX_CMD_GET_FW_STATE; 637c0e344c9SDavid C Somayajulu 638c0e344c9SDavid C Somayajulu if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 4, &mbox_cmd[0], &mbox_sts[0]) != 639afaf5a2dSDavid Somayajulu QLA_SUCCESS) { 640afaf5a2dSDavid Somayajulu DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATE failed w/ " 641afaf5a2dSDavid Somayajulu "status %04X\n", ha->host_no, __func__, 642afaf5a2dSDavid Somayajulu mbox_sts[0])); 643afaf5a2dSDavid Somayajulu return QLA_ERROR; 644afaf5a2dSDavid Somayajulu } 645afaf5a2dSDavid Somayajulu ha->firmware_state = mbox_sts[1]; 646afaf5a2dSDavid Somayajulu ha->board_id = mbox_sts[2]; 647afaf5a2dSDavid Somayajulu ha->addl_fw_state = mbox_sts[3]; 648afaf5a2dSDavid Somayajulu DEBUG2(printk("scsi%ld: %s firmware_state=0x%x\n", 649afaf5a2dSDavid Somayajulu ha->host_no, __func__, ha->firmware_state);) 650afaf5a2dSDavid Somayajulu 651afaf5a2dSDavid Somayajulu return QLA_SUCCESS; 652afaf5a2dSDavid Somayajulu } 653afaf5a2dSDavid Somayajulu 654afaf5a2dSDavid Somayajulu /** 655afaf5a2dSDavid Somayajulu * qla4xxx_get_firmware_status - retrieves firmware status 656afaf5a2dSDavid Somayajulu * @ha: Pointer to host adapter structure. 657afaf5a2dSDavid Somayajulu **/ 658afaf5a2dSDavid Somayajulu int qla4xxx_get_firmware_status(struct scsi_qla_host * ha) 659afaf5a2dSDavid Somayajulu { 660afaf5a2dSDavid Somayajulu uint32_t mbox_cmd[MBOX_REG_COUNT]; 661afaf5a2dSDavid Somayajulu uint32_t mbox_sts[MBOX_REG_COUNT]; 662afaf5a2dSDavid Somayajulu 663afaf5a2dSDavid Somayajulu /* Get firmware version */ 664afaf5a2dSDavid Somayajulu memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 665afaf5a2dSDavid Somayajulu memset(&mbox_sts, 0, sizeof(mbox_sts)); 666c0e344c9SDavid C Somayajulu 667afaf5a2dSDavid Somayajulu mbox_cmd[0] = MBOX_CMD_GET_FW_STATUS; 668c0e344c9SDavid C Somayajulu 669c0e344c9SDavid C Somayajulu if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0], &mbox_sts[0]) != 670afaf5a2dSDavid Somayajulu QLA_SUCCESS) { 671afaf5a2dSDavid Somayajulu DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATUS failed w/ " 672afaf5a2dSDavid Somayajulu "status %04X\n", ha->host_no, __func__, 673afaf5a2dSDavid Somayajulu mbox_sts[0])); 674afaf5a2dSDavid Somayajulu return QLA_ERROR; 675afaf5a2dSDavid Somayajulu } 676f4f5df23SVikas Chaudhary 6773573bfb2SVikas Chaudhary ql4_printk(KERN_INFO, ha, "%ld firmware IOCBs available (%d).\n", 678f581a3f7SVikas Chaudhary ha->host_no, mbox_sts[2]); 679f4f5df23SVikas Chaudhary 680afaf5a2dSDavid Somayajulu return QLA_SUCCESS; 681afaf5a2dSDavid Somayajulu } 682afaf5a2dSDavid Somayajulu 683afaf5a2dSDavid Somayajulu /** 684afaf5a2dSDavid Somayajulu * qla4xxx_get_fwddb_entry - retrieves firmware ddb entry 685afaf5a2dSDavid Somayajulu * @ha: Pointer to host adapter structure. 686afaf5a2dSDavid Somayajulu * @fw_ddb_index: Firmware's device database index 687afaf5a2dSDavid Somayajulu * @fw_ddb_entry: Pointer to firmware's device database entry structure 688afaf5a2dSDavid Somayajulu * @num_valid_ddb_entries: Pointer to number of valid ddb entries 689afaf5a2dSDavid Somayajulu * @next_ddb_index: Pointer to next valid device database index 690afaf5a2dSDavid Somayajulu * @fw_ddb_device_state: Pointer to device state 691afaf5a2dSDavid Somayajulu **/ 692afaf5a2dSDavid Somayajulu int qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha, 693afaf5a2dSDavid Somayajulu uint16_t fw_ddb_index, 694afaf5a2dSDavid Somayajulu struct dev_db_entry *fw_ddb_entry, 695afaf5a2dSDavid Somayajulu dma_addr_t fw_ddb_entry_dma, 696afaf5a2dSDavid Somayajulu uint32_t *num_valid_ddb_entries, 697afaf5a2dSDavid Somayajulu uint32_t *next_ddb_index, 698afaf5a2dSDavid Somayajulu uint32_t *fw_ddb_device_state, 699afaf5a2dSDavid Somayajulu uint32_t *conn_err_detail, 700afaf5a2dSDavid Somayajulu uint16_t *tcp_source_port_num, 701afaf5a2dSDavid Somayajulu uint16_t *connection_id) 702afaf5a2dSDavid Somayajulu { 703afaf5a2dSDavid Somayajulu int status = QLA_ERROR; 7042a49a78eSVikas Chaudhary uint16_t options; 705afaf5a2dSDavid Somayajulu uint32_t mbox_cmd[MBOX_REG_COUNT]; 706afaf5a2dSDavid Somayajulu uint32_t mbox_sts[MBOX_REG_COUNT]; 707afaf5a2dSDavid Somayajulu 708afaf5a2dSDavid Somayajulu /* Make sure the device index is valid */ 709afaf5a2dSDavid Somayajulu if (fw_ddb_index >= MAX_DDB_ENTRIES) { 710f4f5df23SVikas Chaudhary DEBUG2(printk("scsi%ld: %s: ddb [%d] out of range.\n", 711afaf5a2dSDavid Somayajulu ha->host_no, __func__, fw_ddb_index)); 712afaf5a2dSDavid Somayajulu goto exit_get_fwddb; 713afaf5a2dSDavid Somayajulu } 714afaf5a2dSDavid Somayajulu memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 715afaf5a2dSDavid Somayajulu memset(&mbox_sts, 0, sizeof(mbox_sts)); 716981c982cSLalit Chandivade if (fw_ddb_entry) 717981c982cSLalit Chandivade memset(fw_ddb_entry, 0, sizeof(struct dev_db_entry)); 718c0e344c9SDavid C Somayajulu 719afaf5a2dSDavid Somayajulu mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY; 720afaf5a2dSDavid Somayajulu mbox_cmd[1] = (uint32_t) fw_ddb_index; 721afaf5a2dSDavid Somayajulu mbox_cmd[2] = LSDW(fw_ddb_entry_dma); 722afaf5a2dSDavid Somayajulu mbox_cmd[3] = MSDW(fw_ddb_entry_dma); 723c0e344c9SDavid C Somayajulu mbox_cmd[4] = sizeof(struct dev_db_entry); 724c0e344c9SDavid C Somayajulu 725c0e344c9SDavid C Somayajulu if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 7, &mbox_cmd[0], &mbox_sts[0]) == 726afaf5a2dSDavid Somayajulu QLA_ERROR) { 727afaf5a2dSDavid Somayajulu DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_DATABASE_ENTRY failed" 728afaf5a2dSDavid Somayajulu " with status 0x%04X\n", ha->host_no, __func__, 729afaf5a2dSDavid Somayajulu mbox_sts[0])); 730afaf5a2dSDavid Somayajulu goto exit_get_fwddb; 731afaf5a2dSDavid Somayajulu } 732afaf5a2dSDavid Somayajulu if (fw_ddb_index != mbox_sts[1]) { 733f4f5df23SVikas Chaudhary DEBUG2(printk("scsi%ld: %s: ddb mismatch [%d] != [%d].\n", 734afaf5a2dSDavid Somayajulu ha->host_no, __func__, fw_ddb_index, 735afaf5a2dSDavid Somayajulu mbox_sts[1])); 736afaf5a2dSDavid Somayajulu goto exit_get_fwddb; 737afaf5a2dSDavid Somayajulu } 738afaf5a2dSDavid Somayajulu if (fw_ddb_entry) { 7392a49a78eSVikas Chaudhary options = le16_to_cpu(fw_ddb_entry->options); 7402a49a78eSVikas Chaudhary if (options & DDB_OPT_IPV6_DEVICE) { 741c2660df3SVikas Chaudhary ql4_printk(KERN_INFO, ha, "%s: DDB[%d] MB0 %04x Tot %d " 7422a49a78eSVikas Chaudhary "Next %d State %04x ConnErr %08x %pI6 " 7432a49a78eSVikas Chaudhary ":%04d \"%s\"\n", __func__, fw_ddb_index, 7442a49a78eSVikas Chaudhary mbox_sts[0], mbox_sts[2], mbox_sts[3], 7452a49a78eSVikas Chaudhary mbox_sts[4], mbox_sts[5], 7462a49a78eSVikas Chaudhary fw_ddb_entry->ip_addr, 747c0e344c9SDavid C Somayajulu le16_to_cpu(fw_ddb_entry->port), 748c0e344c9SDavid C Somayajulu fw_ddb_entry->iscsi_name); 7492a49a78eSVikas Chaudhary } else { 750c2660df3SVikas Chaudhary ql4_printk(KERN_INFO, ha, "%s: DDB[%d] MB0 %04x Tot %d " 7512a49a78eSVikas Chaudhary "Next %d State %04x ConnErr %08x %pI4 " 7522a49a78eSVikas Chaudhary ":%04d \"%s\"\n", __func__, fw_ddb_index, 7532a49a78eSVikas Chaudhary mbox_sts[0], mbox_sts[2], mbox_sts[3], 7542a49a78eSVikas Chaudhary mbox_sts[4], mbox_sts[5], 7552a49a78eSVikas Chaudhary fw_ddb_entry->ip_addr, 7562a49a78eSVikas Chaudhary le16_to_cpu(fw_ddb_entry->port), 7572a49a78eSVikas Chaudhary fw_ddb_entry->iscsi_name); 7582a49a78eSVikas Chaudhary } 759afaf5a2dSDavid Somayajulu } 760afaf5a2dSDavid Somayajulu if (num_valid_ddb_entries) 761afaf5a2dSDavid Somayajulu *num_valid_ddb_entries = mbox_sts[2]; 762afaf5a2dSDavid Somayajulu if (next_ddb_index) 763afaf5a2dSDavid Somayajulu *next_ddb_index = mbox_sts[3]; 764afaf5a2dSDavid Somayajulu if (fw_ddb_device_state) 765afaf5a2dSDavid Somayajulu *fw_ddb_device_state = mbox_sts[4]; 766afaf5a2dSDavid Somayajulu 767afaf5a2dSDavid Somayajulu /* 768afaf5a2dSDavid Somayajulu * RA: This mailbox has been changed to pass connection error and 769afaf5a2dSDavid Somayajulu * details. Its true for ISP4010 as per Version E - Not sure when it 770afaf5a2dSDavid Somayajulu * was changed. Get the time2wait from the fw_dd_entry field : 771afaf5a2dSDavid Somayajulu * default_time2wait which we call it as minTime2Wait DEV_DB_ENTRY 772afaf5a2dSDavid Somayajulu * struct. 773afaf5a2dSDavid Somayajulu */ 774afaf5a2dSDavid Somayajulu if (conn_err_detail) 775afaf5a2dSDavid Somayajulu *conn_err_detail = mbox_sts[5]; 776afaf5a2dSDavid Somayajulu if (tcp_source_port_num) 7771482338fSRandy Dunlap *tcp_source_port_num = (uint16_t) (mbox_sts[6] >> 16); 778afaf5a2dSDavid Somayajulu if (connection_id) 779afaf5a2dSDavid Somayajulu *connection_id = (uint16_t) mbox_sts[6] & 0x00FF; 780afaf5a2dSDavid Somayajulu status = QLA_SUCCESS; 781afaf5a2dSDavid Somayajulu 782afaf5a2dSDavid Somayajulu exit_get_fwddb: 783afaf5a2dSDavid Somayajulu return status; 784afaf5a2dSDavid Somayajulu } 785afaf5a2dSDavid Somayajulu 786b3a271a9SManish Rangankar int qla4xxx_conn_open(struct scsi_qla_host *ha, uint16_t fw_ddb_index) 787b3a271a9SManish Rangankar { 788b3a271a9SManish Rangankar uint32_t mbox_cmd[MBOX_REG_COUNT]; 789b3a271a9SManish Rangankar uint32_t mbox_sts[MBOX_REG_COUNT]; 790b3a271a9SManish Rangankar int status; 791b3a271a9SManish Rangankar 792b3a271a9SManish Rangankar memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 793b3a271a9SManish Rangankar memset(&mbox_sts, 0, sizeof(mbox_sts)); 794b3a271a9SManish Rangankar 795b3a271a9SManish Rangankar mbox_cmd[0] = MBOX_CMD_CONN_OPEN; 796b3a271a9SManish Rangankar mbox_cmd[1] = fw_ddb_index; 797b3a271a9SManish Rangankar 798b3a271a9SManish Rangankar status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0], 799b3a271a9SManish Rangankar &mbox_sts[0]); 800b3a271a9SManish Rangankar DEBUG2(ql4_printk(KERN_INFO, ha, 801b3a271a9SManish Rangankar "%s: status = %d mbx0 = 0x%x mbx1 = 0x%x\n", 802b3a271a9SManish Rangankar __func__, status, mbox_sts[0], mbox_sts[1])); 803b3a271a9SManish Rangankar return status; 804b3a271a9SManish Rangankar } 805b3a271a9SManish Rangankar 806afaf5a2dSDavid Somayajulu /** 807afaf5a2dSDavid Somayajulu * qla4xxx_set_fwddb_entry - sets a ddb entry. 808afaf5a2dSDavid Somayajulu * @ha: Pointer to host adapter structure. 809afaf5a2dSDavid Somayajulu * @fw_ddb_index: Firmware's device database index 810b3a271a9SManish Rangankar * @fw_ddb_entry_dma: dma address of ddb entry 811b3a271a9SManish Rangankar * @mbx_sts: mailbox 0 to be returned or NULL 812afaf5a2dSDavid Somayajulu * 813afaf5a2dSDavid Somayajulu * This routine initializes or updates the adapter's device database 814b3a271a9SManish Rangankar * entry for the specified device. 815afaf5a2dSDavid Somayajulu **/ 816afaf5a2dSDavid Somayajulu int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index, 817b3a271a9SManish Rangankar dma_addr_t fw_ddb_entry_dma, uint32_t *mbx_sts) 818afaf5a2dSDavid Somayajulu { 819afaf5a2dSDavid Somayajulu uint32_t mbox_cmd[MBOX_REG_COUNT]; 820afaf5a2dSDavid Somayajulu uint32_t mbox_sts[MBOX_REG_COUNT]; 821f4f5df23SVikas Chaudhary int status; 822afaf5a2dSDavid Somayajulu 823afaf5a2dSDavid Somayajulu /* Do not wait for completion. The firmware will send us an 824afaf5a2dSDavid Somayajulu * ASTS_DATABASE_CHANGED (0x8014) to notify us of the login status. 825afaf5a2dSDavid Somayajulu */ 826afaf5a2dSDavid Somayajulu memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 827afaf5a2dSDavid Somayajulu memset(&mbox_sts, 0, sizeof(mbox_sts)); 828afaf5a2dSDavid Somayajulu 829afaf5a2dSDavid Somayajulu mbox_cmd[0] = MBOX_CMD_SET_DATABASE_ENTRY; 830afaf5a2dSDavid Somayajulu mbox_cmd[1] = (uint32_t) fw_ddb_index; 831afaf5a2dSDavid Somayajulu mbox_cmd[2] = LSDW(fw_ddb_entry_dma); 832afaf5a2dSDavid Somayajulu mbox_cmd[3] = MSDW(fw_ddb_entry_dma); 833c0e344c9SDavid C Somayajulu mbox_cmd[4] = sizeof(struct dev_db_entry); 834c0e344c9SDavid C Somayajulu 835f4f5df23SVikas Chaudhary status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], 836f4f5df23SVikas Chaudhary &mbox_sts[0]); 837b3a271a9SManish Rangankar if (mbx_sts) 838b3a271a9SManish Rangankar *mbx_sts = mbox_sts[0]; 839f4f5df23SVikas Chaudhary DEBUG2(printk("scsi%ld: %s: status=%d mbx0=0x%x mbx4=0x%x\n", 840f4f5df23SVikas Chaudhary ha->host_no, __func__, status, mbox_sts[0], mbox_sts[4]);) 841f4f5df23SVikas Chaudhary 842f4f5df23SVikas Chaudhary return status; 843afaf5a2dSDavid Somayajulu } 844afaf5a2dSDavid Somayajulu 845b3a271a9SManish Rangankar int qla4xxx_session_logout_ddb(struct scsi_qla_host *ha, 846b3a271a9SManish Rangankar struct ddb_entry *ddb_entry, int options) 847b3a271a9SManish Rangankar { 848b3a271a9SManish Rangankar int status; 849b3a271a9SManish Rangankar uint32_t mbox_cmd[MBOX_REG_COUNT]; 850b3a271a9SManish Rangankar uint32_t mbox_sts[MBOX_REG_COUNT]; 851b3a271a9SManish Rangankar 852b3a271a9SManish Rangankar memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 853b3a271a9SManish Rangankar memset(&mbox_sts, 0, sizeof(mbox_sts)); 854b3a271a9SManish Rangankar 855b3a271a9SManish Rangankar mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT; 856b3a271a9SManish Rangankar mbox_cmd[1] = ddb_entry->fw_ddb_index; 857b3a271a9SManish Rangankar mbox_cmd[3] = options; 858b3a271a9SManish Rangankar 859b3a271a9SManish Rangankar status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0], 860b3a271a9SManish Rangankar &mbox_sts[0]); 861b3a271a9SManish Rangankar if (status != QLA_SUCCESS) { 862b3a271a9SManish Rangankar DEBUG2(ql4_printk(KERN_INFO, ha, 863b3a271a9SManish Rangankar "%s: MBOX_CMD_CONN_CLOSE_SESS_LOGOUT " 864b3a271a9SManish Rangankar "failed sts %04X %04X", __func__, 865b3a271a9SManish Rangankar mbox_sts[0], mbox_sts[1])); 866b3a271a9SManish Rangankar } 867b3a271a9SManish Rangankar 868b3a271a9SManish Rangankar return status; 869b3a271a9SManish Rangankar } 870b3a271a9SManish Rangankar 871afaf5a2dSDavid Somayajulu /** 872afaf5a2dSDavid Somayajulu * qla4xxx_get_crash_record - retrieves crash record. 873afaf5a2dSDavid Somayajulu * @ha: Pointer to host adapter structure. 874afaf5a2dSDavid Somayajulu * 875afaf5a2dSDavid Somayajulu * This routine retrieves a crash record from the QLA4010 after an 8002h aen. 876afaf5a2dSDavid Somayajulu **/ 877afaf5a2dSDavid Somayajulu void qla4xxx_get_crash_record(struct scsi_qla_host * ha) 878afaf5a2dSDavid Somayajulu { 879afaf5a2dSDavid Somayajulu uint32_t mbox_cmd[MBOX_REG_COUNT]; 880afaf5a2dSDavid Somayajulu uint32_t mbox_sts[MBOX_REG_COUNT]; 881afaf5a2dSDavid Somayajulu struct crash_record *crash_record = NULL; 882afaf5a2dSDavid Somayajulu dma_addr_t crash_record_dma = 0; 883afaf5a2dSDavid Somayajulu uint32_t crash_record_size = 0; 884c0e344c9SDavid C Somayajulu 885afaf5a2dSDavid Somayajulu memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 886afaf5a2dSDavid Somayajulu memset(&mbox_sts, 0, sizeof(mbox_cmd)); 887afaf5a2dSDavid Somayajulu 888afaf5a2dSDavid Somayajulu /* Get size of crash record. */ 889afaf5a2dSDavid Somayajulu mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD; 890c0e344c9SDavid C Somayajulu 891c0e344c9SDavid C Somayajulu if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) != 892afaf5a2dSDavid Somayajulu QLA_SUCCESS) { 893afaf5a2dSDavid Somayajulu DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve size!\n", 894afaf5a2dSDavid Somayajulu ha->host_no, __func__)); 895afaf5a2dSDavid Somayajulu goto exit_get_crash_record; 896afaf5a2dSDavid Somayajulu } 897afaf5a2dSDavid Somayajulu crash_record_size = mbox_sts[4]; 898afaf5a2dSDavid Somayajulu if (crash_record_size == 0) { 899afaf5a2dSDavid Somayajulu DEBUG2(printk("scsi%ld: %s: ERROR: Crash record size is 0!\n", 900afaf5a2dSDavid Somayajulu ha->host_no, __func__)); 901afaf5a2dSDavid Somayajulu goto exit_get_crash_record; 902afaf5a2dSDavid Somayajulu } 903afaf5a2dSDavid Somayajulu 904afaf5a2dSDavid Somayajulu /* Alloc Memory for Crash Record. */ 905afaf5a2dSDavid Somayajulu crash_record = dma_alloc_coherent(&ha->pdev->dev, crash_record_size, 906afaf5a2dSDavid Somayajulu &crash_record_dma, GFP_KERNEL); 907afaf5a2dSDavid Somayajulu if (crash_record == NULL) 908afaf5a2dSDavid Somayajulu goto exit_get_crash_record; 909afaf5a2dSDavid Somayajulu 910afaf5a2dSDavid Somayajulu /* Get Crash Record. */ 911c0e344c9SDavid C Somayajulu memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 912c0e344c9SDavid C Somayajulu memset(&mbox_sts, 0, sizeof(mbox_cmd)); 913c0e344c9SDavid C Somayajulu 914afaf5a2dSDavid Somayajulu mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD; 915afaf5a2dSDavid Somayajulu mbox_cmd[2] = LSDW(crash_record_dma); 916afaf5a2dSDavid Somayajulu mbox_cmd[3] = MSDW(crash_record_dma); 917afaf5a2dSDavid Somayajulu mbox_cmd[4] = crash_record_size; 918c0e344c9SDavid C Somayajulu 919c0e344c9SDavid C Somayajulu if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) != 920afaf5a2dSDavid Somayajulu QLA_SUCCESS) 921afaf5a2dSDavid Somayajulu goto exit_get_crash_record; 922afaf5a2dSDavid Somayajulu 923afaf5a2dSDavid Somayajulu /* Dump Crash Record. */ 924afaf5a2dSDavid Somayajulu 925afaf5a2dSDavid Somayajulu exit_get_crash_record: 926afaf5a2dSDavid Somayajulu if (crash_record) 927afaf5a2dSDavid Somayajulu dma_free_coherent(&ha->pdev->dev, crash_record_size, 928afaf5a2dSDavid Somayajulu crash_record, crash_record_dma); 929afaf5a2dSDavid Somayajulu } 930afaf5a2dSDavid Somayajulu 931afaf5a2dSDavid Somayajulu /** 932afaf5a2dSDavid Somayajulu * qla4xxx_get_conn_event_log - retrieves connection event log 933afaf5a2dSDavid Somayajulu * @ha: Pointer to host adapter structure. 934afaf5a2dSDavid Somayajulu **/ 935afaf5a2dSDavid Somayajulu void qla4xxx_get_conn_event_log(struct scsi_qla_host * ha) 936afaf5a2dSDavid Somayajulu { 937afaf5a2dSDavid Somayajulu uint32_t mbox_cmd[MBOX_REG_COUNT]; 938afaf5a2dSDavid Somayajulu uint32_t mbox_sts[MBOX_REG_COUNT]; 939afaf5a2dSDavid Somayajulu struct conn_event_log_entry *event_log = NULL; 940afaf5a2dSDavid Somayajulu dma_addr_t event_log_dma = 0; 941afaf5a2dSDavid Somayajulu uint32_t event_log_size = 0; 942afaf5a2dSDavid Somayajulu uint32_t num_valid_entries; 943afaf5a2dSDavid Somayajulu uint32_t oldest_entry = 0; 944afaf5a2dSDavid Somayajulu uint32_t max_event_log_entries; 945afaf5a2dSDavid Somayajulu uint8_t i; 946afaf5a2dSDavid Somayajulu 947afaf5a2dSDavid Somayajulu memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 948afaf5a2dSDavid Somayajulu memset(&mbox_sts, 0, sizeof(mbox_cmd)); 949afaf5a2dSDavid Somayajulu 950afaf5a2dSDavid Somayajulu /* Get size of crash record. */ 951afaf5a2dSDavid Somayajulu mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG; 952c0e344c9SDavid C Somayajulu 953c0e344c9SDavid C Somayajulu if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) != 954afaf5a2dSDavid Somayajulu QLA_SUCCESS) 955afaf5a2dSDavid Somayajulu goto exit_get_event_log; 956afaf5a2dSDavid Somayajulu 957afaf5a2dSDavid Somayajulu event_log_size = mbox_sts[4]; 958afaf5a2dSDavid Somayajulu if (event_log_size == 0) 959afaf5a2dSDavid Somayajulu goto exit_get_event_log; 960afaf5a2dSDavid Somayajulu 961afaf5a2dSDavid Somayajulu /* Alloc Memory for Crash Record. */ 962afaf5a2dSDavid Somayajulu event_log = dma_alloc_coherent(&ha->pdev->dev, event_log_size, 963afaf5a2dSDavid Somayajulu &event_log_dma, GFP_KERNEL); 964afaf5a2dSDavid Somayajulu if (event_log == NULL) 965afaf5a2dSDavid Somayajulu goto exit_get_event_log; 966afaf5a2dSDavid Somayajulu 967afaf5a2dSDavid Somayajulu /* Get Crash Record. */ 968c0e344c9SDavid C Somayajulu memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 969c0e344c9SDavid C Somayajulu memset(&mbox_sts, 0, sizeof(mbox_cmd)); 970c0e344c9SDavid C Somayajulu 971afaf5a2dSDavid Somayajulu mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG; 972afaf5a2dSDavid Somayajulu mbox_cmd[2] = LSDW(event_log_dma); 973afaf5a2dSDavid Somayajulu mbox_cmd[3] = MSDW(event_log_dma); 974c0e344c9SDavid C Somayajulu 975c0e344c9SDavid C Somayajulu if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) != 976afaf5a2dSDavid Somayajulu QLA_SUCCESS) { 977afaf5a2dSDavid Somayajulu DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve event " 978afaf5a2dSDavid Somayajulu "log!\n", ha->host_no, __func__)); 979afaf5a2dSDavid Somayajulu goto exit_get_event_log; 980afaf5a2dSDavid Somayajulu } 981afaf5a2dSDavid Somayajulu 982afaf5a2dSDavid Somayajulu /* Dump Event Log. */ 983afaf5a2dSDavid Somayajulu num_valid_entries = mbox_sts[1]; 984afaf5a2dSDavid Somayajulu 985afaf5a2dSDavid Somayajulu max_event_log_entries = event_log_size / 986afaf5a2dSDavid Somayajulu sizeof(struct conn_event_log_entry); 987afaf5a2dSDavid Somayajulu 988afaf5a2dSDavid Somayajulu if (num_valid_entries > max_event_log_entries) 989afaf5a2dSDavid Somayajulu oldest_entry = num_valid_entries % max_event_log_entries; 990afaf5a2dSDavid Somayajulu 991afaf5a2dSDavid Somayajulu DEBUG3(printk("scsi%ld: Connection Event Log Dump (%d entries):\n", 992afaf5a2dSDavid Somayajulu ha->host_no, num_valid_entries)); 993afaf5a2dSDavid Somayajulu 99411010fecSAndrew Vasquez if (ql4xextended_error_logging == 3) { 995afaf5a2dSDavid Somayajulu if (oldest_entry == 0) { 996afaf5a2dSDavid Somayajulu /* Circular Buffer has not wrapped around */ 997afaf5a2dSDavid Somayajulu for (i=0; i < num_valid_entries; i++) { 998afaf5a2dSDavid Somayajulu qla4xxx_dump_buffer((uint8_t *)event_log+ 999afaf5a2dSDavid Somayajulu (i*sizeof(*event_log)), 1000afaf5a2dSDavid Somayajulu sizeof(*event_log)); 1001afaf5a2dSDavid Somayajulu } 1002afaf5a2dSDavid Somayajulu } 1003afaf5a2dSDavid Somayajulu else { 1004afaf5a2dSDavid Somayajulu /* Circular Buffer has wrapped around - 1005afaf5a2dSDavid Somayajulu * display accordingly*/ 1006afaf5a2dSDavid Somayajulu for (i=oldest_entry; i < max_event_log_entries; i++) { 1007afaf5a2dSDavid Somayajulu qla4xxx_dump_buffer((uint8_t *)event_log+ 1008afaf5a2dSDavid Somayajulu (i*sizeof(*event_log)), 1009afaf5a2dSDavid Somayajulu sizeof(*event_log)); 1010afaf5a2dSDavid Somayajulu } 1011afaf5a2dSDavid Somayajulu for (i=0; i < oldest_entry; i++) { 1012afaf5a2dSDavid Somayajulu qla4xxx_dump_buffer((uint8_t *)event_log+ 1013afaf5a2dSDavid Somayajulu (i*sizeof(*event_log)), 1014afaf5a2dSDavid Somayajulu sizeof(*event_log)); 1015afaf5a2dSDavid Somayajulu } 1016afaf5a2dSDavid Somayajulu } 1017afaf5a2dSDavid Somayajulu } 1018afaf5a2dSDavid Somayajulu 1019afaf5a2dSDavid Somayajulu exit_get_event_log: 1020afaf5a2dSDavid Somayajulu if (event_log) 1021afaf5a2dSDavid Somayajulu dma_free_coherent(&ha->pdev->dev, event_log_size, event_log, 1022afaf5a2dSDavid Somayajulu event_log_dma); 1023afaf5a2dSDavid Somayajulu } 1024afaf5a2dSDavid Somayajulu 1025afaf5a2dSDavid Somayajulu /** 102609a0f719SVikas Chaudhary * qla4xxx_abort_task - issues Abort Task 102709a0f719SVikas Chaudhary * @ha: Pointer to host adapter structure. 102809a0f719SVikas Chaudhary * @srb: Pointer to srb entry 102909a0f719SVikas Chaudhary * 103009a0f719SVikas Chaudhary * This routine performs a LUN RESET on the specified target/lun. 103109a0f719SVikas Chaudhary * The caller must ensure that the ddb_entry and lun_entry pointers 103209a0f719SVikas Chaudhary * are valid before calling this routine. 103309a0f719SVikas Chaudhary **/ 103409a0f719SVikas Chaudhary int qla4xxx_abort_task(struct scsi_qla_host *ha, struct srb *srb) 103509a0f719SVikas Chaudhary { 103609a0f719SVikas Chaudhary uint32_t mbox_cmd[MBOX_REG_COUNT]; 103709a0f719SVikas Chaudhary uint32_t mbox_sts[MBOX_REG_COUNT]; 103809a0f719SVikas Chaudhary struct scsi_cmnd *cmd = srb->cmd; 103909a0f719SVikas Chaudhary int status = QLA_SUCCESS; 104009a0f719SVikas Chaudhary unsigned long flags = 0; 104109a0f719SVikas Chaudhary uint32_t index; 104209a0f719SVikas Chaudhary 104309a0f719SVikas Chaudhary /* 104409a0f719SVikas Chaudhary * Send abort task command to ISP, so that the ISP will return 104509a0f719SVikas Chaudhary * request with ABORT status 104609a0f719SVikas Chaudhary */ 104709a0f719SVikas Chaudhary memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 104809a0f719SVikas Chaudhary memset(&mbox_sts, 0, sizeof(mbox_sts)); 104909a0f719SVikas Chaudhary 105009a0f719SVikas Chaudhary spin_lock_irqsave(&ha->hardware_lock, flags); 105109a0f719SVikas Chaudhary index = (unsigned long)(unsigned char *)cmd->host_scribble; 105209a0f719SVikas Chaudhary spin_unlock_irqrestore(&ha->hardware_lock, flags); 105309a0f719SVikas Chaudhary 105409a0f719SVikas Chaudhary /* Firmware already posted completion on response queue */ 105509a0f719SVikas Chaudhary if (index == MAX_SRBS) 105609a0f719SVikas Chaudhary return status; 105709a0f719SVikas Chaudhary 105809a0f719SVikas Chaudhary mbox_cmd[0] = MBOX_CMD_ABORT_TASK; 10596790d4feSKaren Higgins mbox_cmd[1] = srb->ddb->fw_ddb_index; 106009a0f719SVikas Chaudhary mbox_cmd[2] = index; 106109a0f719SVikas Chaudhary /* Immediate Command Enable */ 106209a0f719SVikas Chaudhary mbox_cmd[5] = 0x01; 106309a0f719SVikas Chaudhary 106409a0f719SVikas Chaudhary qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], 106509a0f719SVikas Chaudhary &mbox_sts[0]); 106609a0f719SVikas Chaudhary if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE) { 106709a0f719SVikas Chaudhary status = QLA_ERROR; 106809a0f719SVikas Chaudhary 106909a0f719SVikas Chaudhary DEBUG2(printk(KERN_WARNING "scsi%ld:%d:%d: abort task FAILED: " 107009a0f719SVikas Chaudhary "mbx0=%04X, mb1=%04X, mb2=%04X, mb3=%04X, mb4=%04X\n", 107109a0f719SVikas Chaudhary ha->host_no, cmd->device->id, cmd->device->lun, mbox_sts[0], 107209a0f719SVikas Chaudhary mbox_sts[1], mbox_sts[2], mbox_sts[3], mbox_sts[4])); 107309a0f719SVikas Chaudhary } 107409a0f719SVikas Chaudhary 107509a0f719SVikas Chaudhary return status; 107609a0f719SVikas Chaudhary } 107709a0f719SVikas Chaudhary 107809a0f719SVikas Chaudhary /** 1079afaf5a2dSDavid Somayajulu * qla4xxx_reset_lun - issues LUN Reset 1080afaf5a2dSDavid Somayajulu * @ha: Pointer to host adapter structure. 1081f4f5df23SVikas Chaudhary * @ddb_entry: Pointer to device database entry 1082f4f5df23SVikas Chaudhary * @lun: lun number 1083afaf5a2dSDavid Somayajulu * 1084afaf5a2dSDavid Somayajulu * This routine performs a LUN RESET on the specified target/lun. 1085afaf5a2dSDavid Somayajulu * The caller must ensure that the ddb_entry and lun_entry pointers 1086afaf5a2dSDavid Somayajulu * are valid before calling this routine. 1087afaf5a2dSDavid Somayajulu **/ 1088afaf5a2dSDavid Somayajulu int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry, 1089afaf5a2dSDavid Somayajulu int lun) 1090afaf5a2dSDavid Somayajulu { 1091afaf5a2dSDavid Somayajulu uint32_t mbox_cmd[MBOX_REG_COUNT]; 1092afaf5a2dSDavid Somayajulu uint32_t mbox_sts[MBOX_REG_COUNT]; 1093afaf5a2dSDavid Somayajulu int status = QLA_SUCCESS; 1094afaf5a2dSDavid Somayajulu 1095afaf5a2dSDavid Somayajulu DEBUG2(printk("scsi%ld:%d:%d: lun reset issued\n", ha->host_no, 1096f4f5df23SVikas Chaudhary ddb_entry->fw_ddb_index, lun)); 1097afaf5a2dSDavid Somayajulu 1098afaf5a2dSDavid Somayajulu /* 1099afaf5a2dSDavid Somayajulu * Send lun reset command to ISP, so that the ISP will return all 1100afaf5a2dSDavid Somayajulu * outstanding requests with RESET status 1101afaf5a2dSDavid Somayajulu */ 1102afaf5a2dSDavid Somayajulu memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 1103afaf5a2dSDavid Somayajulu memset(&mbox_sts, 0, sizeof(mbox_sts)); 1104c0e344c9SDavid C Somayajulu 1105afaf5a2dSDavid Somayajulu mbox_cmd[0] = MBOX_CMD_LUN_RESET; 1106afaf5a2dSDavid Somayajulu mbox_cmd[1] = ddb_entry->fw_ddb_index; 1107afaf5a2dSDavid Somayajulu mbox_cmd[2] = lun << 8; 1108afaf5a2dSDavid Somayajulu mbox_cmd[5] = 0x01; /* Immediate Command Enable */ 1109c0e344c9SDavid C Somayajulu 1110c0e344c9SDavid C Somayajulu qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]); 1111afaf5a2dSDavid Somayajulu if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE && 1112afaf5a2dSDavid Somayajulu mbox_sts[0] != MBOX_STS_COMMAND_ERROR) 1113afaf5a2dSDavid Somayajulu status = QLA_ERROR; 1114afaf5a2dSDavid Somayajulu 1115afaf5a2dSDavid Somayajulu return status; 1116afaf5a2dSDavid Somayajulu } 1117afaf5a2dSDavid Somayajulu 1118ce545039SMike Christie /** 1119ce545039SMike Christie * qla4xxx_reset_target - issues target Reset 1120ce545039SMike Christie * @ha: Pointer to host adapter structure. 1121ce545039SMike Christie * @db_entry: Pointer to device database entry 1122ce545039SMike Christie * @un_entry: Pointer to lun entry structure 1123ce545039SMike Christie * 1124ce545039SMike Christie * This routine performs a TARGET RESET on the specified target. 1125ce545039SMike Christie * The caller must ensure that the ddb_entry pointers 1126ce545039SMike Christie * are valid before calling this routine. 1127ce545039SMike Christie **/ 1128ce545039SMike Christie int qla4xxx_reset_target(struct scsi_qla_host *ha, 1129ce545039SMike Christie struct ddb_entry *ddb_entry) 1130ce545039SMike Christie { 1131ce545039SMike Christie uint32_t mbox_cmd[MBOX_REG_COUNT]; 1132ce545039SMike Christie uint32_t mbox_sts[MBOX_REG_COUNT]; 1133ce545039SMike Christie int status = QLA_SUCCESS; 1134ce545039SMike Christie 1135ce545039SMike Christie DEBUG2(printk("scsi%ld:%d: target reset issued\n", ha->host_no, 1136f4f5df23SVikas Chaudhary ddb_entry->fw_ddb_index)); 1137ce545039SMike Christie 1138ce545039SMike Christie /* 1139ce545039SMike Christie * Send target reset command to ISP, so that the ISP will return all 1140ce545039SMike Christie * outstanding requests with RESET status 1141ce545039SMike Christie */ 1142ce545039SMike Christie memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 1143ce545039SMike Christie memset(&mbox_sts, 0, sizeof(mbox_sts)); 1144ce545039SMike Christie 1145ce545039SMike Christie mbox_cmd[0] = MBOX_CMD_TARGET_WARM_RESET; 1146ce545039SMike Christie mbox_cmd[1] = ddb_entry->fw_ddb_index; 1147ce545039SMike Christie mbox_cmd[5] = 0x01; /* Immediate Command Enable */ 1148ce545039SMike Christie 1149ce545039SMike Christie qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], 1150ce545039SMike Christie &mbox_sts[0]); 1151ce545039SMike Christie if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE && 1152ce545039SMike Christie mbox_sts[0] != MBOX_STS_COMMAND_ERROR) 1153ce545039SMike Christie status = QLA_ERROR; 1154ce545039SMike Christie 1155ce545039SMike Christie return status; 1156ce545039SMike Christie } 1157afaf5a2dSDavid Somayajulu 1158afaf5a2dSDavid Somayajulu int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr, 1159afaf5a2dSDavid Somayajulu uint32_t offset, uint32_t len) 1160afaf5a2dSDavid Somayajulu { 1161afaf5a2dSDavid Somayajulu uint32_t mbox_cmd[MBOX_REG_COUNT]; 1162afaf5a2dSDavid Somayajulu uint32_t mbox_sts[MBOX_REG_COUNT]; 1163afaf5a2dSDavid Somayajulu 1164afaf5a2dSDavid Somayajulu memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 1165afaf5a2dSDavid Somayajulu memset(&mbox_sts, 0, sizeof(mbox_sts)); 1166c0e344c9SDavid C Somayajulu 1167afaf5a2dSDavid Somayajulu mbox_cmd[0] = MBOX_CMD_READ_FLASH; 1168afaf5a2dSDavid Somayajulu mbox_cmd[1] = LSDW(dma_addr); 1169afaf5a2dSDavid Somayajulu mbox_cmd[2] = MSDW(dma_addr); 1170afaf5a2dSDavid Somayajulu mbox_cmd[3] = offset; 1171afaf5a2dSDavid Somayajulu mbox_cmd[4] = len; 1172c0e344c9SDavid C Somayajulu 1173c0e344c9SDavid C Somayajulu if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0], &mbox_sts[0]) != 1174afaf5a2dSDavid Somayajulu QLA_SUCCESS) { 1175afaf5a2dSDavid Somayajulu DEBUG2(printk("scsi%ld: %s: MBOX_CMD_READ_FLASH, failed w/ " 1176afaf5a2dSDavid Somayajulu "status %04X %04X, offset %08x, len %08x\n", ha->host_no, 1177afaf5a2dSDavid Somayajulu __func__, mbox_sts[0], mbox_sts[1], offset, len)); 1178afaf5a2dSDavid Somayajulu return QLA_ERROR; 1179afaf5a2dSDavid Somayajulu } 1180afaf5a2dSDavid Somayajulu return QLA_SUCCESS; 1181afaf5a2dSDavid Somayajulu } 1182afaf5a2dSDavid Somayajulu 1183afaf5a2dSDavid Somayajulu /** 11847ad633c0SHarish Zunjarrao * qla4xxx_about_firmware - gets FW, iscsi draft and boot loader version 1185afaf5a2dSDavid Somayajulu * @ha: Pointer to host adapter structure. 1186afaf5a2dSDavid Somayajulu * 11877ad633c0SHarish Zunjarrao * Retrieves the FW version, iSCSI draft version & bootloader version of HBA. 11887ad633c0SHarish Zunjarrao * Mailboxes 2 & 3 may hold an address for data. Make sure that we write 0 to 11897ad633c0SHarish Zunjarrao * those mailboxes, if unused. 1190afaf5a2dSDavid Somayajulu **/ 11917ad633c0SHarish Zunjarrao int qla4xxx_about_firmware(struct scsi_qla_host *ha) 1192afaf5a2dSDavid Somayajulu { 11937ad633c0SHarish Zunjarrao struct about_fw_info *about_fw = NULL; 11947ad633c0SHarish Zunjarrao dma_addr_t about_fw_dma; 1195afaf5a2dSDavid Somayajulu uint32_t mbox_cmd[MBOX_REG_COUNT]; 1196afaf5a2dSDavid Somayajulu uint32_t mbox_sts[MBOX_REG_COUNT]; 11977ad633c0SHarish Zunjarrao int status = QLA_ERROR; 1198afaf5a2dSDavid Somayajulu 11997ad633c0SHarish Zunjarrao about_fw = dma_alloc_coherent(&ha->pdev->dev, 12007ad633c0SHarish Zunjarrao sizeof(struct about_fw_info), 12017ad633c0SHarish Zunjarrao &about_fw_dma, GFP_KERNEL); 12027ad633c0SHarish Zunjarrao if (!about_fw) { 12037ad633c0SHarish Zunjarrao DEBUG2(ql4_printk(KERN_ERR, ha, "%s: Unable to alloc memory " 12047ad633c0SHarish Zunjarrao "for about_fw\n", __func__)); 12057ad633c0SHarish Zunjarrao return status; 12067ad633c0SHarish Zunjarrao } 12077ad633c0SHarish Zunjarrao 12087ad633c0SHarish Zunjarrao memset(about_fw, 0, sizeof(struct about_fw_info)); 1209afaf5a2dSDavid Somayajulu memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 1210afaf5a2dSDavid Somayajulu memset(&mbox_sts, 0, sizeof(mbox_sts)); 1211c0e344c9SDavid C Somayajulu 1212afaf5a2dSDavid Somayajulu mbox_cmd[0] = MBOX_CMD_ABOUT_FW; 12137ad633c0SHarish Zunjarrao mbox_cmd[2] = LSDW(about_fw_dma); 12147ad633c0SHarish Zunjarrao mbox_cmd[3] = MSDW(about_fw_dma); 12157ad633c0SHarish Zunjarrao mbox_cmd[4] = sizeof(struct about_fw_info); 1216c0e344c9SDavid C Somayajulu 12177ad633c0SHarish Zunjarrao status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT, 12187ad633c0SHarish Zunjarrao &mbox_cmd[0], &mbox_sts[0]); 12197ad633c0SHarish Zunjarrao if (status != QLA_SUCCESS) { 12207ad633c0SHarish Zunjarrao DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_ABOUT_FW " 12217ad633c0SHarish Zunjarrao "failed w/ status %04X\n", __func__, 12227ad633c0SHarish Zunjarrao mbox_sts[0])); 12237ad633c0SHarish Zunjarrao goto exit_about_fw; 1224afaf5a2dSDavid Somayajulu } 1225afaf5a2dSDavid Somayajulu 12267ad633c0SHarish Zunjarrao /* Save version information. */ 12277ad633c0SHarish Zunjarrao ha->firmware_version[0] = le16_to_cpu(about_fw->fw_major); 12287ad633c0SHarish Zunjarrao ha->firmware_version[1] = le16_to_cpu(about_fw->fw_minor); 12297ad633c0SHarish Zunjarrao ha->patch_number = le16_to_cpu(about_fw->fw_patch); 12307ad633c0SHarish Zunjarrao ha->build_number = le16_to_cpu(about_fw->fw_build); 12317ad633c0SHarish Zunjarrao ha->iscsi_major = le16_to_cpu(about_fw->iscsi_major); 12327ad633c0SHarish Zunjarrao ha->iscsi_minor = le16_to_cpu(about_fw->iscsi_minor); 12337ad633c0SHarish Zunjarrao ha->bootload_major = le16_to_cpu(about_fw->bootload_major); 12347ad633c0SHarish Zunjarrao ha->bootload_minor = le16_to_cpu(about_fw->bootload_minor); 12357ad633c0SHarish Zunjarrao ha->bootload_patch = le16_to_cpu(about_fw->bootload_patch); 12367ad633c0SHarish Zunjarrao ha->bootload_build = le16_to_cpu(about_fw->bootload_build); 12377ad633c0SHarish Zunjarrao status = QLA_SUCCESS; 1238afaf5a2dSDavid Somayajulu 12397ad633c0SHarish Zunjarrao exit_about_fw: 12407ad633c0SHarish Zunjarrao dma_free_coherent(&ha->pdev->dev, sizeof(struct about_fw_info), 12417ad633c0SHarish Zunjarrao about_fw, about_fw_dma); 12427ad633c0SHarish Zunjarrao return status; 1243afaf5a2dSDavid Somayajulu } 1244afaf5a2dSDavid Somayajulu 1245b3a271a9SManish Rangankar static int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, uint32_t options, 124647975477SAdrian Bunk dma_addr_t dma_addr) 1247afaf5a2dSDavid Somayajulu { 1248afaf5a2dSDavid Somayajulu uint32_t mbox_cmd[MBOX_REG_COUNT]; 1249afaf5a2dSDavid Somayajulu uint32_t mbox_sts[MBOX_REG_COUNT]; 1250afaf5a2dSDavid Somayajulu 1251afaf5a2dSDavid Somayajulu memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 1252afaf5a2dSDavid Somayajulu memset(&mbox_sts, 0, sizeof(mbox_sts)); 1253afaf5a2dSDavid Somayajulu 1254afaf5a2dSDavid Somayajulu mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY_DEFAULTS; 1255b3a271a9SManish Rangankar mbox_cmd[1] = options; 1256afaf5a2dSDavid Somayajulu mbox_cmd[2] = LSDW(dma_addr); 1257afaf5a2dSDavid Somayajulu mbox_cmd[3] = MSDW(dma_addr); 1258afaf5a2dSDavid Somayajulu 1259c0e344c9SDavid C Somayajulu if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) != 1260afaf5a2dSDavid Somayajulu QLA_SUCCESS) { 1261afaf5a2dSDavid Somayajulu DEBUG2(printk("scsi%ld: %s: failed status %04X\n", 1262afaf5a2dSDavid Somayajulu ha->host_no, __func__, mbox_sts[0])); 1263afaf5a2dSDavid Somayajulu return QLA_ERROR; 1264afaf5a2dSDavid Somayajulu } 1265afaf5a2dSDavid Somayajulu return QLA_SUCCESS; 1266afaf5a2dSDavid Somayajulu } 1267afaf5a2dSDavid Somayajulu 1268b3a271a9SManish Rangankar int qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t ddb_index, 1269b3a271a9SManish Rangankar uint32_t *mbx_sts) 1270afaf5a2dSDavid Somayajulu { 1271b3a271a9SManish Rangankar int status; 1272afaf5a2dSDavid Somayajulu uint32_t mbox_cmd[MBOX_REG_COUNT]; 1273afaf5a2dSDavid Somayajulu uint32_t mbox_sts[MBOX_REG_COUNT]; 1274afaf5a2dSDavid Somayajulu 1275afaf5a2dSDavid Somayajulu memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 1276afaf5a2dSDavid Somayajulu memset(&mbox_sts, 0, sizeof(mbox_sts)); 1277afaf5a2dSDavid Somayajulu 1278afaf5a2dSDavid Somayajulu mbox_cmd[0] = MBOX_CMD_REQUEST_DATABASE_ENTRY; 1279b3a271a9SManish Rangankar mbox_cmd[1] = ddb_index; 1280afaf5a2dSDavid Somayajulu 1281b3a271a9SManish Rangankar status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], 1282b3a271a9SManish Rangankar &mbox_sts[0]); 1283b3a271a9SManish Rangankar if (status != QLA_SUCCESS) { 1284b3a271a9SManish Rangankar DEBUG2(ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n", 1285b3a271a9SManish Rangankar __func__, mbox_sts[0])); 1286afaf5a2dSDavid Somayajulu } 1287afaf5a2dSDavid Somayajulu 1288b3a271a9SManish Rangankar *mbx_sts = mbox_sts[0]; 1289b3a271a9SManish Rangankar return status; 1290afaf5a2dSDavid Somayajulu } 1291afaf5a2dSDavid Somayajulu 1292b3a271a9SManish Rangankar int qla4xxx_clear_ddb_entry(struct scsi_qla_host *ha, uint32_t ddb_index) 1293b3a271a9SManish Rangankar { 1294b3a271a9SManish Rangankar int status; 1295b3a271a9SManish Rangankar uint32_t mbox_cmd[MBOX_REG_COUNT]; 1296b3a271a9SManish Rangankar uint32_t mbox_sts[MBOX_REG_COUNT]; 1297b3a271a9SManish Rangankar 1298b3a271a9SManish Rangankar memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 1299b3a271a9SManish Rangankar memset(&mbox_sts, 0, sizeof(mbox_sts)); 1300b3a271a9SManish Rangankar 1301b3a271a9SManish Rangankar mbox_cmd[0] = MBOX_CMD_CLEAR_DATABASE_ENTRY; 1302b3a271a9SManish Rangankar mbox_cmd[1] = ddb_index; 1303b3a271a9SManish Rangankar 1304b3a271a9SManish Rangankar status = qla4xxx_mailbox_command(ha, 2, 1, &mbox_cmd[0], 1305b3a271a9SManish Rangankar &mbox_sts[0]); 1306b3a271a9SManish Rangankar if (status != QLA_SUCCESS) { 1307b3a271a9SManish Rangankar DEBUG2(ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n", 1308b3a271a9SManish Rangankar __func__, mbox_sts[0])); 1309b3a271a9SManish Rangankar } 1310b3a271a9SManish Rangankar 1311b3a271a9SManish Rangankar return status; 1312b3a271a9SManish Rangankar } 1313b3a271a9SManish Rangankar 1314d00efe3fSMike Christie int qla4xxx_set_flash(struct scsi_qla_host *ha, dma_addr_t dma_addr, 1315d00efe3fSMike Christie uint32_t offset, uint32_t length, uint32_t options) 1316d00efe3fSMike Christie { 1317d00efe3fSMike Christie uint32_t mbox_cmd[MBOX_REG_COUNT]; 1318d00efe3fSMike Christie uint32_t mbox_sts[MBOX_REG_COUNT]; 1319d00efe3fSMike Christie int status = QLA_SUCCESS; 1320d00efe3fSMike Christie 1321d00efe3fSMike Christie memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 1322d00efe3fSMike Christie memset(&mbox_sts, 0, sizeof(mbox_sts)); 1323d00efe3fSMike Christie 1324d00efe3fSMike Christie mbox_cmd[0] = MBOX_CMD_WRITE_FLASH; 1325d00efe3fSMike Christie mbox_cmd[1] = LSDW(dma_addr); 1326d00efe3fSMike Christie mbox_cmd[2] = MSDW(dma_addr); 1327d00efe3fSMike Christie mbox_cmd[3] = offset; 1328d00efe3fSMike Christie mbox_cmd[4] = length; 1329d00efe3fSMike Christie mbox_cmd[5] = options; 1330d00efe3fSMike Christie 1331d00efe3fSMike Christie status = qla4xxx_mailbox_command(ha, 6, 2, &mbox_cmd[0], &mbox_sts[0]); 1332d00efe3fSMike Christie if (status != QLA_SUCCESS) { 1333d00efe3fSMike Christie DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_WRITE_FLASH " 1334d00efe3fSMike Christie "failed w/ status %04X, mbx1 %04X\n", 1335d00efe3fSMike Christie __func__, mbox_sts[0], mbox_sts[1])); 1336d00efe3fSMike Christie } 1337d00efe3fSMike Christie return status; 1338d00efe3fSMike Christie } 1339d00efe3fSMike Christie 13402a991c21SManish Rangankar int qla4xxx_bootdb_by_index(struct scsi_qla_host *ha, 13412a991c21SManish Rangankar struct dev_db_entry *fw_ddb_entry, 13422a991c21SManish Rangankar dma_addr_t fw_ddb_entry_dma, uint16_t ddb_index) 13432a991c21SManish Rangankar { 13442a991c21SManish Rangankar uint32_t dev_db_start_offset = FLASH_OFFSET_DB_INFO; 13452a991c21SManish Rangankar uint32_t dev_db_end_offset; 13462a991c21SManish Rangankar int status = QLA_ERROR; 13472a991c21SManish Rangankar 13482a991c21SManish Rangankar memset(fw_ddb_entry, 0, sizeof(*fw_ddb_entry)); 13492a991c21SManish Rangankar 13502a991c21SManish Rangankar dev_db_start_offset += (ddb_index * sizeof(*fw_ddb_entry)); 13512a991c21SManish Rangankar dev_db_end_offset = FLASH_OFFSET_DB_END; 13522a991c21SManish Rangankar 13532a991c21SManish Rangankar if (dev_db_start_offset > dev_db_end_offset) { 13542a991c21SManish Rangankar DEBUG2(ql4_printk(KERN_ERR, ha, 13552a991c21SManish Rangankar "%s:Invalid DDB index %d", __func__, 13562a991c21SManish Rangankar ddb_index)); 13572a991c21SManish Rangankar goto exit_bootdb_failed; 13582a991c21SManish Rangankar } 13592a991c21SManish Rangankar 13602a991c21SManish Rangankar if (qla4xxx_get_flash(ha, fw_ddb_entry_dma, dev_db_start_offset, 13612a991c21SManish Rangankar sizeof(*fw_ddb_entry)) != QLA_SUCCESS) { 13622a991c21SManish Rangankar ql4_printk(KERN_ERR, ha, "scsi%ld: %s: Get Flash" 13632a991c21SManish Rangankar "failed\n", ha->host_no, __func__); 13642a991c21SManish Rangankar goto exit_bootdb_failed; 13652a991c21SManish Rangankar } 13662a991c21SManish Rangankar 13672a991c21SManish Rangankar if (fw_ddb_entry->cookie == DDB_VALID_COOKIE) 13682a991c21SManish Rangankar status = QLA_SUCCESS; 13692a991c21SManish Rangankar 13702a991c21SManish Rangankar exit_bootdb_failed: 13712a991c21SManish Rangankar return status; 13722a991c21SManish Rangankar } 13732a991c21SManish Rangankar 13742a991c21SManish Rangankar int qla4xxx_get_chap(struct scsi_qla_host *ha, char *username, char *password, 13752a991c21SManish Rangankar uint16_t idx) 13762a991c21SManish Rangankar { 13772a991c21SManish Rangankar int ret = 0; 13782a991c21SManish Rangankar int rval = QLA_ERROR; 13794549415aSLalit Chandivade uint32_t offset = 0, chap_size; 13802a991c21SManish Rangankar struct ql4_chap_table *chap_table; 13812a991c21SManish Rangankar dma_addr_t chap_dma; 13822a991c21SManish Rangankar 13832a991c21SManish Rangankar chap_table = dma_pool_alloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma); 13842a991c21SManish Rangankar if (chap_table == NULL) { 13852a991c21SManish Rangankar ret = -ENOMEM; 13862a991c21SManish Rangankar goto exit_get_chap; 13872a991c21SManish Rangankar } 13882a991c21SManish Rangankar 13894549415aSLalit Chandivade chap_size = sizeof(struct ql4_chap_table); 13904549415aSLalit Chandivade memset(chap_table, 0, chap_size); 13912a991c21SManish Rangankar 13924549415aSLalit Chandivade if (is_qla40XX(ha)) 13934549415aSLalit Chandivade offset = FLASH_CHAP_OFFSET | (idx * chap_size); 13944549415aSLalit Chandivade else { 13954549415aSLalit Chandivade offset = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_region_chap << 2); 13964549415aSLalit Chandivade /* flt_chap_size is CHAP table size for both ports 13974549415aSLalit Chandivade * so divide it by 2 to calculate the offset for second port 13984549415aSLalit Chandivade */ 13994549415aSLalit Chandivade if (ha->port_num == 1) 14004549415aSLalit Chandivade offset += (ha->hw.flt_chap_size / 2); 14014549415aSLalit Chandivade offset += (idx * chap_size); 14024549415aSLalit Chandivade } 14032a991c21SManish Rangankar 14044549415aSLalit Chandivade rval = qla4xxx_get_flash(ha, chap_dma, offset, chap_size); 14052a991c21SManish Rangankar if (rval != QLA_SUCCESS) { 14062a991c21SManish Rangankar ret = -EINVAL; 14072a991c21SManish Rangankar goto exit_get_chap; 14082a991c21SManish Rangankar } 14092a991c21SManish Rangankar 14102a991c21SManish Rangankar DEBUG2(ql4_printk(KERN_INFO, ha, "Chap Cookie: x%x\n", 14112a991c21SManish Rangankar __le16_to_cpu(chap_table->cookie))); 14122a991c21SManish Rangankar 14132a991c21SManish Rangankar if (__le16_to_cpu(chap_table->cookie) != CHAP_VALID_COOKIE) { 14142a991c21SManish Rangankar ql4_printk(KERN_ERR, ha, "No valid chap entry found\n"); 14152a991c21SManish Rangankar goto exit_get_chap; 14162a991c21SManish Rangankar } 14172a991c21SManish Rangankar 14182a991c21SManish Rangankar strncpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN); 14192a991c21SManish Rangankar strncpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN); 14202a991c21SManish Rangankar chap_table->cookie = __constant_cpu_to_le16(CHAP_VALID_COOKIE); 14212a991c21SManish Rangankar 14222a991c21SManish Rangankar exit_get_chap: 14232a991c21SManish Rangankar dma_pool_free(ha->chap_dma_pool, chap_table, chap_dma); 14242a991c21SManish Rangankar return ret; 14252a991c21SManish Rangankar } 14262a991c21SManish Rangankar 1427b3a271a9SManish Rangankar static int qla4xxx_set_chap(struct scsi_qla_host *ha, char *username, 1428b3a271a9SManish Rangankar char *password, uint16_t idx, int bidi) 1429b3a271a9SManish Rangankar { 1430b3a271a9SManish Rangankar int ret = 0; 1431b3a271a9SManish Rangankar int rval = QLA_ERROR; 1432b3a271a9SManish Rangankar uint32_t offset = 0; 1433b3a271a9SManish Rangankar struct ql4_chap_table *chap_table; 1434b3a271a9SManish Rangankar dma_addr_t chap_dma; 1435b3a271a9SManish Rangankar 1436b3a271a9SManish Rangankar chap_table = dma_pool_alloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma); 1437b3a271a9SManish Rangankar if (chap_table == NULL) { 1438b3a271a9SManish Rangankar ret = -ENOMEM; 1439b3a271a9SManish Rangankar goto exit_set_chap; 1440b3a271a9SManish Rangankar } 1441b3a271a9SManish Rangankar 1442b3a271a9SManish Rangankar memset(chap_table, 0, sizeof(struct ql4_chap_table)); 1443b3a271a9SManish Rangankar if (bidi) 1444b3a271a9SManish Rangankar chap_table->flags |= BIT_6; /* peer */ 1445b3a271a9SManish Rangankar else 1446b3a271a9SManish Rangankar chap_table->flags |= BIT_7; /* local */ 1447b3a271a9SManish Rangankar chap_table->secret_len = strlen(password); 1448b3a271a9SManish Rangankar strncpy(chap_table->secret, password, MAX_CHAP_SECRET_LEN); 1449b3a271a9SManish Rangankar strncpy(chap_table->name, username, MAX_CHAP_NAME_LEN); 1450b3a271a9SManish Rangankar chap_table->cookie = __constant_cpu_to_le16(CHAP_VALID_COOKIE); 14514549415aSLalit Chandivade offset = FLASH_CHAP_OFFSET | (idx * sizeof(struct ql4_chap_table)); 1452b3a271a9SManish Rangankar rval = qla4xxx_set_flash(ha, chap_dma, offset, 1453b3a271a9SManish Rangankar sizeof(struct ql4_chap_table), 1454b3a271a9SManish Rangankar FLASH_OPT_RMW_COMMIT); 14554549415aSLalit Chandivade 14564549415aSLalit Chandivade if (rval == QLA_SUCCESS && ha->chap_list) { 14574549415aSLalit Chandivade /* Update ha chap_list cache */ 14584549415aSLalit Chandivade memcpy((struct ql4_chap_table *)ha->chap_list + idx, 14594549415aSLalit Chandivade chap_table, sizeof(struct ql4_chap_table)); 14604549415aSLalit Chandivade } 1461b3a271a9SManish Rangankar dma_pool_free(ha->chap_dma_pool, chap_table, chap_dma); 1462b3a271a9SManish Rangankar if (rval != QLA_SUCCESS) 1463b3a271a9SManish Rangankar ret = -EINVAL; 1464b3a271a9SManish Rangankar 1465b3a271a9SManish Rangankar exit_set_chap: 1466b3a271a9SManish Rangankar return ret; 1467b3a271a9SManish Rangankar } 1468b3a271a9SManish Rangankar 14694549415aSLalit Chandivade /** 14704549415aSLalit Chandivade * qla4xxx_get_chap_index - Get chap index given username and secret 14714549415aSLalit Chandivade * @ha: pointer to adapter structure 14724549415aSLalit Chandivade * @username: CHAP username to be searched 14734549415aSLalit Chandivade * @password: CHAP password to be searched 14744549415aSLalit Chandivade * @bidi: Is this a BIDI CHAP 14754549415aSLalit Chandivade * @chap_index: CHAP index to be returned 14764549415aSLalit Chandivade * 14774549415aSLalit Chandivade * Match the username and password in the chap_list, return the index if a 14784549415aSLalit Chandivade * match is found. If a match is not found then add the entry in FLASH and 14794549415aSLalit Chandivade * return the index at which entry is written in the FLASH. 14804549415aSLalit Chandivade **/ 1481fca9f04dSMike Christie int qla4xxx_get_chap_index(struct scsi_qla_host *ha, char *username, 14824549415aSLalit Chandivade char *password, int bidi, uint16_t *chap_index) 14834549415aSLalit Chandivade { 14844549415aSLalit Chandivade int i, rval; 14854549415aSLalit Chandivade int free_index = -1; 14864549415aSLalit Chandivade int found_index = 0; 14874549415aSLalit Chandivade int max_chap_entries = 0; 14884549415aSLalit Chandivade struct ql4_chap_table *chap_table; 14894549415aSLalit Chandivade 14904549415aSLalit Chandivade if (is_qla8022(ha)) 14914549415aSLalit Chandivade max_chap_entries = (ha->hw.flt_chap_size / 2) / 14924549415aSLalit Chandivade sizeof(struct ql4_chap_table); 14934549415aSLalit Chandivade else 14944549415aSLalit Chandivade max_chap_entries = MAX_CHAP_ENTRIES_40XX; 14954549415aSLalit Chandivade 14964549415aSLalit Chandivade if (!ha->chap_list) { 14974549415aSLalit Chandivade ql4_printk(KERN_ERR, ha, "Do not have CHAP table cache\n"); 14984549415aSLalit Chandivade return QLA_ERROR; 14994549415aSLalit Chandivade } 15004549415aSLalit Chandivade 1501fca9f04dSMike Christie if (!username || !password) { 1502fca9f04dSMike Christie ql4_printk(KERN_ERR, ha, "Do not have username and psw\n"); 1503fca9f04dSMike Christie return QLA_ERROR; 1504fca9f04dSMike Christie } 1505fca9f04dSMike Christie 15064549415aSLalit Chandivade mutex_lock(&ha->chap_sem); 15074549415aSLalit Chandivade for (i = 0; i < max_chap_entries; i++) { 15084549415aSLalit Chandivade chap_table = (struct ql4_chap_table *)ha->chap_list + i; 15094549415aSLalit Chandivade if (chap_table->cookie != 15104549415aSLalit Chandivade __constant_cpu_to_le16(CHAP_VALID_COOKIE)) { 15114549415aSLalit Chandivade if (i > MAX_RESRV_CHAP_IDX && free_index == -1) 15124549415aSLalit Chandivade free_index = i; 15134549415aSLalit Chandivade continue; 15144549415aSLalit Chandivade } 15154549415aSLalit Chandivade if (bidi) { 15164549415aSLalit Chandivade if (chap_table->flags & BIT_7) 15174549415aSLalit Chandivade continue; 15184549415aSLalit Chandivade } else { 15194549415aSLalit Chandivade if (chap_table->flags & BIT_6) 15204549415aSLalit Chandivade continue; 15214549415aSLalit Chandivade } 15224549415aSLalit Chandivade if (!strncmp(chap_table->secret, password, 15234549415aSLalit Chandivade MAX_CHAP_SECRET_LEN) && 15244549415aSLalit Chandivade !strncmp(chap_table->name, username, 15254549415aSLalit Chandivade MAX_CHAP_NAME_LEN)) { 15264549415aSLalit Chandivade *chap_index = i; 15274549415aSLalit Chandivade found_index = 1; 15284549415aSLalit Chandivade break; 15294549415aSLalit Chandivade } 15304549415aSLalit Chandivade } 15314549415aSLalit Chandivade 15324549415aSLalit Chandivade /* If chap entry is not present and a free index is available then 15334549415aSLalit Chandivade * write the entry in flash 15344549415aSLalit Chandivade */ 15354549415aSLalit Chandivade if (!found_index && free_index != -1) { 15364549415aSLalit Chandivade rval = qla4xxx_set_chap(ha, username, password, 15374549415aSLalit Chandivade free_index, bidi); 15384549415aSLalit Chandivade if (!rval) { 15394549415aSLalit Chandivade *chap_index = free_index; 15404549415aSLalit Chandivade found_index = 1; 15414549415aSLalit Chandivade } 15424549415aSLalit Chandivade } 15434549415aSLalit Chandivade 15444549415aSLalit Chandivade mutex_unlock(&ha->chap_sem); 15454549415aSLalit Chandivade 15464549415aSLalit Chandivade if (found_index) 15474549415aSLalit Chandivade return QLA_SUCCESS; 15484549415aSLalit Chandivade return QLA_ERROR; 15494549415aSLalit Chandivade } 15504549415aSLalit Chandivade 1551d00efe3fSMike Christie int qla4xxx_conn_close_sess_logout(struct scsi_qla_host *ha, 1552d00efe3fSMike Christie uint16_t fw_ddb_index, 1553d00efe3fSMike Christie uint16_t connection_id, 1554d00efe3fSMike Christie uint16_t option) 1555d00efe3fSMike Christie { 1556d00efe3fSMike Christie uint32_t mbox_cmd[MBOX_REG_COUNT]; 1557d00efe3fSMike Christie uint32_t mbox_sts[MBOX_REG_COUNT]; 1558d00efe3fSMike Christie int status = QLA_SUCCESS; 1559d00efe3fSMike Christie 1560d00efe3fSMike Christie memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 1561d00efe3fSMike Christie memset(&mbox_sts, 0, sizeof(mbox_sts)); 1562d00efe3fSMike Christie 1563d00efe3fSMike Christie mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT; 1564d00efe3fSMike Christie mbox_cmd[1] = fw_ddb_index; 1565d00efe3fSMike Christie mbox_cmd[2] = connection_id; 1566d00efe3fSMike Christie mbox_cmd[3] = option; 1567d00efe3fSMike Christie 1568d00efe3fSMike Christie status = qla4xxx_mailbox_command(ha, 4, 2, &mbox_cmd[0], &mbox_sts[0]); 1569d00efe3fSMike Christie if (status != QLA_SUCCESS) { 1570d00efe3fSMike Christie DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_CONN_CLOSE " 1571d00efe3fSMike Christie "option %04x failed w/ status %04X %04X\n", 1572d00efe3fSMike Christie __func__, option, mbox_sts[0], mbox_sts[1])); 1573d00efe3fSMike Christie } 1574d00efe3fSMike Christie return status; 1575d00efe3fSMike Christie } 1576d00efe3fSMike Christie 1577d00efe3fSMike Christie int qla4xxx_disable_acb(struct scsi_qla_host *ha) 1578d00efe3fSMike Christie { 1579d00efe3fSMike Christie uint32_t mbox_cmd[MBOX_REG_COUNT]; 1580d00efe3fSMike Christie uint32_t mbox_sts[MBOX_REG_COUNT]; 1581d00efe3fSMike Christie int status = QLA_SUCCESS; 1582d00efe3fSMike Christie 1583d00efe3fSMike Christie memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 1584d00efe3fSMike Christie memset(&mbox_sts, 0, sizeof(mbox_sts)); 1585d00efe3fSMike Christie 1586d00efe3fSMike Christie mbox_cmd[0] = MBOX_CMD_DISABLE_ACB; 1587d00efe3fSMike Christie 1588d00efe3fSMike Christie status = qla4xxx_mailbox_command(ha, 8, 5, &mbox_cmd[0], &mbox_sts[0]); 1589d00efe3fSMike Christie if (status != QLA_SUCCESS) { 1590d00efe3fSMike Christie DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_DISABLE_ACB " 1591d00efe3fSMike Christie "failed w/ status %04X %04X %04X", __func__, 1592d00efe3fSMike Christie mbox_sts[0], mbox_sts[1], mbox_sts[2])); 1593d00efe3fSMike Christie } 1594d00efe3fSMike Christie return status; 1595d00efe3fSMike Christie } 1596d00efe3fSMike Christie 15976085491cSHarish Zunjarrao int qla4xxx_get_acb(struct scsi_qla_host *ha, dma_addr_t acb_dma, 15986085491cSHarish Zunjarrao uint32_t acb_type, uint32_t len) 1599d00efe3fSMike Christie { 16006085491cSHarish Zunjarrao uint32_t mbox_cmd[MBOX_REG_COUNT]; 16016085491cSHarish Zunjarrao uint32_t mbox_sts[MBOX_REG_COUNT]; 1602d00efe3fSMike Christie int status = QLA_SUCCESS; 1603d00efe3fSMike Christie 16046085491cSHarish Zunjarrao memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 16056085491cSHarish Zunjarrao memset(&mbox_sts, 0, sizeof(mbox_sts)); 16066085491cSHarish Zunjarrao 1607d00efe3fSMike Christie mbox_cmd[0] = MBOX_CMD_GET_ACB; 16086085491cSHarish Zunjarrao mbox_cmd[1] = acb_type; 1609d00efe3fSMike Christie mbox_cmd[2] = LSDW(acb_dma); 1610d00efe3fSMike Christie mbox_cmd[3] = MSDW(acb_dma); 16116085491cSHarish Zunjarrao mbox_cmd[4] = len; 1612d00efe3fSMike Christie 1613d00efe3fSMike Christie status = qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]); 1614d00efe3fSMike Christie if (status != QLA_SUCCESS) { 1615d00efe3fSMike Christie DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_GET_ACB " 1616d00efe3fSMike Christie "failed w/ status %04X\n", __func__, 1617d00efe3fSMike Christie mbox_sts[0])); 1618d00efe3fSMike Christie } 1619d00efe3fSMike Christie return status; 1620d00efe3fSMike Christie } 1621d00efe3fSMike Christie 1622d00efe3fSMike Christie int qla4xxx_set_acb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, 1623d00efe3fSMike Christie uint32_t *mbox_sts, dma_addr_t acb_dma) 1624d00efe3fSMike Christie { 1625d00efe3fSMike Christie int status = QLA_SUCCESS; 1626d00efe3fSMike Christie 1627d00efe3fSMike Christie memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT); 1628d00efe3fSMike Christie memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT); 1629d00efe3fSMike Christie mbox_cmd[0] = MBOX_CMD_SET_ACB; 1630d00efe3fSMike Christie mbox_cmd[1] = 0; /* Primary ACB */ 1631d00efe3fSMike Christie mbox_cmd[2] = LSDW(acb_dma); 1632d00efe3fSMike Christie mbox_cmd[3] = MSDW(acb_dma); 1633d00efe3fSMike Christie mbox_cmd[4] = sizeof(struct addr_ctrl_blk); 1634d00efe3fSMike Christie 1635d00efe3fSMike Christie status = qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]); 1636d00efe3fSMike Christie if (status != QLA_SUCCESS) { 1637d00efe3fSMike Christie DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_SET_ACB " 1638d00efe3fSMike Christie "failed w/ status %04X\n", __func__, 1639d00efe3fSMike Christie mbox_sts[0])); 1640d00efe3fSMike Christie } 1641d00efe3fSMike Christie return status; 1642d00efe3fSMike Christie } 1643b3a271a9SManish Rangankar 1644b3a271a9SManish Rangankar int qla4xxx_set_param_ddbentry(struct scsi_qla_host *ha, 1645b3a271a9SManish Rangankar struct ddb_entry *ddb_entry, 1646b3a271a9SManish Rangankar struct iscsi_cls_conn *cls_conn, 1647b3a271a9SManish Rangankar uint32_t *mbx_sts) 1648b3a271a9SManish Rangankar { 1649b3a271a9SManish Rangankar struct dev_db_entry *fw_ddb_entry; 1650b3a271a9SManish Rangankar struct iscsi_conn *conn; 1651b3a271a9SManish Rangankar struct iscsi_session *sess; 1652b3a271a9SManish Rangankar struct qla_conn *qla_conn; 1653b3a271a9SManish Rangankar struct sockaddr *dst_addr; 1654b3a271a9SManish Rangankar dma_addr_t fw_ddb_entry_dma; 1655b3a271a9SManish Rangankar int status = QLA_SUCCESS; 1656b3a271a9SManish Rangankar int rval = 0; 1657b3a271a9SManish Rangankar struct sockaddr_in *addr; 1658b3a271a9SManish Rangankar struct sockaddr_in6 *addr6; 1659b3a271a9SManish Rangankar char *ip; 1660b3a271a9SManish Rangankar uint16_t iscsi_opts = 0; 1661b3a271a9SManish Rangankar uint32_t options = 0; 1662173269efSManish Rangankar uint16_t idx, *ptid; 1663b3a271a9SManish Rangankar 1664b3a271a9SManish Rangankar fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), 1665b3a271a9SManish Rangankar &fw_ddb_entry_dma, GFP_KERNEL); 1666b3a271a9SManish Rangankar if (!fw_ddb_entry) { 1667b3a271a9SManish Rangankar DEBUG2(ql4_printk(KERN_ERR, ha, 1668b3a271a9SManish Rangankar "%s: Unable to allocate dma buffer.\n", 1669b3a271a9SManish Rangankar __func__)); 1670b3a271a9SManish Rangankar rval = -ENOMEM; 1671b3a271a9SManish Rangankar goto exit_set_param_no_free; 1672b3a271a9SManish Rangankar } 1673b3a271a9SManish Rangankar 1674b3a271a9SManish Rangankar conn = cls_conn->dd_data; 1675b3a271a9SManish Rangankar qla_conn = conn->dd_data; 1676b3a271a9SManish Rangankar sess = conn->session; 1677d46bdeb1SManish Rangankar dst_addr = (struct sockaddr *)&qla_conn->qla_ep->dst_addr; 1678b3a271a9SManish Rangankar 1679b3a271a9SManish Rangankar if (dst_addr->sa_family == AF_INET6) 1680b3a271a9SManish Rangankar options |= IPV6_DEFAULT_DDB_ENTRY; 1681b3a271a9SManish Rangankar 1682b3a271a9SManish Rangankar status = qla4xxx_get_default_ddb(ha, options, fw_ddb_entry_dma); 1683b3a271a9SManish Rangankar if (status == QLA_ERROR) { 1684b3a271a9SManish Rangankar rval = -EINVAL; 1685b3a271a9SManish Rangankar goto exit_set_param; 1686b3a271a9SManish Rangankar } 1687b3a271a9SManish Rangankar 1688173269efSManish Rangankar ptid = (uint16_t *)&fw_ddb_entry->isid[1]; 1689173269efSManish Rangankar *ptid = cpu_to_le16((uint16_t)ddb_entry->sess->target_id); 1690173269efSManish Rangankar 1691173269efSManish Rangankar DEBUG2(ql4_printk(KERN_INFO, ha, "ISID [%02x%02x%02x%02x%02x%02x]\n", 1692173269efSManish Rangankar fw_ddb_entry->isid[5], fw_ddb_entry->isid[4], 1693173269efSManish Rangankar fw_ddb_entry->isid[3], fw_ddb_entry->isid[2], 1694173269efSManish Rangankar fw_ddb_entry->isid[1], fw_ddb_entry->isid[0])); 1695173269efSManish Rangankar 1696b3a271a9SManish Rangankar iscsi_opts = le16_to_cpu(fw_ddb_entry->iscsi_options); 1697b3a271a9SManish Rangankar memset(fw_ddb_entry->iscsi_alias, 0, sizeof(fw_ddb_entry->iscsi_alias)); 1698b3a271a9SManish Rangankar 1699b3a271a9SManish Rangankar memset(fw_ddb_entry->iscsi_name, 0, sizeof(fw_ddb_entry->iscsi_name)); 1700b3a271a9SManish Rangankar 1701b3a271a9SManish Rangankar if (sess->targetname != NULL) { 1702b3a271a9SManish Rangankar memcpy(fw_ddb_entry->iscsi_name, sess->targetname, 1703b3a271a9SManish Rangankar min(strlen(sess->targetname), 1704b3a271a9SManish Rangankar sizeof(fw_ddb_entry->iscsi_name))); 1705b3a271a9SManish Rangankar } 1706b3a271a9SManish Rangankar 1707b3a271a9SManish Rangankar memset(fw_ddb_entry->ip_addr, 0, sizeof(fw_ddb_entry->ip_addr)); 1708b3a271a9SManish Rangankar memset(fw_ddb_entry->tgt_addr, 0, sizeof(fw_ddb_entry->tgt_addr)); 1709b3a271a9SManish Rangankar 1710b3a271a9SManish Rangankar fw_ddb_entry->options = DDB_OPT_TARGET | DDB_OPT_AUTO_SENDTGTS_DISABLE; 1711b3a271a9SManish Rangankar 1712b3a271a9SManish Rangankar if (dst_addr->sa_family == AF_INET) { 1713b3a271a9SManish Rangankar addr = (struct sockaddr_in *)dst_addr; 1714b3a271a9SManish Rangankar ip = (char *)&addr->sin_addr; 1715b3a271a9SManish Rangankar memcpy(fw_ddb_entry->ip_addr, ip, IP_ADDR_LEN); 1716b3a271a9SManish Rangankar fw_ddb_entry->port = cpu_to_le16(ntohs(addr->sin_port)); 1717b3a271a9SManish Rangankar DEBUG2(ql4_printk(KERN_INFO, ha, 1718b3a271a9SManish Rangankar "%s: Destination Address [%pI4]: index [%d]\n", 1719b3a271a9SManish Rangankar __func__, fw_ddb_entry->ip_addr, 1720b3a271a9SManish Rangankar ddb_entry->fw_ddb_index)); 1721b3a271a9SManish Rangankar } else if (dst_addr->sa_family == AF_INET6) { 1722b3a271a9SManish Rangankar addr6 = (struct sockaddr_in6 *)dst_addr; 1723b3a271a9SManish Rangankar ip = (char *)&addr6->sin6_addr; 1724b3a271a9SManish Rangankar memcpy(fw_ddb_entry->ip_addr, ip, IPv6_ADDR_LEN); 1725b3a271a9SManish Rangankar fw_ddb_entry->port = cpu_to_le16(ntohs(addr6->sin6_port)); 1726b3a271a9SManish Rangankar fw_ddb_entry->options |= DDB_OPT_IPV6_DEVICE; 1727b3a271a9SManish Rangankar DEBUG2(ql4_printk(KERN_INFO, ha, 1728b3a271a9SManish Rangankar "%s: Destination Address [%pI6]: index [%d]\n", 1729b3a271a9SManish Rangankar __func__, fw_ddb_entry->ip_addr, 1730b3a271a9SManish Rangankar ddb_entry->fw_ddb_index)); 1731b3a271a9SManish Rangankar } else { 1732b3a271a9SManish Rangankar ql4_printk(KERN_ERR, ha, 1733b3a271a9SManish Rangankar "%s: Failed to get IP Address\n", 1734b3a271a9SManish Rangankar __func__); 1735b3a271a9SManish Rangankar rval = -EINVAL; 1736b3a271a9SManish Rangankar goto exit_set_param; 1737b3a271a9SManish Rangankar } 1738b3a271a9SManish Rangankar 1739b3a271a9SManish Rangankar /* CHAP */ 1740b3a271a9SManish Rangankar if (sess->username != NULL && sess->password != NULL) { 1741b3a271a9SManish Rangankar if (strlen(sess->username) && strlen(sess->password)) { 1742b3a271a9SManish Rangankar iscsi_opts |= BIT_7; 1743b3a271a9SManish Rangankar 17444549415aSLalit Chandivade rval = qla4xxx_get_chap_index(ha, sess->username, 17454549415aSLalit Chandivade sess->password, 17464549415aSLalit Chandivade LOCAL_CHAP, &idx); 1747b3a271a9SManish Rangankar if (rval) 1748b3a271a9SManish Rangankar goto exit_set_param; 1749b3a271a9SManish Rangankar 1750b3a271a9SManish Rangankar fw_ddb_entry->chap_tbl_idx = cpu_to_le16(idx); 1751b3a271a9SManish Rangankar } 1752b3a271a9SManish Rangankar } 1753b3a271a9SManish Rangankar 1754b3a271a9SManish Rangankar if (sess->username_in != NULL && sess->password_in != NULL) { 1755b3a271a9SManish Rangankar /* Check if BIDI CHAP */ 1756b3a271a9SManish Rangankar if (strlen(sess->username_in) && strlen(sess->password_in)) { 1757b3a271a9SManish Rangankar iscsi_opts |= BIT_4; 17584549415aSLalit Chandivade 17594549415aSLalit Chandivade rval = qla4xxx_get_chap_index(ha, sess->username_in, 17604549415aSLalit Chandivade sess->password_in, 17614549415aSLalit Chandivade BIDI_CHAP, &idx); 1762b3a271a9SManish Rangankar if (rval) 1763b3a271a9SManish Rangankar goto exit_set_param; 1764b3a271a9SManish Rangankar } 1765b3a271a9SManish Rangankar } 1766b3a271a9SManish Rangankar 1767b3a271a9SManish Rangankar if (sess->initial_r2t_en) 1768b3a271a9SManish Rangankar iscsi_opts |= BIT_10; 1769b3a271a9SManish Rangankar 1770b3a271a9SManish Rangankar if (sess->imm_data_en) 1771b3a271a9SManish Rangankar iscsi_opts |= BIT_11; 1772b3a271a9SManish Rangankar 1773b3a271a9SManish Rangankar fw_ddb_entry->iscsi_options = cpu_to_le16(iscsi_opts); 1774b3a271a9SManish Rangankar 1775b3a271a9SManish Rangankar if (conn->max_recv_dlength) 1776b3a271a9SManish Rangankar fw_ddb_entry->iscsi_max_rcv_data_seg_len = 1777b3a271a9SManish Rangankar __constant_cpu_to_le16((conn->max_recv_dlength / BYTE_UNITS)); 1778b3a271a9SManish Rangankar 1779b3a271a9SManish Rangankar if (sess->max_r2t) 1780b3a271a9SManish Rangankar fw_ddb_entry->iscsi_max_outsnd_r2t = cpu_to_le16(sess->max_r2t); 1781b3a271a9SManish Rangankar 1782b3a271a9SManish Rangankar if (sess->first_burst) 1783b3a271a9SManish Rangankar fw_ddb_entry->iscsi_first_burst_len = 1784b3a271a9SManish Rangankar __constant_cpu_to_le16((sess->first_burst / BYTE_UNITS)); 1785b3a271a9SManish Rangankar 1786b3a271a9SManish Rangankar if (sess->max_burst) 1787b3a271a9SManish Rangankar fw_ddb_entry->iscsi_max_burst_len = 1788b3a271a9SManish Rangankar __constant_cpu_to_le16((sess->max_burst / BYTE_UNITS)); 1789b3a271a9SManish Rangankar 1790b3a271a9SManish Rangankar if (sess->time2wait) 1791b3a271a9SManish Rangankar fw_ddb_entry->iscsi_def_time2wait = 1792b3a271a9SManish Rangankar cpu_to_le16(sess->time2wait); 1793b3a271a9SManish Rangankar 1794b3a271a9SManish Rangankar if (sess->time2retain) 1795b3a271a9SManish Rangankar fw_ddb_entry->iscsi_def_time2retain = 1796b3a271a9SManish Rangankar cpu_to_le16(sess->time2retain); 1797b3a271a9SManish Rangankar 1798b3a271a9SManish Rangankar status = qla4xxx_set_ddb_entry(ha, ddb_entry->fw_ddb_index, 1799b3a271a9SManish Rangankar fw_ddb_entry_dma, mbx_sts); 1800b3a271a9SManish Rangankar 1801b3a271a9SManish Rangankar if (status != QLA_SUCCESS) 1802b3a271a9SManish Rangankar rval = -EINVAL; 1803b3a271a9SManish Rangankar exit_set_param: 1804b3a271a9SManish Rangankar dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), 1805b3a271a9SManish Rangankar fw_ddb_entry, fw_ddb_entry_dma); 1806b3a271a9SManish Rangankar exit_set_param_no_free: 1807b3a271a9SManish Rangankar return rval; 1808b3a271a9SManish Rangankar } 1809b3a271a9SManish Rangankar 1810b3a271a9SManish Rangankar int qla4xxx_get_mgmt_data(struct scsi_qla_host *ha, uint16_t fw_ddb_index, 1811b3a271a9SManish Rangankar uint16_t stats_size, dma_addr_t stats_dma) 1812b3a271a9SManish Rangankar { 1813b3a271a9SManish Rangankar int status = QLA_SUCCESS; 1814b3a271a9SManish Rangankar uint32_t mbox_cmd[MBOX_REG_COUNT]; 1815b3a271a9SManish Rangankar uint32_t mbox_sts[MBOX_REG_COUNT]; 1816b3a271a9SManish Rangankar 1817b3a271a9SManish Rangankar memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT); 1818b3a271a9SManish Rangankar memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT); 1819b3a271a9SManish Rangankar mbox_cmd[0] = MBOX_CMD_GET_MANAGEMENT_DATA; 1820b3a271a9SManish Rangankar mbox_cmd[1] = fw_ddb_index; 1821b3a271a9SManish Rangankar mbox_cmd[2] = LSDW(stats_dma); 1822b3a271a9SManish Rangankar mbox_cmd[3] = MSDW(stats_dma); 1823b3a271a9SManish Rangankar mbox_cmd[4] = stats_size; 1824b3a271a9SManish Rangankar 1825b3a271a9SManish Rangankar status = qla4xxx_mailbox_command(ha, 5, 1, &mbox_cmd[0], &mbox_sts[0]); 1826b3a271a9SManish Rangankar if (status != QLA_SUCCESS) { 1827b3a271a9SManish Rangankar DEBUG2(ql4_printk(KERN_WARNING, ha, 1828b3a271a9SManish Rangankar "%s: MBOX_CMD_GET_MANAGEMENT_DATA " 1829b3a271a9SManish Rangankar "failed w/ status %04X\n", __func__, 1830b3a271a9SManish Rangankar mbox_sts[0])); 1831b3a271a9SManish Rangankar } 1832b3a271a9SManish Rangankar return status; 1833b3a271a9SManish Rangankar } 18348b0402e1SHarish Zunjarrao 18358b0402e1SHarish Zunjarrao int qla4xxx_get_ip_state(struct scsi_qla_host *ha, uint32_t acb_idx, 18368b0402e1SHarish Zunjarrao uint32_t ip_idx, uint32_t *sts) 18378b0402e1SHarish Zunjarrao { 18388b0402e1SHarish Zunjarrao uint32_t mbox_cmd[MBOX_REG_COUNT]; 18398b0402e1SHarish Zunjarrao uint32_t mbox_sts[MBOX_REG_COUNT]; 18408b0402e1SHarish Zunjarrao int status = QLA_SUCCESS; 18418b0402e1SHarish Zunjarrao 18428b0402e1SHarish Zunjarrao memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 18438b0402e1SHarish Zunjarrao memset(&mbox_sts, 0, sizeof(mbox_sts)); 18448b0402e1SHarish Zunjarrao mbox_cmd[0] = MBOX_CMD_GET_IP_ADDR_STATE; 18458b0402e1SHarish Zunjarrao mbox_cmd[1] = acb_idx; 18468b0402e1SHarish Zunjarrao mbox_cmd[2] = ip_idx; 18478b0402e1SHarish Zunjarrao 18488b0402e1SHarish Zunjarrao status = qla4xxx_mailbox_command(ha, 3, 8, &mbox_cmd[0], &mbox_sts[0]); 18498b0402e1SHarish Zunjarrao if (status != QLA_SUCCESS) { 18508b0402e1SHarish Zunjarrao DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: " 18518b0402e1SHarish Zunjarrao "MBOX_CMD_GET_IP_ADDR_STATE failed w/ " 18528b0402e1SHarish Zunjarrao "status %04X\n", __func__, mbox_sts[0])); 18538b0402e1SHarish Zunjarrao } 18548b0402e1SHarish Zunjarrao memcpy(sts, mbox_sts, sizeof(mbox_sts)); 18558b0402e1SHarish Zunjarrao return status; 18568b0402e1SHarish Zunjarrao } 18577c07d139SHarish Zunjarrao 18587c07d139SHarish Zunjarrao int qla4xxx_get_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma, 18597c07d139SHarish Zunjarrao uint32_t offset, uint32_t size) 18607c07d139SHarish Zunjarrao { 18617c07d139SHarish Zunjarrao int status = QLA_SUCCESS; 18627c07d139SHarish Zunjarrao uint32_t mbox_cmd[MBOX_REG_COUNT]; 18637c07d139SHarish Zunjarrao uint32_t mbox_sts[MBOX_REG_COUNT]; 18647c07d139SHarish Zunjarrao 18657c07d139SHarish Zunjarrao memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 18667c07d139SHarish Zunjarrao memset(&mbox_sts, 0, sizeof(mbox_sts)); 18677c07d139SHarish Zunjarrao 18687c07d139SHarish Zunjarrao mbox_cmd[0] = MBOX_CMD_GET_NVRAM; 18697c07d139SHarish Zunjarrao mbox_cmd[1] = LSDW(nvram_dma); 18707c07d139SHarish Zunjarrao mbox_cmd[2] = MSDW(nvram_dma); 18717c07d139SHarish Zunjarrao mbox_cmd[3] = offset; 18727c07d139SHarish Zunjarrao mbox_cmd[4] = size; 18737c07d139SHarish Zunjarrao 18747c07d139SHarish Zunjarrao status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], 18757c07d139SHarish Zunjarrao &mbox_sts[0]); 18767c07d139SHarish Zunjarrao if (status != QLA_SUCCESS) { 18777c07d139SHarish Zunjarrao DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed " 18787c07d139SHarish Zunjarrao "status %04X\n", ha->host_no, __func__, 18797c07d139SHarish Zunjarrao mbox_sts[0])); 18807c07d139SHarish Zunjarrao } 18817c07d139SHarish Zunjarrao return status; 18827c07d139SHarish Zunjarrao } 18837c07d139SHarish Zunjarrao 18847c07d139SHarish Zunjarrao int qla4xxx_set_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma, 18857c07d139SHarish Zunjarrao uint32_t offset, uint32_t size) 18867c07d139SHarish Zunjarrao { 18877c07d139SHarish Zunjarrao int status = QLA_SUCCESS; 18887c07d139SHarish Zunjarrao uint32_t mbox_cmd[MBOX_REG_COUNT]; 18897c07d139SHarish Zunjarrao uint32_t mbox_sts[MBOX_REG_COUNT]; 18907c07d139SHarish Zunjarrao 18917c07d139SHarish Zunjarrao memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 18927c07d139SHarish Zunjarrao memset(&mbox_sts, 0, sizeof(mbox_sts)); 18937c07d139SHarish Zunjarrao 18947c07d139SHarish Zunjarrao mbox_cmd[0] = MBOX_CMD_SET_NVRAM; 18957c07d139SHarish Zunjarrao mbox_cmd[1] = LSDW(nvram_dma); 18967c07d139SHarish Zunjarrao mbox_cmd[2] = MSDW(nvram_dma); 18977c07d139SHarish Zunjarrao mbox_cmd[3] = offset; 18987c07d139SHarish Zunjarrao mbox_cmd[4] = size; 18997c07d139SHarish Zunjarrao 19007c07d139SHarish Zunjarrao status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], 19017c07d139SHarish Zunjarrao &mbox_sts[0]); 19027c07d139SHarish Zunjarrao if (status != QLA_SUCCESS) { 19037c07d139SHarish Zunjarrao DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed " 19047c07d139SHarish Zunjarrao "status %04X\n", ha->host_no, __func__, 19057c07d139SHarish Zunjarrao mbox_sts[0])); 19067c07d139SHarish Zunjarrao } 19077c07d139SHarish Zunjarrao return status; 19087c07d139SHarish Zunjarrao } 19095232f801SHarish Zunjarrao 19105232f801SHarish Zunjarrao int qla4xxx_restore_factory_defaults(struct scsi_qla_host *ha, 19115232f801SHarish Zunjarrao uint32_t region, uint32_t field0, 19125232f801SHarish Zunjarrao uint32_t field1) 19135232f801SHarish Zunjarrao { 19145232f801SHarish Zunjarrao int status = QLA_SUCCESS; 19155232f801SHarish Zunjarrao uint32_t mbox_cmd[MBOX_REG_COUNT]; 19165232f801SHarish Zunjarrao uint32_t mbox_sts[MBOX_REG_COUNT]; 19175232f801SHarish Zunjarrao 19185232f801SHarish Zunjarrao memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 19195232f801SHarish Zunjarrao memset(&mbox_sts, 0, sizeof(mbox_sts)); 19205232f801SHarish Zunjarrao 19215232f801SHarish Zunjarrao mbox_cmd[0] = MBOX_CMD_RESTORE_FACTORY_DEFAULTS; 19225232f801SHarish Zunjarrao mbox_cmd[3] = region; 19235232f801SHarish Zunjarrao mbox_cmd[4] = field0; 19245232f801SHarish Zunjarrao mbox_cmd[5] = field1; 19255232f801SHarish Zunjarrao 19265232f801SHarish Zunjarrao status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0], 19275232f801SHarish Zunjarrao &mbox_sts[0]); 19285232f801SHarish Zunjarrao if (status != QLA_SUCCESS) { 19295232f801SHarish Zunjarrao DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed " 19305232f801SHarish Zunjarrao "status %04X\n", ha->host_no, __func__, 19315232f801SHarish Zunjarrao mbox_sts[0])); 19325232f801SHarish Zunjarrao } 19335232f801SHarish Zunjarrao return status; 19345232f801SHarish Zunjarrao } 1935*cfb27874SManish Dusane 1936*cfb27874SManish Dusane /** 1937*cfb27874SManish Dusane * qla4_8xxx_set_param - set driver version in firmware. 1938*cfb27874SManish Dusane * @ha: Pointer to host adapter structure. 1939*cfb27874SManish Dusane * @param: Parameter to set i.e driver version 1940*cfb27874SManish Dusane **/ 1941*cfb27874SManish Dusane int qla4_8xxx_set_param(struct scsi_qla_host *ha, int param) 1942*cfb27874SManish Dusane { 1943*cfb27874SManish Dusane uint32_t mbox_cmd[MBOX_REG_COUNT]; 1944*cfb27874SManish Dusane uint32_t mbox_sts[MBOX_REG_COUNT]; 1945*cfb27874SManish Dusane uint32_t status; 1946*cfb27874SManish Dusane 1947*cfb27874SManish Dusane memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 1948*cfb27874SManish Dusane memset(&mbox_sts, 0, sizeof(mbox_sts)); 1949*cfb27874SManish Dusane 1950*cfb27874SManish Dusane mbox_cmd[0] = MBOX_CMD_SET_PARAM; 1951*cfb27874SManish Dusane if (param == SET_DRVR_VERSION) { 1952*cfb27874SManish Dusane mbox_cmd[1] = SET_DRVR_VERSION; 1953*cfb27874SManish Dusane strncpy((char *)&mbox_cmd[2], QLA4XXX_DRIVER_VERSION, 1954*cfb27874SManish Dusane MAX_DRVR_VER_LEN); 1955*cfb27874SManish Dusane } else { 1956*cfb27874SManish Dusane ql4_printk(KERN_ERR, ha, "%s: invalid parameter 0x%x\n", 1957*cfb27874SManish Dusane __func__, param); 1958*cfb27874SManish Dusane status = QLA_ERROR; 1959*cfb27874SManish Dusane goto exit_set_param; 1960*cfb27874SManish Dusane } 1961*cfb27874SManish Dusane 1962*cfb27874SManish Dusane status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, mbox_cmd, 1963*cfb27874SManish Dusane mbox_sts); 1964*cfb27874SManish Dusane if (status == QLA_ERROR) 1965*cfb27874SManish Dusane ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n", 1966*cfb27874SManish Dusane __func__, mbox_sts[0]); 1967*cfb27874SManish Dusane 1968*cfb27874SManish Dusane exit_set_param: 1969*cfb27874SManish Dusane return status; 1970*cfb27874SManish Dusane } 1971