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