2459 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * QLogic iSCSI HBA Driver4 * Copyright (c) 2003-2013 QLogic Corporation5 */6 7#include <linux/ctype.h>8#include "ql4_def.h"9#include "ql4_glbl.h"10#include "ql4_dbg.h"11#include "ql4_inline.h"12#include "ql4_version.h"13 14void qla4xxx_queue_mbox_cmd(struct scsi_qla_host *ha, uint32_t *mbx_cmd,15 int in_count)16{17 int i;18 19 /* Load all mailbox registers, except mailbox 0. */20 for (i = 1; i < in_count; i++)21 writel(mbx_cmd[i], &ha->reg->mailbox[i]);22 23 /* Wakeup firmware */24 writel(mbx_cmd[0], &ha->reg->mailbox[0]);25 readl(&ha->reg->mailbox[0]);26 writel(set_rmask(CSR_INTR_RISC), &ha->reg->ctrl_status);27 readl(&ha->reg->ctrl_status);28}29 30void qla4xxx_process_mbox_intr(struct scsi_qla_host *ha, int out_count)31{32 int intr_status;33 34 intr_status = readl(&ha->reg->ctrl_status);35 if (intr_status & INTR_PENDING) {36 /*37 * Service the interrupt.38 * The ISR will save the mailbox status registers39 * to a temporary storage location in the adapter structure.40 */41 ha->mbox_status_count = out_count;42 ha->isp_ops->interrupt_service_routine(ha, intr_status);43 }44}45 46/**47 * qla4xxx_is_intr_poll_mode - Are we allowed to poll for interrupts?48 * @ha: Pointer to host adapter structure.49 * returns: 1=polling mode, 0=non-polling mode50 **/51static int qla4xxx_is_intr_poll_mode(struct scsi_qla_host *ha)52{53 int rval = 1;54 55 if (is_qla8032(ha) || is_qla8042(ha)) {56 if (test_bit(AF_IRQ_ATTACHED, &ha->flags) &&57 test_bit(AF_83XX_MBOX_INTR_ON, &ha->flags))58 rval = 0;59 } else {60 if (test_bit(AF_IRQ_ATTACHED, &ha->flags) &&61 test_bit(AF_INTERRUPTS_ON, &ha->flags) &&62 test_bit(AF_ONLINE, &ha->flags) &&63 !test_bit(AF_HA_REMOVAL, &ha->flags))64 rval = 0;65 }66 67 return rval;68}69 70/**71 * qla4xxx_mailbox_command - issues mailbox commands72 * @ha: Pointer to host adapter structure.73 * @inCount: number of mailbox registers to load.74 * @outCount: number of mailbox registers to return.75 * @mbx_cmd: data pointer for mailbox in registers.76 * @mbx_sts: data pointer for mailbox out registers.77 *78 * This routine issue mailbox commands and waits for completion.79 * If outCount is 0, this routine completes successfully WITHOUT waiting80 * for the mailbox command to complete.81 **/82int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,83 uint8_t outCount, uint32_t *mbx_cmd,84 uint32_t *mbx_sts)85{86 int status = QLA_ERROR;87 uint8_t i;88 u_long wait_count;89 unsigned long flags = 0;90 uint32_t dev_state;91 92 /* Make sure that pointers are valid */93 if (!mbx_cmd || !mbx_sts) {94 DEBUG2(printk("scsi%ld: %s: Invalid mbx_cmd or mbx_sts "95 "pointer\n", ha->host_no, __func__));96 return status;97 }98 99 if (is_qla40XX(ha)) {100 if (test_bit(AF_HA_REMOVAL, &ha->flags)) {101 DEBUG2(ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: "102 "prematurely completing mbx cmd as "103 "adapter removal detected\n",104 ha->host_no, __func__));105 return status;106 }107 }108 109 if ((is_aer_supported(ha)) &&110 (test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags))) {111 DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Perm failure on EEH, "112 "timeout MBX Exiting.\n", ha->host_no, __func__));113 return status;114 }115 116 /* Mailbox code active */117 wait_count = MBOX_TOV * 100;118 119 while (wait_count--) {120 mutex_lock(&ha->mbox_sem);121 if (!test_bit(AF_MBOX_COMMAND, &ha->flags)) {122 set_bit(AF_MBOX_COMMAND, &ha->flags);123 mutex_unlock(&ha->mbox_sem);124 break;125 }126 mutex_unlock(&ha->mbox_sem);127 if (!wait_count) {128 DEBUG2(printk("scsi%ld: %s: mbox_sem failed\n",129 ha->host_no, __func__));130 return status;131 }132 msleep(10);133 }134 135 if (is_qla80XX(ha)) {136 if (test_bit(AF_FW_RECOVERY, &ha->flags)) {137 DEBUG2(ql4_printk(KERN_WARNING, ha,138 "scsi%ld: %s: prematurely completing mbx cmd as firmware recovery detected\n",139 ha->host_no, __func__));140 goto mbox_exit;141 }142 /* Do not send any mbx cmd if h/w is in failed state*/143 ha->isp_ops->idc_lock(ha);144 dev_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DEV_STATE);145 ha->isp_ops->idc_unlock(ha);146 if (dev_state == QLA8XXX_DEV_FAILED) {147 ql4_printk(KERN_WARNING, ha,148 "scsi%ld: %s: H/W is in failed state, do not send any mailbox commands\n",149 ha->host_no, __func__);150 goto mbox_exit;151 }152 }153 154 spin_lock_irqsave(&ha->hardware_lock, flags);155 156 ha->mbox_status_count = outCount;157 for (i = 0; i < outCount; i++)158 ha->mbox_status[i] = 0;159 160 /* Queue the mailbox command to the firmware */161 ha->isp_ops->queue_mailbox_command(ha, mbx_cmd, inCount);162 163 spin_unlock_irqrestore(&ha->hardware_lock, flags);164 165 /* Wait for completion */166 167 /*168 * If we don't want status, don't wait for the mailbox command to169 * complete. For example, MBOX_CMD_RESET_FW doesn't return status,170 * you must poll the inbound Interrupt Mask for completion.171 */172 if (outCount == 0) {173 status = QLA_SUCCESS;174 goto mbox_exit;175 }176 177 /*178 * Wait for completion: Poll or completion queue179 */180 if (qla4xxx_is_intr_poll_mode(ha)) {181 /* Poll for command to complete */182 wait_count = jiffies + MBOX_TOV * HZ;183 while (test_bit(AF_MBOX_COMMAND_DONE, &ha->flags) == 0) {184 if (time_after_eq(jiffies, wait_count))185 break;186 /*187 * Service the interrupt.188 * The ISR will save the mailbox status registers189 * to a temporary storage location in the adapter190 * structure.191 */192 spin_lock_irqsave(&ha->hardware_lock, flags);193 ha->isp_ops->process_mailbox_interrupt(ha, outCount);194 spin_unlock_irqrestore(&ha->hardware_lock, flags);195 msleep(10);196 }197 } else {198 /* Do not poll for completion. Use completion queue */199 set_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags);200 wait_for_completion_timeout(&ha->mbx_intr_comp, MBOX_TOV * HZ);201 clear_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags);202 }203 204 /* Check for mailbox timeout. */205 if (!test_bit(AF_MBOX_COMMAND_DONE, &ha->flags)) {206 if (is_qla80XX(ha) &&207 test_bit(AF_FW_RECOVERY, &ha->flags)) {208 DEBUG2(ql4_printk(KERN_INFO, ha,209 "scsi%ld: %s: prematurely completing mbx cmd as "210 "firmware recovery detected\n",211 ha->host_no, __func__));212 goto mbox_exit;213 }214 ql4_printk(KERN_WARNING, ha, "scsi%ld: Mailbox Cmd 0x%08X timed out, Scheduling Adapter Reset\n",215 ha->host_no, mbx_cmd[0]);216 ha->mailbox_timeout_count++;217 mbx_sts[0] = (-1);218 set_bit(DPC_RESET_HA, &ha->dpc_flags);219 if (is_qla8022(ha)) {220 ql4_printk(KERN_INFO, ha,221 "disabling pause transmit on port 0 & 1.\n");222 qla4_82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x98,223 CRB_NIU_XG_PAUSE_CTL_P0 |224 CRB_NIU_XG_PAUSE_CTL_P1);225 } else if (is_qla8032(ha) || is_qla8042(ha)) {226 ql4_printk(KERN_INFO, ha, " %s: disabling pause transmit on port 0 & 1.\n",227 __func__);228 qla4_83xx_disable_pause(ha);229 }230 goto mbox_exit;231 }232 233 /*234 * Copy the mailbox out registers to the caller's mailbox in/out235 * structure.236 */237 spin_lock_irqsave(&ha->hardware_lock, flags);238 for (i = 0; i < outCount; i++)239 mbx_sts[i] = ha->mbox_status[i];240 241 /* Set return status and error flags (if applicable). */242 switch (ha->mbox_status[0]) {243 case MBOX_STS_COMMAND_COMPLETE:244 status = QLA_SUCCESS;245 break;246 247 case MBOX_STS_INTERMEDIATE_COMPLETION:248 status = QLA_SUCCESS;249 break;250 251 case MBOX_STS_BUSY:252 ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: Cmd = %08X, ISP BUSY\n",253 ha->host_no, __func__, mbx_cmd[0]);254 ha->mailbox_timeout_count++;255 break;256 257 default:258 ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: FAILED, MBOX CMD = %08X, MBOX STS = %08X %08X %08X %08X %08X %08X %08X %08X\n",259 ha->host_no, __func__, mbx_cmd[0], mbx_sts[0],260 mbx_sts[1], mbx_sts[2], mbx_sts[3], mbx_sts[4],261 mbx_sts[5], mbx_sts[6], mbx_sts[7]);262 break;263 }264 spin_unlock_irqrestore(&ha->hardware_lock, flags);265 266mbox_exit:267 mutex_lock(&ha->mbox_sem);268 clear_bit(AF_MBOX_COMMAND, &ha->flags);269 mutex_unlock(&ha->mbox_sem);270 clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags);271 272 return status;273}274 275/**276 * qla4xxx_get_minidump_template - Get the firmware template277 * @ha: Pointer to host adapter structure.278 * @phys_addr: dma address for template279 *280 * Obtain the minidump template from firmware during initialization281 * as it may not be available when minidump is desired.282 **/283int qla4xxx_get_minidump_template(struct scsi_qla_host *ha,284 dma_addr_t phys_addr)285{286 uint32_t mbox_cmd[MBOX_REG_COUNT];287 uint32_t mbox_sts[MBOX_REG_COUNT];288 int status;289 290 memset(&mbox_cmd, 0, sizeof(mbox_cmd));291 memset(&mbox_sts, 0, sizeof(mbox_sts));292 293 mbox_cmd[0] = MBOX_CMD_MINIDUMP;294 mbox_cmd[1] = MINIDUMP_GET_TMPLT_SUBCOMMAND;295 mbox_cmd[2] = LSDW(phys_addr);296 mbox_cmd[3] = MSDW(phys_addr);297 mbox_cmd[4] = ha->fw_dump_tmplt_size;298 mbox_cmd[5] = 0;299 300 status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0],301 &mbox_sts[0]);302 if (status != QLA_SUCCESS) {303 DEBUG2(ql4_printk(KERN_INFO, ha,304 "scsi%ld: %s: Cmd = %08X, mbx[0] = 0x%04x, mbx[1] = 0x%04x\n",305 ha->host_no, __func__, mbox_cmd[0],306 mbox_sts[0], mbox_sts[1]));307 }308 return status;309}310 311/**312 * qla4xxx_req_template_size - Get minidump template size from firmware.313 * @ha: Pointer to host adapter structure.314 **/315int qla4xxx_req_template_size(struct scsi_qla_host *ha)316{317 uint32_t mbox_cmd[MBOX_REG_COUNT];318 uint32_t mbox_sts[MBOX_REG_COUNT];319 int status;320 321 memset(&mbox_cmd, 0, sizeof(mbox_cmd));322 memset(&mbox_sts, 0, sizeof(mbox_sts));323 324 mbox_cmd[0] = MBOX_CMD_MINIDUMP;325 mbox_cmd[1] = MINIDUMP_GET_SIZE_SUBCOMMAND;326 327 status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 8, &mbox_cmd[0],328 &mbox_sts[0]);329 if (status == QLA_SUCCESS) {330 ha->fw_dump_tmplt_size = mbox_sts[1];331 DEBUG2(ql4_printk(KERN_INFO, ha,332 "%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",333 __func__, mbox_sts[0], mbox_sts[1],334 mbox_sts[2], mbox_sts[3], mbox_sts[4],335 mbox_sts[5], mbox_sts[6], mbox_sts[7]));336 if (ha->fw_dump_tmplt_size == 0)337 status = QLA_ERROR;338 } else {339 ql4_printk(KERN_WARNING, ha,340 "%s: Error sts[0]=0x%04x, mbx[1]=0x%04x\n",341 __func__, mbox_sts[0], mbox_sts[1]);342 status = QLA_ERROR;343 }344 345 return status;346}347 348void qla4xxx_mailbox_premature_completion(struct scsi_qla_host *ha)349{350 set_bit(AF_FW_RECOVERY, &ha->flags);351 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: set FW RECOVERY!\n",352 ha->host_no, __func__);353 354 if (test_bit(AF_MBOX_COMMAND, &ha->flags)) {355 if (test_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags)) {356 complete(&ha->mbx_intr_comp);357 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Due to fw "358 "recovery, doing premature completion of "359 "mbx cmd\n", ha->host_no, __func__);360 361 } else {362 set_bit(AF_MBOX_COMMAND_DONE, &ha->flags);363 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Due to fw "364 "recovery, doing premature completion of "365 "polling mbx cmd\n", ha->host_no, __func__);366 }367 }368}369 370static uint8_t371qla4xxx_set_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,372 uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma)373{374 memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT);375 memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT);376 377 if (is_qla8022(ha))378 qla4_82xx_wr_32(ha, ha->nx_db_wr_ptr, 0);379 380 mbox_cmd[0] = MBOX_CMD_INITIALIZE_FIRMWARE;381 mbox_cmd[1] = 0;382 mbox_cmd[2] = LSDW(init_fw_cb_dma);383 mbox_cmd[3] = MSDW(init_fw_cb_dma);384 mbox_cmd[4] = sizeof(struct addr_ctrl_blk);385 386 if (qla4xxx_mailbox_command(ha, 6, 6, mbox_cmd, mbox_sts) !=387 QLA_SUCCESS) {388 DEBUG2(printk(KERN_WARNING "scsi%ld: %s: "389 "MBOX_CMD_INITIALIZE_FIRMWARE"390 " failed w/ status %04X\n",391 ha->host_no, __func__, mbox_sts[0]));392 return QLA_ERROR;393 }394 return QLA_SUCCESS;395}396 397uint8_t398qla4xxx_get_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,399 uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma)400{401 memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT);402 memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT);403 mbox_cmd[0] = MBOX_CMD_GET_INIT_FW_CTRL_BLOCK;404 mbox_cmd[2] = LSDW(init_fw_cb_dma);405 mbox_cmd[3] = MSDW(init_fw_cb_dma);406 mbox_cmd[4] = sizeof(struct addr_ctrl_blk);407 408 if (qla4xxx_mailbox_command(ha, 5, 5, mbox_cmd, mbox_sts) !=409 QLA_SUCCESS) {410 DEBUG2(printk(KERN_WARNING "scsi%ld: %s: "411 "MBOX_CMD_GET_INIT_FW_CTRL_BLOCK"412 " failed w/ status %04X\n",413 ha->host_no, __func__, mbox_sts[0]));414 return QLA_ERROR;415 }416 return QLA_SUCCESS;417}418 419uint8_t qla4xxx_set_ipaddr_state(uint8_t fw_ipaddr_state)420{421 uint8_t ipaddr_state;422 423 switch (fw_ipaddr_state) {424 case IP_ADDRSTATE_UNCONFIGURED:425 ipaddr_state = ISCSI_IPDDRESS_STATE_UNCONFIGURED;426 break;427 case IP_ADDRSTATE_INVALID:428 ipaddr_state = ISCSI_IPDDRESS_STATE_INVALID;429 break;430 case IP_ADDRSTATE_ACQUIRING:431 ipaddr_state = ISCSI_IPDDRESS_STATE_ACQUIRING;432 break;433 case IP_ADDRSTATE_TENTATIVE:434 ipaddr_state = ISCSI_IPDDRESS_STATE_TENTATIVE;435 break;436 case IP_ADDRSTATE_DEPRICATED:437 ipaddr_state = ISCSI_IPDDRESS_STATE_DEPRECATED;438 break;439 case IP_ADDRSTATE_PREFERRED:440 ipaddr_state = ISCSI_IPDDRESS_STATE_VALID;441 break;442 case IP_ADDRSTATE_DISABLING:443 ipaddr_state = ISCSI_IPDDRESS_STATE_DISABLING;444 break;445 default:446 ipaddr_state = ISCSI_IPDDRESS_STATE_UNCONFIGURED;447 }448 return ipaddr_state;449}450 451static void452qla4xxx_update_local_ip(struct scsi_qla_host *ha,453 struct addr_ctrl_blk *init_fw_cb)454{455 ha->ip_config.tcp_options = le16_to_cpu(init_fw_cb->ipv4_tcp_opts);456 ha->ip_config.ipv4_options = le16_to_cpu(init_fw_cb->ipv4_ip_opts);457 ha->ip_config.ipv4_addr_state =458 qla4xxx_set_ipaddr_state(init_fw_cb->ipv4_addr_state);459 ha->ip_config.eth_mtu_size =460 le16_to_cpu(init_fw_cb->eth_mtu_size);461 ha->ip_config.ipv4_port = le16_to_cpu(init_fw_cb->ipv4_port);462 463 if (ha->acb_version == ACB_SUPPORTED) {464 ha->ip_config.ipv6_options = le16_to_cpu(init_fw_cb->ipv6_opts);465 ha->ip_config.ipv6_addl_options =466 le16_to_cpu(init_fw_cb->ipv6_addtl_opts);467 ha->ip_config.ipv6_tcp_options =468 le16_to_cpu(init_fw_cb->ipv6_tcp_opts);469 }470 471 /* Save IPv4 Address Info */472 memcpy(ha->ip_config.ip_address, init_fw_cb->ipv4_addr,473 min(sizeof(ha->ip_config.ip_address),474 sizeof(init_fw_cb->ipv4_addr)));475 memcpy(ha->ip_config.subnet_mask, init_fw_cb->ipv4_subnet,476 min(sizeof(ha->ip_config.subnet_mask),477 sizeof(init_fw_cb->ipv4_subnet)));478 memcpy(ha->ip_config.gateway, init_fw_cb->ipv4_gw_addr,479 min(sizeof(ha->ip_config.gateway),480 sizeof(init_fw_cb->ipv4_gw_addr)));481 482 ha->ip_config.ipv4_vlan_tag = be16_to_cpu(init_fw_cb->ipv4_vlan_tag);483 ha->ip_config.control = init_fw_cb->control;484 ha->ip_config.tcp_wsf = init_fw_cb->ipv4_tcp_wsf;485 ha->ip_config.ipv4_tos = init_fw_cb->ipv4_tos;486 ha->ip_config.ipv4_cache_id = init_fw_cb->ipv4_cacheid;487 ha->ip_config.ipv4_alt_cid_len = init_fw_cb->ipv4_dhcp_alt_cid_len;488 memcpy(ha->ip_config.ipv4_alt_cid, init_fw_cb->ipv4_dhcp_alt_cid,489 min(sizeof(ha->ip_config.ipv4_alt_cid),490 sizeof(init_fw_cb->ipv4_dhcp_alt_cid)));491 ha->ip_config.ipv4_vid_len = init_fw_cb->ipv4_dhcp_vid_len;492 memcpy(ha->ip_config.ipv4_vid, init_fw_cb->ipv4_dhcp_vid,493 min(sizeof(ha->ip_config.ipv4_vid),494 sizeof(init_fw_cb->ipv4_dhcp_vid)));495 ha->ip_config.ipv4_ttl = init_fw_cb->ipv4_ttl;496 ha->ip_config.def_timeout = le16_to_cpu(init_fw_cb->def_timeout);497 ha->ip_config.abort_timer = init_fw_cb->abort_timer;498 ha->ip_config.iscsi_options = le16_to_cpu(init_fw_cb->iscsi_opts);499 ha->ip_config.iscsi_max_pdu_size =500 le16_to_cpu(init_fw_cb->iscsi_max_pdu_size);501 ha->ip_config.iscsi_first_burst_len =502 le16_to_cpu(init_fw_cb->iscsi_fburst_len);503 ha->ip_config.iscsi_max_outstnd_r2t =504 le16_to_cpu(init_fw_cb->iscsi_max_outstnd_r2t);505 ha->ip_config.iscsi_max_burst_len =506 le16_to_cpu(init_fw_cb->iscsi_max_burst_len);507 memcpy(ha->ip_config.iscsi_name, init_fw_cb->iscsi_name,508 min(sizeof(ha->ip_config.iscsi_name),509 sizeof(init_fw_cb->iscsi_name)));510 511 if (is_ipv6_enabled(ha)) {512 /* Save IPv6 Address */513 ha->ip_config.ipv6_link_local_state =514 qla4xxx_set_ipaddr_state(init_fw_cb->ipv6_lnk_lcl_addr_state);515 ha->ip_config.ipv6_addr0_state =516 qla4xxx_set_ipaddr_state(init_fw_cb->ipv6_addr0_state);517 ha->ip_config.ipv6_addr1_state =518 qla4xxx_set_ipaddr_state(init_fw_cb->ipv6_addr1_state);519 520 switch (le16_to_cpu(init_fw_cb->ipv6_dflt_rtr_state)) {521 case IPV6_RTRSTATE_UNKNOWN:522 ha->ip_config.ipv6_default_router_state =523 ISCSI_ROUTER_STATE_UNKNOWN;524 break;525 case IPV6_RTRSTATE_MANUAL:526 ha->ip_config.ipv6_default_router_state =527 ISCSI_ROUTER_STATE_MANUAL;528 break;529 case IPV6_RTRSTATE_ADVERTISED:530 ha->ip_config.ipv6_default_router_state =531 ISCSI_ROUTER_STATE_ADVERTISED;532 break;533 case IPV6_RTRSTATE_STALE:534 ha->ip_config.ipv6_default_router_state =535 ISCSI_ROUTER_STATE_STALE;536 break;537 default:538 ha->ip_config.ipv6_default_router_state =539 ISCSI_ROUTER_STATE_UNKNOWN;540 }541 542 ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[0] = 0xFE;543 ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[1] = 0x80;544 545 memcpy(&ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[8],546 init_fw_cb->ipv6_if_id,547 min(sizeof(ha->ip_config.ipv6_link_local_addr)/2,548 sizeof(init_fw_cb->ipv6_if_id)));549 memcpy(&ha->ip_config.ipv6_addr0, init_fw_cb->ipv6_addr0,550 min(sizeof(ha->ip_config.ipv6_addr0),551 sizeof(init_fw_cb->ipv6_addr0)));552 memcpy(&ha->ip_config.ipv6_addr1, init_fw_cb->ipv6_addr1,553 min(sizeof(ha->ip_config.ipv6_addr1),554 sizeof(init_fw_cb->ipv6_addr1)));555 memcpy(&ha->ip_config.ipv6_default_router_addr,556 init_fw_cb->ipv6_dflt_rtr_addr,557 min(sizeof(ha->ip_config.ipv6_default_router_addr),558 sizeof(init_fw_cb->ipv6_dflt_rtr_addr)));559 ha->ip_config.ipv6_vlan_tag =560 be16_to_cpu(init_fw_cb->ipv6_vlan_tag);561 ha->ip_config.ipv6_port = le16_to_cpu(init_fw_cb->ipv6_port);562 ha->ip_config.ipv6_cache_id = init_fw_cb->ipv6_cache_id;563 ha->ip_config.ipv6_flow_lbl =564 le16_to_cpu(init_fw_cb->ipv6_flow_lbl);565 ha->ip_config.ipv6_traffic_class =566 init_fw_cb->ipv6_traffic_class;567 ha->ip_config.ipv6_hop_limit = init_fw_cb->ipv6_hop_limit;568 ha->ip_config.ipv6_nd_reach_time =569 le32_to_cpu(init_fw_cb->ipv6_nd_reach_time);570 ha->ip_config.ipv6_nd_rexmit_timer =571 le32_to_cpu(init_fw_cb->ipv6_nd_rexmit_timer);572 ha->ip_config.ipv6_nd_stale_timeout =573 le32_to_cpu(init_fw_cb->ipv6_nd_stale_timeout);574 ha->ip_config.ipv6_dup_addr_detect_count =575 init_fw_cb->ipv6_dup_addr_detect_count;576 ha->ip_config.ipv6_gw_advrt_mtu =577 le32_to_cpu(init_fw_cb->ipv6_gw_advrt_mtu);578 ha->ip_config.ipv6_tcp_wsf = init_fw_cb->ipv6_tcp_wsf;579 }580}581 582uint8_t583qla4xxx_update_local_ifcb(struct scsi_qla_host *ha,584 uint32_t *mbox_cmd,585 uint32_t *mbox_sts,586 struct addr_ctrl_blk *init_fw_cb,587 dma_addr_t init_fw_cb_dma)588{589 if (qla4xxx_get_ifcb(ha, mbox_cmd, mbox_sts, init_fw_cb_dma)590 != QLA_SUCCESS) {591 DEBUG2(printk(KERN_WARNING592 "scsi%ld: %s: Failed to get init_fw_ctrl_blk\n",593 ha->host_no, __func__));594 return QLA_ERROR;595 }596 597 DEBUG2(qla4xxx_dump_buffer(init_fw_cb, sizeof(struct addr_ctrl_blk)));598 599 /* Save some info in adapter structure. */600 ha->acb_version = init_fw_cb->acb_version;601 ha->firmware_options = le16_to_cpu(init_fw_cb->fw_options);602 ha->heartbeat_interval = init_fw_cb->hb_interval;603 memcpy(ha->name_string, init_fw_cb->iscsi_name,604 min(sizeof(ha->name_string),605 sizeof(init_fw_cb->iscsi_name)));606 ha->def_timeout = le16_to_cpu(init_fw_cb->def_timeout);607 /*memcpy(ha->alias, init_fw_cb->Alias,608 min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));*/609 610 qla4xxx_update_local_ip(ha, init_fw_cb);611 612 return QLA_SUCCESS;613}614 615/**616 * qla4xxx_initialize_fw_cb - initializes firmware control block.617 * @ha: Pointer to host adapter structure.618 **/619int qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha)620{621 struct addr_ctrl_blk *init_fw_cb;622 dma_addr_t init_fw_cb_dma;623 uint32_t mbox_cmd[MBOX_REG_COUNT];624 uint32_t mbox_sts[MBOX_REG_COUNT];625 int status = QLA_ERROR;626 627 init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,628 sizeof(struct addr_ctrl_blk),629 &init_fw_cb_dma, GFP_KERNEL);630 if (init_fw_cb == NULL) {631 DEBUG2(printk("scsi%ld: %s: Unable to alloc init_cb\n",632 ha->host_no, __func__));633 goto exit_init_fw_cb_no_free;634 }635 636 /* Get Initialize Firmware Control Block. */637 memset(&mbox_cmd, 0, sizeof(mbox_cmd));638 memset(&mbox_sts, 0, sizeof(mbox_sts));639 640 if (qla4xxx_get_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma) !=641 QLA_SUCCESS) {642 goto exit_init_fw_cb;643 }644 645 /* Fill in the request and response queue information. */646 init_fw_cb->rqq_consumer_idx = cpu_to_le16(ha->request_out);647 init_fw_cb->compq_producer_idx = cpu_to_le16(ha->response_in);648 init_fw_cb->rqq_len = cpu_to_le16(REQUEST_QUEUE_DEPTH);649 init_fw_cb->compq_len = cpu_to_le16(RESPONSE_QUEUE_DEPTH);650 init_fw_cb->rqq_addr_lo = cpu_to_le32(LSDW(ha->request_dma));651 init_fw_cb->rqq_addr_hi = cpu_to_le32(MSDW(ha->request_dma));652 init_fw_cb->compq_addr_lo = cpu_to_le32(LSDW(ha->response_dma));653 init_fw_cb->compq_addr_hi = cpu_to_le32(MSDW(ha->response_dma));654 init_fw_cb->shdwreg_addr_lo = cpu_to_le32(LSDW(ha->shadow_regs_dma));655 init_fw_cb->shdwreg_addr_hi = cpu_to_le32(MSDW(ha->shadow_regs_dma));656 657 /* Set up required options. */658 init_fw_cb->fw_options |=659 cpu_to_le16(FWOPT_SESSION_MODE |660 FWOPT_INITIATOR_MODE);661 662 if (is_qla80XX(ha))663 init_fw_cb->fw_options |=664 cpu_to_le16(FWOPT_ENABLE_CRBDB);665 666 init_fw_cb->fw_options &= cpu_to_le16(~FWOPT_TARGET_MODE);667 668 init_fw_cb->add_fw_options = 0;669 init_fw_cb->add_fw_options |=670 cpu_to_le16(ADFWOPT_SERIALIZE_TASK_MGMT);671 init_fw_cb->add_fw_options |=672 cpu_to_le16(ADFWOPT_AUTOCONN_DISABLE);673 674 if (qla4xxx_set_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma)675 != QLA_SUCCESS) {676 DEBUG2(printk(KERN_WARNING677 "scsi%ld: %s: Failed to set init_fw_ctrl_blk\n",678 ha->host_no, __func__));679 goto exit_init_fw_cb;680 }681 682 if (qla4xxx_update_local_ifcb(ha, &mbox_cmd[0], &mbox_sts[0],683 init_fw_cb, init_fw_cb_dma) != QLA_SUCCESS) {684 DEBUG2(printk("scsi%ld: %s: Failed to update local ifcb\n",685 ha->host_no, __func__));686 goto exit_init_fw_cb;687 }688 status = QLA_SUCCESS;689 690exit_init_fw_cb:691 dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk),692 init_fw_cb, init_fw_cb_dma);693exit_init_fw_cb_no_free:694 return status;695}696 697/**698 * qla4xxx_get_dhcp_ip_address - gets HBA ip address via DHCP699 * @ha: Pointer to host adapter structure.700 **/701int qla4xxx_get_dhcp_ip_address(struct scsi_qla_host * ha)702{703 struct addr_ctrl_blk *init_fw_cb;704 dma_addr_t init_fw_cb_dma;705 uint32_t mbox_cmd[MBOX_REG_COUNT];706 uint32_t mbox_sts[MBOX_REG_COUNT];707 708 init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,709 sizeof(struct addr_ctrl_blk),710 &init_fw_cb_dma, GFP_KERNEL);711 if (init_fw_cb == NULL) {712 printk("scsi%ld: %s: Unable to alloc init_cb\n", ha->host_no,713 __func__);714 return QLA_ERROR;715 }716 717 /* Get Initialize Firmware Control Block. */718 if (qla4xxx_get_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma) !=719 QLA_SUCCESS) {720 DEBUG2(printk("scsi%ld: %s: Failed to get init_fw_ctrl_blk\n",721 ha->host_no, __func__));722 dma_free_coherent(&ha->pdev->dev,723 sizeof(struct addr_ctrl_blk),724 init_fw_cb, init_fw_cb_dma);725 return QLA_ERROR;726 }727 728 /* Save IP Address. */729 qla4xxx_update_local_ip(ha, init_fw_cb);730 dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk),731 init_fw_cb, init_fw_cb_dma);732 733 return QLA_SUCCESS;734}735 736/**737 * qla4xxx_get_firmware_state - gets firmware state of HBA738 * @ha: Pointer to host adapter structure.739 **/740int qla4xxx_get_firmware_state(struct scsi_qla_host * ha)741{742 uint32_t mbox_cmd[MBOX_REG_COUNT];743 uint32_t mbox_sts[MBOX_REG_COUNT];744 745 /* Get firmware version */746 memset(&mbox_cmd, 0, sizeof(mbox_cmd));747 memset(&mbox_sts, 0, sizeof(mbox_sts));748 749 mbox_cmd[0] = MBOX_CMD_GET_FW_STATE;750 751 if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 4, &mbox_cmd[0], &mbox_sts[0]) !=752 QLA_SUCCESS) {753 DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATE failed w/ "754 "status %04X\n", ha->host_no, __func__,755 mbox_sts[0]));756 return QLA_ERROR;757 }758 ha->firmware_state = mbox_sts[1];759 ha->board_id = mbox_sts[2];760 ha->addl_fw_state = mbox_sts[3];761 DEBUG2(printk("scsi%ld: %s firmware_state=0x%x\n",762 ha->host_no, __func__, ha->firmware_state);)763 764 return QLA_SUCCESS;765}766 767/**768 * qla4xxx_get_firmware_status - retrieves firmware status769 * @ha: Pointer to host adapter structure.770 **/771int qla4xxx_get_firmware_status(struct scsi_qla_host * ha)772{773 uint32_t mbox_cmd[MBOX_REG_COUNT];774 uint32_t mbox_sts[MBOX_REG_COUNT];775 776 /* Get firmware version */777 memset(&mbox_cmd, 0, sizeof(mbox_cmd));778 memset(&mbox_sts, 0, sizeof(mbox_sts));779 780 mbox_cmd[0] = MBOX_CMD_GET_FW_STATUS;781 782 if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0], &mbox_sts[0]) !=783 QLA_SUCCESS) {784 DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATUS failed w/ "785 "status %04X\n", ha->host_no, __func__,786 mbox_sts[0]));787 return QLA_ERROR;788 }789 790 /* High-water mark of IOCBs */791 ha->iocb_hiwat = mbox_sts[2];792 DEBUG2(ql4_printk(KERN_INFO, ha,793 "%s: firmware IOCBs available = %d\n", __func__,794 ha->iocb_hiwat));795 796 if (ha->iocb_hiwat > IOCB_HIWAT_CUSHION)797 ha->iocb_hiwat -= IOCB_HIWAT_CUSHION;798 799 /* Ideally, we should not enter this code, as the # of firmware800 * IOCBs is hard-coded in the firmware. We set a default801 * iocb_hiwat here just in case */802 if (ha->iocb_hiwat == 0) {803 ha->iocb_hiwat = REQUEST_QUEUE_DEPTH / 4;804 DEBUG2(ql4_printk(KERN_WARNING, ha,805 "%s: Setting IOCB's to = %d\n", __func__,806 ha->iocb_hiwat));807 }808 809 return QLA_SUCCESS;810}811 812/*813 * qla4xxx_get_fwddb_entry - retrieves firmware ddb entry814 * @ha: Pointer to host adapter structure.815 * @fw_ddb_index: Firmware's device database index816 * @fw_ddb_entry: Pointer to firmware's device database entry structure817 * @num_valid_ddb_entries: Pointer to number of valid ddb entries818 * @next_ddb_index: Pointer to next valid device database index819 * @fw_ddb_device_state: Pointer to device state820 **/821int qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha,822 uint16_t fw_ddb_index,823 struct dev_db_entry *fw_ddb_entry,824 dma_addr_t fw_ddb_entry_dma,825 uint32_t *num_valid_ddb_entries,826 uint32_t *next_ddb_index,827 uint32_t *fw_ddb_device_state,828 uint32_t *conn_err_detail,829 uint16_t *tcp_source_port_num,830 uint16_t *connection_id)831{832 int status = QLA_ERROR;833 uint16_t options;834 uint32_t mbox_cmd[MBOX_REG_COUNT];835 uint32_t mbox_sts[MBOX_REG_COUNT];836 837 /* Make sure the device index is valid */838 if (fw_ddb_index >= MAX_DDB_ENTRIES) {839 DEBUG2(printk("scsi%ld: %s: ddb [%d] out of range.\n",840 ha->host_no, __func__, fw_ddb_index));841 goto exit_get_fwddb;842 }843 memset(&mbox_cmd, 0, sizeof(mbox_cmd));844 memset(&mbox_sts, 0, sizeof(mbox_sts));845 if (fw_ddb_entry)846 memset(fw_ddb_entry, 0, sizeof(struct dev_db_entry));847 848 mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY;849 mbox_cmd[1] = (uint32_t) fw_ddb_index;850 mbox_cmd[2] = LSDW(fw_ddb_entry_dma);851 mbox_cmd[3] = MSDW(fw_ddb_entry_dma);852 mbox_cmd[4] = sizeof(struct dev_db_entry);853 854 if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 7, &mbox_cmd[0], &mbox_sts[0]) ==855 QLA_ERROR) {856 DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_DATABASE_ENTRY failed"857 " with status 0x%04X\n", ha->host_no, __func__,858 mbox_sts[0]));859 goto exit_get_fwddb;860 }861 if (fw_ddb_index != mbox_sts[1]) {862 DEBUG2(printk("scsi%ld: %s: ddb mismatch [%d] != [%d].\n",863 ha->host_no, __func__, fw_ddb_index,864 mbox_sts[1]));865 goto exit_get_fwddb;866 }867 if (fw_ddb_entry) {868 options = le16_to_cpu(fw_ddb_entry->options);869 if (options & DDB_OPT_IPV6_DEVICE) {870 ql4_printk(KERN_INFO, ha, "%s: DDB[%d] MB0 %04x Tot %d "871 "Next %d State %04x ConnErr %08x %pI6 "872 ":%04d \"%s\"\n", __func__, fw_ddb_index,873 mbox_sts[0], mbox_sts[2], mbox_sts[3],874 mbox_sts[4], mbox_sts[5],875 fw_ddb_entry->ip_addr,876 le16_to_cpu(fw_ddb_entry->port),877 fw_ddb_entry->iscsi_name);878 } else {879 ql4_printk(KERN_INFO, ha, "%s: DDB[%d] MB0 %04x Tot %d "880 "Next %d State %04x ConnErr %08x %pI4 "881 ":%04d \"%s\"\n", __func__, fw_ddb_index,882 mbox_sts[0], mbox_sts[2], mbox_sts[3],883 mbox_sts[4], mbox_sts[5],884 fw_ddb_entry->ip_addr,885 le16_to_cpu(fw_ddb_entry->port),886 fw_ddb_entry->iscsi_name);887 }888 }889 if (num_valid_ddb_entries)890 *num_valid_ddb_entries = mbox_sts[2];891 if (next_ddb_index)892 *next_ddb_index = mbox_sts[3];893 if (fw_ddb_device_state)894 *fw_ddb_device_state = mbox_sts[4];895 896 /*897 * RA: This mailbox has been changed to pass connection error and898 * details. Its true for ISP4010 as per Version E - Not sure when it899 * was changed. Get the time2wait from the fw_dd_entry field :900 * default_time2wait which we call it as minTime2Wait DEV_DB_ENTRY901 * struct.902 */903 if (conn_err_detail)904 *conn_err_detail = mbox_sts[5];905 if (tcp_source_port_num)906 *tcp_source_port_num = (uint16_t) (mbox_sts[6] >> 16);907 if (connection_id)908 *connection_id = (uint16_t) mbox_sts[6] & 0x00FF;909 status = QLA_SUCCESS;910 911exit_get_fwddb:912 return status;913}914 915int qla4xxx_conn_open(struct scsi_qla_host *ha, uint16_t fw_ddb_index)916{917 uint32_t mbox_cmd[MBOX_REG_COUNT];918 uint32_t mbox_sts[MBOX_REG_COUNT];919 int status;920 921 memset(&mbox_cmd, 0, sizeof(mbox_cmd));922 memset(&mbox_sts, 0, sizeof(mbox_sts));923 924 mbox_cmd[0] = MBOX_CMD_CONN_OPEN;925 mbox_cmd[1] = fw_ddb_index;926 927 status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0],928 &mbox_sts[0]);929 DEBUG2(ql4_printk(KERN_INFO, ha,930 "%s: status = %d mbx0 = 0x%x mbx1 = 0x%x\n",931 __func__, status, mbox_sts[0], mbox_sts[1]));932 return status;933}934 935/**936 * qla4xxx_set_ddb_entry - sets a ddb entry.937 * @ha: Pointer to host adapter structure.938 * @fw_ddb_index: Firmware's device database index939 * @fw_ddb_entry_dma: dma address of ddb entry940 * @mbx_sts: mailbox 0 to be returned or NULL941 *942 * This routine initializes or updates the adapter's device database943 * entry for the specified device.944 **/945int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index,946 dma_addr_t fw_ddb_entry_dma, uint32_t *mbx_sts)947{948 uint32_t mbox_cmd[MBOX_REG_COUNT];949 uint32_t mbox_sts[MBOX_REG_COUNT];950 int status;951 952 /* Do not wait for completion. The firmware will send us an953 * ASTS_DATABASE_CHANGED (0x8014) to notify us of the login status.954 */955 memset(&mbox_cmd, 0, sizeof(mbox_cmd));956 memset(&mbox_sts, 0, sizeof(mbox_sts));957 958 mbox_cmd[0] = MBOX_CMD_SET_DATABASE_ENTRY;959 mbox_cmd[1] = (uint32_t) fw_ddb_index;960 mbox_cmd[2] = LSDW(fw_ddb_entry_dma);961 mbox_cmd[3] = MSDW(fw_ddb_entry_dma);962 mbox_cmd[4] = sizeof(struct dev_db_entry);963 964 status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0],965 &mbox_sts[0]);966 if (mbx_sts)967 *mbx_sts = mbox_sts[0];968 DEBUG2(printk("scsi%ld: %s: status=%d mbx0=0x%x mbx4=0x%x\n",969 ha->host_no, __func__, status, mbox_sts[0], mbox_sts[4]);)970 971 return status;972}973 974int qla4xxx_session_logout_ddb(struct scsi_qla_host *ha,975 struct ddb_entry *ddb_entry, int options)976{977 int status;978 uint32_t mbox_cmd[MBOX_REG_COUNT];979 uint32_t mbox_sts[MBOX_REG_COUNT];980 981 memset(&mbox_cmd, 0, sizeof(mbox_cmd));982 memset(&mbox_sts, 0, sizeof(mbox_sts));983 984 mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT;985 mbox_cmd[1] = ddb_entry->fw_ddb_index;986 mbox_cmd[3] = options;987 988 status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0],989 &mbox_sts[0]);990 if (status != QLA_SUCCESS) {991 DEBUG2(ql4_printk(KERN_INFO, ha,992 "%s: MBOX_CMD_CONN_CLOSE_SESS_LOGOUT "993 "failed sts %04X %04X", __func__,994 mbox_sts[0], mbox_sts[1]));995 if ((mbox_sts[0] == MBOX_STS_COMMAND_ERROR) &&996 (mbox_sts[1] == DDB_NOT_LOGGED_IN)) {997 set_bit(DDB_CONN_CLOSE_FAILURE, &ddb_entry->flags);998 }999 }1000 1001 return status;1002}1003 1004/**1005 * qla4xxx_get_crash_record - retrieves crash record.1006 * @ha: Pointer to host adapter structure.1007 *1008 * This routine retrieves a crash record from the QLA4010 after an 8002h aen.1009 **/1010void qla4xxx_get_crash_record(struct scsi_qla_host * ha)1011{1012 uint32_t mbox_cmd[MBOX_REG_COUNT];1013 uint32_t mbox_sts[MBOX_REG_COUNT];1014 struct crash_record *crash_record = NULL;1015 dma_addr_t crash_record_dma = 0;1016 uint32_t crash_record_size = 0;1017 1018 memset(&mbox_cmd, 0, sizeof(mbox_cmd));1019 memset(&mbox_sts, 0, sizeof(mbox_cmd));1020 1021 /* Get size of crash record. */1022 mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD;1023 1024 if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=1025 QLA_SUCCESS) {1026 DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve size!\n",1027 ha->host_no, __func__));1028 goto exit_get_crash_record;1029 }1030 crash_record_size = mbox_sts[4];1031 if (crash_record_size == 0) {1032 DEBUG2(printk("scsi%ld: %s: ERROR: Crash record size is 0!\n",1033 ha->host_no, __func__));1034 goto exit_get_crash_record;1035 }1036 1037 /* Alloc Memory for Crash Record. */1038 crash_record = dma_alloc_coherent(&ha->pdev->dev, crash_record_size,1039 &crash_record_dma, GFP_KERNEL);1040 if (crash_record == NULL)1041 goto exit_get_crash_record;1042 1043 /* Get Crash Record. */1044 memset(&mbox_cmd, 0, sizeof(mbox_cmd));1045 memset(&mbox_sts, 0, sizeof(mbox_cmd));1046 1047 mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD;1048 mbox_cmd[2] = LSDW(crash_record_dma);1049 mbox_cmd[3] = MSDW(crash_record_dma);1050 mbox_cmd[4] = crash_record_size;1051 1052 if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=1053 QLA_SUCCESS)1054 goto exit_get_crash_record;1055 1056 /* Dump Crash Record. */1057 1058exit_get_crash_record:1059 if (crash_record)1060 dma_free_coherent(&ha->pdev->dev, crash_record_size,1061 crash_record, crash_record_dma);1062}1063 1064/**1065 * qla4xxx_get_conn_event_log - retrieves connection event log1066 * @ha: Pointer to host adapter structure.1067 **/1068void qla4xxx_get_conn_event_log(struct scsi_qla_host * ha)1069{1070 uint32_t mbox_cmd[MBOX_REG_COUNT];1071 uint32_t mbox_sts[MBOX_REG_COUNT];1072 struct conn_event_log_entry *event_log = NULL;1073 dma_addr_t event_log_dma = 0;1074 uint32_t event_log_size = 0;1075 uint32_t num_valid_entries;1076 uint32_t oldest_entry = 0;1077 uint32_t max_event_log_entries;1078 uint8_t i;1079 1080 memset(&mbox_cmd, 0, sizeof(mbox_cmd));1081 memset(&mbox_sts, 0, sizeof(mbox_cmd));1082 1083 /* Get size of crash record. */1084 mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG;1085 1086 if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=1087 QLA_SUCCESS)1088 goto exit_get_event_log;1089 1090 event_log_size = mbox_sts[4];1091 if (event_log_size == 0)1092 goto exit_get_event_log;1093 1094 /* Alloc Memory for Crash Record. */1095 event_log = dma_alloc_coherent(&ha->pdev->dev, event_log_size,1096 &event_log_dma, GFP_KERNEL);1097 if (event_log == NULL)1098 goto exit_get_event_log;1099 1100 /* Get Crash Record. */1101 memset(&mbox_cmd, 0, sizeof(mbox_cmd));1102 memset(&mbox_sts, 0, sizeof(mbox_cmd));1103 1104 mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG;1105 mbox_cmd[2] = LSDW(event_log_dma);1106 mbox_cmd[3] = MSDW(event_log_dma);1107 1108 if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=1109 QLA_SUCCESS) {1110 DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve event "1111 "log!\n", ha->host_no, __func__));1112 goto exit_get_event_log;1113 }1114 1115 /* Dump Event Log. */1116 num_valid_entries = mbox_sts[1];1117 1118 max_event_log_entries = event_log_size /1119 sizeof(struct conn_event_log_entry);1120 1121 if (num_valid_entries > max_event_log_entries)1122 oldest_entry = num_valid_entries % max_event_log_entries;1123 1124 DEBUG3(printk("scsi%ld: Connection Event Log Dump (%d entries):\n",1125 ha->host_no, num_valid_entries));1126 1127 if (ql4xextended_error_logging == 3) {1128 if (oldest_entry == 0) {1129 /* Circular Buffer has not wrapped around */1130 for (i=0; i < num_valid_entries; i++) {1131 qla4xxx_dump_buffer((uint8_t *)event_log+1132 (i*sizeof(*event_log)),1133 sizeof(*event_log));1134 }1135 }1136 else {1137 /* Circular Buffer has wrapped around -1138 * display accordingly*/1139 for (i=oldest_entry; i < max_event_log_entries; i++) {1140 qla4xxx_dump_buffer((uint8_t *)event_log+1141 (i*sizeof(*event_log)),1142 sizeof(*event_log));1143 }1144 for (i=0; i < oldest_entry; i++) {1145 qla4xxx_dump_buffer((uint8_t *)event_log+1146 (i*sizeof(*event_log)),1147 sizeof(*event_log));1148 }1149 }1150 }1151 1152exit_get_event_log:1153 if (event_log)1154 dma_free_coherent(&ha->pdev->dev, event_log_size, event_log,1155 event_log_dma);1156}1157 1158/**1159 * qla4xxx_abort_task - issues Abort Task1160 * @ha: Pointer to host adapter structure.1161 * @srb: Pointer to srb entry1162 *1163 * This routine performs a LUN RESET on the specified target/lun.1164 * The caller must ensure that the ddb_entry and lun_entry pointers1165 * are valid before calling this routine.1166 **/1167int qla4xxx_abort_task(struct scsi_qla_host *ha, struct srb *srb)1168{1169 uint32_t mbox_cmd[MBOX_REG_COUNT];1170 uint32_t mbox_sts[MBOX_REG_COUNT];1171 struct scsi_cmnd *cmd = srb->cmd;1172 int status = QLA_SUCCESS;1173 unsigned long flags = 0;1174 uint32_t index;1175 1176 /*1177 * Send abort task command to ISP, so that the ISP will return1178 * request with ABORT status1179 */1180 memset(&mbox_cmd, 0, sizeof(mbox_cmd));1181 memset(&mbox_sts, 0, sizeof(mbox_sts));1182 1183 spin_lock_irqsave(&ha->hardware_lock, flags);1184 index = (unsigned long)(unsigned char *)cmd->host_scribble;1185 spin_unlock_irqrestore(&ha->hardware_lock, flags);1186 1187 /* Firmware already posted completion on response queue */1188 if (index == MAX_SRBS)1189 return status;1190 1191 mbox_cmd[0] = MBOX_CMD_ABORT_TASK;1192 mbox_cmd[1] = srb->ddb->fw_ddb_index;1193 mbox_cmd[2] = index;1194 /* Immediate Command Enable */1195 mbox_cmd[5] = 0x01;1196 1197 qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0],1198 &mbox_sts[0]);1199 if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE) {1200 status = QLA_ERROR;1201 1202 DEBUG2(printk(KERN_WARNING "scsi%ld:%d:%llu: abort task FAILED: "1203 "mbx0=%04X, mb1=%04X, mb2=%04X, mb3=%04X, mb4=%04X\n",1204 ha->host_no, cmd->device->id, cmd->device->lun, mbox_sts[0],1205 mbox_sts[1], mbox_sts[2], mbox_sts[3], mbox_sts[4]));1206 }1207 1208 return status;1209}1210 1211/**1212 * qla4xxx_reset_lun - issues LUN Reset1213 * @ha: Pointer to host adapter structure.1214 * @ddb_entry: Pointer to device database entry1215 * @lun: lun number1216 *1217 * This routine performs a LUN RESET on the specified target/lun.1218 * The caller must ensure that the ddb_entry and lun_entry pointers1219 * are valid before calling this routine.1220 **/1221int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry,1222 uint64_t lun)1223{1224 uint32_t mbox_cmd[MBOX_REG_COUNT];1225 uint32_t mbox_sts[MBOX_REG_COUNT];1226 uint32_t scsi_lun[2];1227 int status = QLA_SUCCESS;1228 1229 DEBUG2(printk("scsi%ld:%d:%llu: lun reset issued\n", ha->host_no,1230 ddb_entry->fw_ddb_index, lun));1231 1232 /*1233 * Send lun reset command to ISP, so that the ISP will return all1234 * outstanding requests with RESET status1235 */1236 memset(&mbox_cmd, 0, sizeof(mbox_cmd));1237 memset(&mbox_sts, 0, sizeof(mbox_sts));1238 int_to_scsilun(lun, (struct scsi_lun *) scsi_lun);1239 1240 mbox_cmd[0] = MBOX_CMD_LUN_RESET;1241 mbox_cmd[1] = ddb_entry->fw_ddb_index;1242 /* FW expects LUN bytes 0-3 in Incoming Mailbox 21243 * (LUN byte 0 is LSByte, byte 3 is MSByte) */1244 mbox_cmd[2] = cpu_to_le32(scsi_lun[0]);1245 /* FW expects LUN bytes 4-7 in Incoming Mailbox 31246 * (LUN byte 4 is LSByte, byte 7 is MSByte) */1247 mbox_cmd[3] = cpu_to_le32(scsi_lun[1]);1248 mbox_cmd[5] = 0x01; /* Immediate Command Enable */1249 1250 qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]);1251 if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE &&1252 mbox_sts[0] != MBOX_STS_COMMAND_ERROR)1253 status = QLA_ERROR;1254 1255 return status;1256}1257 1258/**1259 * qla4xxx_reset_target - issues target Reset1260 * @ha: Pointer to host adapter structure.1261 * @ddb_entry: Pointer to device database entry1262 *1263 * This routine performs a TARGET RESET on the specified target.1264 * The caller must ensure that the ddb_entry pointers1265 * are valid before calling this routine.1266 **/1267int qla4xxx_reset_target(struct scsi_qla_host *ha,1268 struct ddb_entry *ddb_entry)1269{1270 uint32_t mbox_cmd[MBOX_REG_COUNT];1271 uint32_t mbox_sts[MBOX_REG_COUNT];1272 int status = QLA_SUCCESS;1273 1274 DEBUG2(printk("scsi%ld:%d: target reset issued\n", ha->host_no,1275 ddb_entry->fw_ddb_index));1276 1277 /*1278 * Send target reset command to ISP, so that the ISP will return all1279 * outstanding requests with RESET status1280 */1281 memset(&mbox_cmd, 0, sizeof(mbox_cmd));1282 memset(&mbox_sts, 0, sizeof(mbox_sts));1283 1284 mbox_cmd[0] = MBOX_CMD_TARGET_WARM_RESET;1285 mbox_cmd[1] = ddb_entry->fw_ddb_index;1286 mbox_cmd[5] = 0x01; /* Immediate Command Enable */1287 1288 qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],1289 &mbox_sts[0]);1290 if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE &&1291 mbox_sts[0] != MBOX_STS_COMMAND_ERROR)1292 status = QLA_ERROR;1293 1294 return status;1295}1296 1297int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr,1298 uint32_t offset, uint32_t len)1299{1300 uint32_t mbox_cmd[MBOX_REG_COUNT];1301 uint32_t mbox_sts[MBOX_REG_COUNT];1302 1303 memset(&mbox_cmd, 0, sizeof(mbox_cmd));1304 memset(&mbox_sts, 0, sizeof(mbox_sts));1305 1306 mbox_cmd[0] = MBOX_CMD_READ_FLASH;1307 mbox_cmd[1] = LSDW(dma_addr);1308 mbox_cmd[2] = MSDW(dma_addr);1309 mbox_cmd[3] = offset;1310 mbox_cmd[4] = len;1311 1312 if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0], &mbox_sts[0]) !=1313 QLA_SUCCESS) {1314 DEBUG2(printk("scsi%ld: %s: MBOX_CMD_READ_FLASH, failed w/ "1315 "status %04X %04X, offset %08x, len %08x\n", ha->host_no,1316 __func__, mbox_sts[0], mbox_sts[1], offset, len));1317 return QLA_ERROR;1318 }1319 return QLA_SUCCESS;1320}1321 1322/**1323 * qla4xxx_about_firmware - gets FW, iscsi draft and boot loader version1324 * @ha: Pointer to host adapter structure.1325 *1326 * Retrieves the FW version, iSCSI draft version & bootloader version of HBA.1327 * Mailboxes 2 & 3 may hold an address for data. Make sure that we write 0 to1328 * those mailboxes, if unused.1329 **/1330int qla4xxx_about_firmware(struct scsi_qla_host *ha)1331{1332 struct about_fw_info *about_fw = NULL;1333 dma_addr_t about_fw_dma;1334 uint32_t mbox_cmd[MBOX_REG_COUNT];1335 uint32_t mbox_sts[MBOX_REG_COUNT];1336 int status = QLA_ERROR;1337 1338 about_fw = dma_alloc_coherent(&ha->pdev->dev,1339 sizeof(struct about_fw_info),1340 &about_fw_dma, GFP_KERNEL);1341 if (!about_fw) {1342 DEBUG2(ql4_printk(KERN_ERR, ha, "%s: Unable to alloc memory "1343 "for about_fw\n", __func__));1344 return status;1345 }1346 1347 memset(&mbox_cmd, 0, sizeof(mbox_cmd));1348 memset(&mbox_sts, 0, sizeof(mbox_sts));1349 1350 mbox_cmd[0] = MBOX_CMD_ABOUT_FW;1351 mbox_cmd[2] = LSDW(about_fw_dma);1352 mbox_cmd[3] = MSDW(about_fw_dma);1353 mbox_cmd[4] = sizeof(struct about_fw_info);1354 1355 status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT,1356 &mbox_cmd[0], &mbox_sts[0]);1357 if (status != QLA_SUCCESS) {1358 DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_ABOUT_FW "1359 "failed w/ status %04X\n", __func__,1360 mbox_sts[0]));1361 goto exit_about_fw;1362 }1363 1364 /* Save version information. */1365 ha->fw_info.fw_major = le16_to_cpu(about_fw->fw_major);1366 ha->fw_info.fw_minor = le16_to_cpu(about_fw->fw_minor);1367 ha->fw_info.fw_patch = le16_to_cpu(about_fw->fw_patch);1368 ha->fw_info.fw_build = le16_to_cpu(about_fw->fw_build);1369 memcpy(ha->fw_info.fw_build_date, about_fw->fw_build_date,1370 sizeof(about_fw->fw_build_date));1371 memcpy(ha->fw_info.fw_build_time, about_fw->fw_build_time,1372 sizeof(about_fw->fw_build_time));1373 strcpy((char *)ha->fw_info.fw_build_user,1374 skip_spaces((char *)about_fw->fw_build_user));1375 ha->fw_info.fw_load_source = le16_to_cpu(about_fw->fw_load_source);1376 ha->fw_info.iscsi_major = le16_to_cpu(about_fw->iscsi_major);1377 ha->fw_info.iscsi_minor = le16_to_cpu(about_fw->iscsi_minor);1378 ha->fw_info.bootload_major = le16_to_cpu(about_fw->bootload_major);1379 ha->fw_info.bootload_minor = le16_to_cpu(about_fw->bootload_minor);1380 ha->fw_info.bootload_patch = le16_to_cpu(about_fw->bootload_patch);1381 ha->fw_info.bootload_build = le16_to_cpu(about_fw->bootload_build);1382 strcpy((char *)ha->fw_info.extended_timestamp,1383 skip_spaces((char *)about_fw->extended_timestamp));1384 1385 ha->fw_uptime_secs = le32_to_cpu(mbox_sts[5]);1386 ha->fw_uptime_msecs = le32_to_cpu(mbox_sts[6]);1387 status = QLA_SUCCESS;1388 1389exit_about_fw:1390 dma_free_coherent(&ha->pdev->dev, sizeof(struct about_fw_info),1391 about_fw, about_fw_dma);1392 return status;1393}1394 1395int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, uint32_t options,1396 dma_addr_t dma_addr)1397{1398 uint32_t mbox_cmd[MBOX_REG_COUNT];1399 uint32_t mbox_sts[MBOX_REG_COUNT];1400 1401 memset(&mbox_cmd, 0, sizeof(mbox_cmd));1402 memset(&mbox_sts, 0, sizeof(mbox_sts));1403 1404 mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY_DEFAULTS;1405 mbox_cmd[1] = options;1406 mbox_cmd[2] = LSDW(dma_addr);1407 mbox_cmd[3] = MSDW(dma_addr);1408 1409 if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) !=1410 QLA_SUCCESS) {1411 DEBUG2(printk("scsi%ld: %s: failed status %04X\n",1412 ha->host_no, __func__, mbox_sts[0]));1413 return QLA_ERROR;1414 }1415 return QLA_SUCCESS;1416}1417 1418int qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t ddb_index,1419 uint32_t *mbx_sts)1420{1421 int status;1422 uint32_t mbox_cmd[MBOX_REG_COUNT];1423 uint32_t mbox_sts[MBOX_REG_COUNT];1424 1425 memset(&mbox_cmd, 0, sizeof(mbox_cmd));1426 memset(&mbox_sts, 0, sizeof(mbox_sts));1427 1428 mbox_cmd[0] = MBOX_CMD_REQUEST_DATABASE_ENTRY;1429 mbox_cmd[1] = ddb_index;1430 1431 status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],1432 &mbox_sts[0]);1433 if (status != QLA_SUCCESS) {1434 DEBUG2(ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n",1435 __func__, mbox_sts[0]));1436 }1437 1438 *mbx_sts = mbox_sts[0];1439 return status;1440}1441 1442int qla4xxx_clear_ddb_entry(struct scsi_qla_host *ha, uint32_t ddb_index)1443{1444 int status;1445 uint32_t mbox_cmd[MBOX_REG_COUNT];1446 uint32_t mbox_sts[MBOX_REG_COUNT];1447 1448 memset(&mbox_cmd, 0, sizeof(mbox_cmd));1449 memset(&mbox_sts, 0, sizeof(mbox_sts));1450 1451 mbox_cmd[0] = MBOX_CMD_CLEAR_DATABASE_ENTRY;1452 mbox_cmd[1] = ddb_index;1453 1454 status = qla4xxx_mailbox_command(ha, 2, 1, &mbox_cmd[0],1455 &mbox_sts[0]);1456 if (status != QLA_SUCCESS) {1457 DEBUG2(ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n",1458 __func__, mbox_sts[0]));1459 }1460 1461 return status;1462}1463 1464int qla4xxx_set_flash(struct scsi_qla_host *ha, dma_addr_t dma_addr,1465 uint32_t offset, uint32_t length, uint32_t options)1466{1467 uint32_t mbox_cmd[MBOX_REG_COUNT];1468 uint32_t mbox_sts[MBOX_REG_COUNT];1469 int status = QLA_SUCCESS;1470 1471 memset(&mbox_cmd, 0, sizeof(mbox_cmd));1472 memset(&mbox_sts, 0, sizeof(mbox_sts));1473 1474 mbox_cmd[0] = MBOX_CMD_WRITE_FLASH;1475 mbox_cmd[1] = LSDW(dma_addr);1476 mbox_cmd[2] = MSDW(dma_addr);1477 mbox_cmd[3] = offset;1478 mbox_cmd[4] = length;1479 mbox_cmd[5] = options;1480 1481 status = qla4xxx_mailbox_command(ha, 6, 2, &mbox_cmd[0], &mbox_sts[0]);1482 if (status != QLA_SUCCESS) {1483 DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_WRITE_FLASH "1484 "failed w/ status %04X, mbx1 %04X\n",1485 __func__, mbox_sts[0], mbox_sts[1]));1486 }1487 return status;1488}1489 1490int qla4xxx_bootdb_by_index(struct scsi_qla_host *ha,1491 struct dev_db_entry *fw_ddb_entry,1492 dma_addr_t fw_ddb_entry_dma, uint16_t ddb_index)1493{1494 uint32_t dev_db_start_offset = FLASH_OFFSET_DB_INFO;1495 uint32_t dev_db_end_offset;1496 int status = QLA_ERROR;1497 1498 memset(fw_ddb_entry, 0, sizeof(*fw_ddb_entry));1499 1500 dev_db_start_offset += (ddb_index * sizeof(*fw_ddb_entry));1501 dev_db_end_offset = FLASH_OFFSET_DB_END;1502 1503 if (dev_db_start_offset > dev_db_end_offset) {1504 DEBUG2(ql4_printk(KERN_ERR, ha,1505 "%s:Invalid DDB index %d", __func__,1506 ddb_index));1507 goto exit_bootdb_failed;1508 }1509 1510 if (qla4xxx_get_flash(ha, fw_ddb_entry_dma, dev_db_start_offset,1511 sizeof(*fw_ddb_entry)) != QLA_SUCCESS) {1512 ql4_printk(KERN_ERR, ha, "scsi%ld: %s: Get Flash"1513 "failed\n", ha->host_no, __func__);1514 goto exit_bootdb_failed;1515 }1516 1517 if (fw_ddb_entry->cookie == DDB_VALID_COOKIE)1518 status = QLA_SUCCESS;1519 1520exit_bootdb_failed:1521 return status;1522}1523 1524int qla4xxx_flashdb_by_index(struct scsi_qla_host *ha,1525 struct dev_db_entry *fw_ddb_entry,1526 dma_addr_t fw_ddb_entry_dma, uint16_t ddb_index)1527{1528 uint32_t dev_db_start_offset;1529 uint32_t dev_db_end_offset;1530 int status = QLA_ERROR;1531 1532 memset(fw_ddb_entry, 0, sizeof(*fw_ddb_entry));1533 1534 if (is_qla40XX(ha)) {1535 dev_db_start_offset = FLASH_OFFSET_DB_INFO;1536 dev_db_end_offset = FLASH_OFFSET_DB_END;1537 } else {1538 dev_db_start_offset = FLASH_RAW_ACCESS_ADDR +1539 (ha->hw.flt_region_ddb << 2);1540 /* flt_ddb_size is DDB table size for both ports1541 * so divide it by 2 to calculate the offset for second port1542 */1543 if (ha->port_num == 1)1544 dev_db_start_offset += (ha->hw.flt_ddb_size / 2);1545 1546 dev_db_end_offset = dev_db_start_offset +1547 (ha->hw.flt_ddb_size / 2);1548 }1549 1550 dev_db_start_offset += (ddb_index * sizeof(*fw_ddb_entry));1551 1552 if (dev_db_start_offset > dev_db_end_offset) {1553 DEBUG2(ql4_printk(KERN_ERR, ha,1554 "%s:Invalid DDB index %d", __func__,1555 ddb_index));1556 goto exit_fdb_failed;1557 }1558 1559 if (qla4xxx_get_flash(ha, fw_ddb_entry_dma, dev_db_start_offset,1560 sizeof(*fw_ddb_entry)) != QLA_SUCCESS) {1561 ql4_printk(KERN_ERR, ha, "scsi%ld: %s: Get Flash failed\n",1562 ha->host_no, __func__);1563 goto exit_fdb_failed;1564 }1565 1566 if (fw_ddb_entry->cookie == DDB_VALID_COOKIE)1567 status = QLA_SUCCESS;1568 1569exit_fdb_failed:1570 return status;1571}1572 1573int qla4xxx_get_chap(struct scsi_qla_host *ha, char *username, char *password,1574 uint16_t idx)1575{1576 int ret = 0;1577 int rval = QLA_ERROR;1578 uint32_t offset = 0, chap_size;1579 struct ql4_chap_table *chap_table;1580 dma_addr_t chap_dma;1581 1582 chap_table = dma_pool_zalloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma);1583 if (chap_table == NULL)1584 return -ENOMEM;1585 1586 chap_size = sizeof(struct ql4_chap_table);1587 1588 if (is_qla40XX(ha))1589 offset = FLASH_CHAP_OFFSET | (idx * chap_size);1590 else {1591 offset = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_region_chap << 2);1592 /* flt_chap_size is CHAP table size for both ports1593 * so divide it by 2 to calculate the offset for second port1594 */1595 if (ha->port_num == 1)1596 offset += (ha->hw.flt_chap_size / 2);1597 offset += (idx * chap_size);1598 }1599 1600 rval = qla4xxx_get_flash(ha, chap_dma, offset, chap_size);1601 if (rval != QLA_SUCCESS) {1602 ret = -EINVAL;1603 goto exit_get_chap;1604 }1605 1606 DEBUG2(ql4_printk(KERN_INFO, ha, "Chap Cookie: x%x\n",1607 __le16_to_cpu(chap_table->cookie)));1608 1609 if (__le16_to_cpu(chap_table->cookie) != CHAP_VALID_COOKIE) {1610 ql4_printk(KERN_ERR, ha, "No valid chap entry found\n");1611 goto exit_get_chap;1612 }1613 1614 strscpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN);1615 strscpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN);1616 chap_table->cookie = cpu_to_le16(CHAP_VALID_COOKIE);1617 1618exit_get_chap:1619 dma_pool_free(ha->chap_dma_pool, chap_table, chap_dma);1620 return ret;1621}1622 1623/**1624 * qla4xxx_set_chap - Make a chap entry at the given index1625 * @ha: pointer to adapter structure1626 * @username: CHAP username to set1627 * @password: CHAP password to set1628 * @idx: CHAP index at which to make the entry1629 * @bidi: type of chap entry (chap_in or chap_out)1630 *1631 * Create chap entry at the given index with the information provided.1632 *1633 * Note: Caller should acquire the chap lock before getting here.1634 **/1635int qla4xxx_set_chap(struct scsi_qla_host *ha, char *username, char *password,1636 uint16_t idx, int bidi)1637{1638 int ret = 0;1639 int rval = QLA_ERROR;1640 uint32_t offset = 0;1641 struct ql4_chap_table *chap_table;1642 uint32_t chap_size = 0;1643 dma_addr_t chap_dma;1644 ssize_t secret_len;1645 1646 chap_table = dma_pool_zalloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma);1647 if (chap_table == NULL) {1648 ret = -ENOMEM;1649 goto exit_set_chap;1650 }1651 1652 if (bidi)1653 chap_table->flags |= BIT_6; /* peer */1654 else1655 chap_table->flags |= BIT_7; /* local */1656 1657 secret_len = strscpy(chap_table->secret, password,1658 sizeof(chap_table->secret));1659 if (secret_len < MIN_CHAP_SECRET_LEN)1660 goto cleanup_chap_table;1661 chap_table->secret_len = (uint8_t)secret_len;1662 strscpy(chap_table->name, username, sizeof(chap_table->name));1663 chap_table->cookie = cpu_to_le16(CHAP_VALID_COOKIE);1664 1665 if (is_qla40XX(ha)) {1666 chap_size = MAX_CHAP_ENTRIES_40XX * sizeof(*chap_table);1667 offset = FLASH_CHAP_OFFSET;1668 } else { /* Single region contains CHAP info for both ports which is1669 * divided into half for each port.1670 */1671 chap_size = ha->hw.flt_chap_size / 2;1672 offset = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_region_chap << 2);1673 if (ha->port_num == 1)1674 offset += chap_size;1675 }1676 1677 offset += (idx * sizeof(struct ql4_chap_table));1678 rval = qla4xxx_set_flash(ha, chap_dma, offset,1679 sizeof(struct ql4_chap_table),1680 FLASH_OPT_RMW_COMMIT);1681 1682 if (rval == QLA_SUCCESS && ha->chap_list) {1683 /* Update ha chap_list cache */1684 memcpy((struct ql4_chap_table *)ha->chap_list + idx,1685 chap_table, sizeof(struct ql4_chap_table));1686 }1687 1688cleanup_chap_table:1689 dma_pool_free(ha->chap_dma_pool, chap_table, chap_dma);1690 if (rval != QLA_SUCCESS)1691 ret = -EINVAL;1692 1693exit_set_chap:1694 return ret;1695}1696 1697 1698int qla4xxx_get_uni_chap_at_index(struct scsi_qla_host *ha, char *username,1699 char *password, uint16_t chap_index)1700{1701 int rval = QLA_ERROR;1702 struct ql4_chap_table *chap_table = NULL;1703 int max_chap_entries;1704 1705 if (!ha->chap_list) {1706 ql4_printk(KERN_ERR, ha, "Do not have CHAP table cache\n");1707 rval = QLA_ERROR;1708 goto exit_uni_chap;1709 }1710 1711 if (!username || !password) {1712 ql4_printk(KERN_ERR, ha, "No memory for username & secret\n");1713 rval = QLA_ERROR;1714 goto exit_uni_chap;1715 }1716 1717 if (is_qla80XX(ha))1718 max_chap_entries = (ha->hw.flt_chap_size / 2) /1719 sizeof(struct ql4_chap_table);1720 else1721 max_chap_entries = MAX_CHAP_ENTRIES_40XX;1722 1723 if (chap_index > max_chap_entries) {1724 ql4_printk(KERN_ERR, ha, "Invalid Chap index\n");1725 rval = QLA_ERROR;1726 goto exit_uni_chap;1727 }1728 1729 mutex_lock(&ha->chap_sem);1730 chap_table = (struct ql4_chap_table *)ha->chap_list + chap_index;1731 if (chap_table->cookie != cpu_to_le16(CHAP_VALID_COOKIE)) {1732 rval = QLA_ERROR;1733 goto exit_unlock_uni_chap;1734 }1735 1736 if (!(chap_table->flags & BIT_7)) {1737 ql4_printk(KERN_ERR, ha, "Unidirectional entry not set\n");1738 rval = QLA_ERROR;1739 goto exit_unlock_uni_chap;1740 }1741 1742 strscpy(password, chap_table->secret, MAX_CHAP_SECRET_LEN);1743 strscpy(username, chap_table->name, MAX_CHAP_NAME_LEN);1744 1745 rval = QLA_SUCCESS;1746 1747exit_unlock_uni_chap:1748 mutex_unlock(&ha->chap_sem);1749exit_uni_chap:1750 return rval;1751}1752 1753/**1754 * qla4xxx_get_chap_index - Get chap index given username and secret1755 * @ha: pointer to adapter structure1756 * @username: CHAP username to be searched1757 * @password: CHAP password to be searched1758 * @bidi: Is this a BIDI CHAP1759 * @chap_index: CHAP index to be returned1760 *1761 * Match the username and password in the chap_list, return the index if a1762 * match is found. If a match is not found then add the entry in FLASH and1763 * return the index at which entry is written in the FLASH.1764 **/1765int qla4xxx_get_chap_index(struct scsi_qla_host *ha, char *username,1766 char *password, int bidi, uint16_t *chap_index)1767{1768 int i, rval;1769 int free_index = -1;1770 int found_index = 0;1771 int max_chap_entries = 0;1772 struct ql4_chap_table *chap_table;1773 1774 if (is_qla80XX(ha))1775 max_chap_entries = (ha->hw.flt_chap_size / 2) /1776 sizeof(struct ql4_chap_table);1777 else1778 max_chap_entries = MAX_CHAP_ENTRIES_40XX;1779 1780 if (!ha->chap_list) {1781 ql4_printk(KERN_ERR, ha, "Do not have CHAP table cache\n");1782 return QLA_ERROR;1783 }1784 1785 if (!username || !password) {1786 ql4_printk(KERN_ERR, ha, "Do not have username and psw\n");1787 return QLA_ERROR;1788 }1789 1790 mutex_lock(&ha->chap_sem);1791 for (i = 0; i < max_chap_entries; i++) {1792 chap_table = (struct ql4_chap_table *)ha->chap_list + i;1793 if (chap_table->cookie !=1794 cpu_to_le16(CHAP_VALID_COOKIE)) {1795 if (i > MAX_RESRV_CHAP_IDX && free_index == -1)1796 free_index = i;1797 continue;1798 }1799 if (bidi) {1800 if (chap_table->flags & BIT_7)1801 continue;1802 } else {1803 if (chap_table->flags & BIT_6)1804 continue;1805 }1806 if (!strncmp(chap_table->secret, password,1807 MAX_CHAP_SECRET_LEN) &&1808 !strncmp(chap_table->name, username,1809 MAX_CHAP_NAME_LEN)) {1810 *chap_index = i;1811 found_index = 1;1812 break;1813 }1814 }1815 1816 /* If chap entry is not present and a free index is available then1817 * write the entry in flash1818 */1819 if (!found_index && free_index != -1) {1820 rval = qla4xxx_set_chap(ha, username, password,1821 free_index, bidi);1822 if (!rval) {1823 *chap_index = free_index;1824 found_index = 1;1825 }1826 }1827 1828 mutex_unlock(&ha->chap_sem);1829 1830 if (found_index)1831 return QLA_SUCCESS;1832 return QLA_ERROR;1833}1834 1835int qla4xxx_conn_close_sess_logout(struct scsi_qla_host *ha,1836 uint16_t fw_ddb_index,1837 uint16_t connection_id,1838 uint16_t option)1839{1840 uint32_t mbox_cmd[MBOX_REG_COUNT];1841 uint32_t mbox_sts[MBOX_REG_COUNT];1842 int status = QLA_SUCCESS;1843 1844 memset(&mbox_cmd, 0, sizeof(mbox_cmd));1845 memset(&mbox_sts, 0, sizeof(mbox_sts));1846 1847 mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT;1848 mbox_cmd[1] = fw_ddb_index;1849 mbox_cmd[2] = connection_id;1850 mbox_cmd[3] = option;1851 1852 status = qla4xxx_mailbox_command(ha, 4, 2, &mbox_cmd[0], &mbox_sts[0]);1853 if (status != QLA_SUCCESS) {1854 DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_CONN_CLOSE "1855 "option %04x failed w/ status %04X %04X\n",1856 __func__, option, mbox_sts[0], mbox_sts[1]));1857 }1858 return status;1859}1860 1861/**1862 * qla4_84xx_extend_idc_tmo - Extend IDC Timeout.1863 * @ha: Pointer to host adapter structure.1864 * @ext_tmo: idc timeout value1865 *1866 * Requests firmware to extend the idc timeout value.1867 **/1868static int qla4_84xx_extend_idc_tmo(struct scsi_qla_host *ha, uint32_t ext_tmo)1869{1870 uint32_t mbox_cmd[MBOX_REG_COUNT];1871 uint32_t mbox_sts[MBOX_REG_COUNT];1872 int status;1873 1874 memset(&mbox_cmd, 0, sizeof(mbox_cmd));1875 memset(&mbox_sts, 0, sizeof(mbox_sts));1876 ext_tmo &= 0xf;1877 1878 mbox_cmd[0] = MBOX_CMD_IDC_TIME_EXTEND;1879 mbox_cmd[1] = ((ha->idc_info.request_desc & 0xfffff0ff) |1880 (ext_tmo << 8)); /* new timeout */1881 mbox_cmd[2] = ha->idc_info.info1;1882 mbox_cmd[3] = ha->idc_info.info2;1883 mbox_cmd[4] = ha->idc_info.info3;1884 1885 status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT,1886 mbox_cmd, mbox_sts);1887 if (status != QLA_SUCCESS) {1888 DEBUG2(ql4_printk(KERN_INFO, ha,1889 "scsi%ld: %s: failed status %04X\n",1890 ha->host_no, __func__, mbox_sts[0]));1891 return QLA_ERROR;1892 } else {1893 ql4_printk(KERN_INFO, ha, "%s: IDC timeout extended by %d secs\n",1894 __func__, ext_tmo);1895 }1896 1897 return QLA_SUCCESS;1898}1899 1900int qla4xxx_disable_acb(struct scsi_qla_host *ha)1901{1902 uint32_t mbox_cmd[MBOX_REG_COUNT];1903 uint32_t mbox_sts[MBOX_REG_COUNT];1904 int status = QLA_SUCCESS;1905 1906 memset(&mbox_cmd, 0, sizeof(mbox_cmd));1907 memset(&mbox_sts, 0, sizeof(mbox_sts));1908 1909 mbox_cmd[0] = MBOX_CMD_DISABLE_ACB;1910 1911 status = qla4xxx_mailbox_command(ha, 8, 5, &mbox_cmd[0], &mbox_sts[0]);1912 if (status != QLA_SUCCESS) {1913 DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_DISABLE_ACB "1914 "failed w/ status %04X %04X %04X", __func__,1915 mbox_sts[0], mbox_sts[1], mbox_sts[2]));1916 } else {1917 if (is_qla8042(ha) &&1918 test_bit(DPC_POST_IDC_ACK, &ha->dpc_flags) &&1919 (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE)) {1920 /*1921 * Disable ACB mailbox command takes time to complete1922 * based on the total number of targets connected.1923 * For 512 targets, it took approximately 5 secs to1924 * complete. Setting the timeout value to 8, with the 31925 * secs buffer.1926 */1927 qla4_84xx_extend_idc_tmo(ha, IDC_EXTEND_TOV);1928 if (!wait_for_completion_timeout(&ha->disable_acb_comp,1929 IDC_EXTEND_TOV * HZ)) {1930 ql4_printk(KERN_WARNING, ha, "%s: Disable ACB Completion not received\n",1931 __func__);1932 }1933 }1934 }1935 return status;1936}1937 1938int qla4xxx_get_acb(struct scsi_qla_host *ha, dma_addr_t acb_dma,1939 uint32_t acb_type, uint32_t len)1940{1941 uint32_t mbox_cmd[MBOX_REG_COUNT];1942 uint32_t mbox_sts[MBOX_REG_COUNT];1943 int status = QLA_SUCCESS;1944 1945 memset(&mbox_cmd, 0, sizeof(mbox_cmd));1946 memset(&mbox_sts, 0, sizeof(mbox_sts));1947 1948 mbox_cmd[0] = MBOX_CMD_GET_ACB;1949 mbox_cmd[1] = acb_type;1950 mbox_cmd[2] = LSDW(acb_dma);1951 mbox_cmd[3] = MSDW(acb_dma);1952 mbox_cmd[4] = len;1953 1954 status = qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]);1955 if (status != QLA_SUCCESS) {1956 DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_GET_ACB "1957 "failed w/ status %04X\n", __func__,1958 mbox_sts[0]));1959 }1960 return status;1961}1962 1963int qla4xxx_set_acb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,1964 uint32_t *mbox_sts, dma_addr_t acb_dma)1965{1966 int status = QLA_SUCCESS;1967 1968 memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT);1969 memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT);1970 mbox_cmd[0] = MBOX_CMD_SET_ACB;1971 mbox_cmd[1] = 0; /* Primary ACB */1972 mbox_cmd[2] = LSDW(acb_dma);1973 mbox_cmd[3] = MSDW(acb_dma);1974 mbox_cmd[4] = sizeof(struct addr_ctrl_blk);1975 1976 status = qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]);1977 if (status != QLA_SUCCESS) {1978 DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_SET_ACB "1979 "failed w/ status %04X\n", __func__,1980 mbox_sts[0]));1981 }1982 return status;1983}1984 1985int qla4xxx_set_param_ddbentry(struct scsi_qla_host *ha,1986 struct ddb_entry *ddb_entry,1987 struct iscsi_cls_conn *cls_conn,1988 uint32_t *mbx_sts)1989{1990 struct dev_db_entry *fw_ddb_entry;1991 struct iscsi_conn *conn;1992 struct iscsi_session *sess;1993 struct qla_conn *qla_conn;1994 struct sockaddr *dst_addr;1995 dma_addr_t fw_ddb_entry_dma;1996 int status = QLA_SUCCESS;1997 int rval = 0;1998 struct sockaddr_in *addr;1999 struct sockaddr_in6 *addr6;2000 char *ip;2001 uint16_t iscsi_opts = 0;2002 uint32_t options = 0;2003 uint16_t idx, *ptid;2004 2005 fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),2006 &fw_ddb_entry_dma, GFP_KERNEL);2007 if (!fw_ddb_entry) {2008 DEBUG2(ql4_printk(KERN_ERR, ha,2009 "%s: Unable to allocate dma buffer.\n",2010 __func__));2011 rval = -ENOMEM;2012 goto exit_set_param_no_free;2013 }2014 2015 conn = cls_conn->dd_data;2016 qla_conn = conn->dd_data;2017 sess = conn->session;2018 dst_addr = (struct sockaddr *)&qla_conn->qla_ep->dst_addr;2019 2020 if (dst_addr->sa_family == AF_INET6)2021 options |= IPV6_DEFAULT_DDB_ENTRY;2022 2023 status = qla4xxx_get_default_ddb(ha, options, fw_ddb_entry_dma);2024 if (status == QLA_ERROR) {2025 rval = -EINVAL;2026 goto exit_set_param;2027 }2028 2029 ptid = (uint16_t *)&fw_ddb_entry->isid[1];2030 *ptid = cpu_to_le16((uint16_t)ddb_entry->sess->target_id);2031 2032 DEBUG2(ql4_printk(KERN_INFO, ha, "ISID [%pmR]\n", fw_ddb_entry->isid));2033 2034 iscsi_opts = le16_to_cpu(fw_ddb_entry->iscsi_options);2035 memset(fw_ddb_entry->iscsi_alias, 0, sizeof(fw_ddb_entry->iscsi_alias));2036 2037 memset(fw_ddb_entry->iscsi_name, 0, sizeof(fw_ddb_entry->iscsi_name));2038 2039 if (sess->targetname != NULL) {2040 memcpy(fw_ddb_entry->iscsi_name, sess->targetname,2041 min(strlen(sess->targetname),2042 sizeof(fw_ddb_entry->iscsi_name)));2043 }2044 2045 memset(fw_ddb_entry->ip_addr, 0, sizeof(fw_ddb_entry->ip_addr));2046 memset(fw_ddb_entry->tgt_addr, 0, sizeof(fw_ddb_entry->tgt_addr));2047 2048 fw_ddb_entry->options = DDB_OPT_TARGET | DDB_OPT_AUTO_SENDTGTS_DISABLE;2049 2050 if (dst_addr->sa_family == AF_INET) {2051 addr = (struct sockaddr_in *)dst_addr;2052 ip = (char *)&addr->sin_addr;2053 memcpy(fw_ddb_entry->ip_addr, ip, IP_ADDR_LEN);2054 fw_ddb_entry->port = cpu_to_le16(ntohs(addr->sin_port));2055 DEBUG2(ql4_printk(KERN_INFO, ha,2056 "%s: Destination Address [%pI4]: index [%d]\n",2057 __func__, fw_ddb_entry->ip_addr,2058 ddb_entry->fw_ddb_index));2059 } else if (dst_addr->sa_family == AF_INET6) {2060 addr6 = (struct sockaddr_in6 *)dst_addr;2061 ip = (char *)&addr6->sin6_addr;2062 memcpy(fw_ddb_entry->ip_addr, ip, IPv6_ADDR_LEN);2063 fw_ddb_entry->port = cpu_to_le16(ntohs(addr6->sin6_port));2064 fw_ddb_entry->options |= DDB_OPT_IPV6_DEVICE;2065 DEBUG2(ql4_printk(KERN_INFO, ha,2066 "%s: Destination Address [%pI6]: index [%d]\n",2067 __func__, fw_ddb_entry->ip_addr,2068 ddb_entry->fw_ddb_index));2069 } else {2070 ql4_printk(KERN_ERR, ha,2071 "%s: Failed to get IP Address\n",2072 __func__);2073 rval = -EINVAL;2074 goto exit_set_param;2075 }2076 2077 /* CHAP */2078 if (sess->username != NULL && sess->password != NULL) {2079 if (strlen(sess->username) && strlen(sess->password)) {2080 iscsi_opts |= BIT_7;2081 2082 rval = qla4xxx_get_chap_index(ha, sess->username,2083 sess->password,2084 LOCAL_CHAP, &idx);2085 if (rval)2086 goto exit_set_param;2087 2088 fw_ddb_entry->chap_tbl_idx = cpu_to_le16(idx);2089 }2090 }2091 2092 if (sess->username_in != NULL && sess->password_in != NULL) {2093 /* Check if BIDI CHAP */2094 if (strlen(sess->username_in) && strlen(sess->password_in)) {2095 iscsi_opts |= BIT_4;2096 2097 rval = qla4xxx_get_chap_index(ha, sess->username_in,2098 sess->password_in,2099 BIDI_CHAP, &idx);2100 if (rval)2101 goto exit_set_param;2102 }2103 }2104 2105 if (sess->initial_r2t_en)2106 iscsi_opts |= BIT_10;2107 2108 if (sess->imm_data_en)2109 iscsi_opts |= BIT_11;2110 2111 fw_ddb_entry->iscsi_options = cpu_to_le16(iscsi_opts);2112 2113 if (conn->max_recv_dlength)2114 fw_ddb_entry->iscsi_max_rcv_data_seg_len =2115 cpu_to_le16((conn->max_recv_dlength / BYTE_UNITS));2116 2117 if (sess->max_r2t)2118 fw_ddb_entry->iscsi_max_outsnd_r2t = cpu_to_le16(sess->max_r2t);2119 2120 if (sess->first_burst)2121 fw_ddb_entry->iscsi_first_burst_len =2122 cpu_to_le16((sess->first_burst / BYTE_UNITS));2123 2124 if (sess->max_burst)2125 fw_ddb_entry->iscsi_max_burst_len =2126 cpu_to_le16((sess->max_burst / BYTE_UNITS));2127 2128 if (sess->time2wait)2129 fw_ddb_entry->iscsi_def_time2wait =2130 cpu_to_le16(sess->time2wait);2131 2132 if (sess->time2retain)2133 fw_ddb_entry->iscsi_def_time2retain =2134 cpu_to_le16(sess->time2retain);2135 2136 status = qla4xxx_set_ddb_entry(ha, ddb_entry->fw_ddb_index,2137 fw_ddb_entry_dma, mbx_sts);2138 2139 if (status != QLA_SUCCESS)2140 rval = -EINVAL;2141exit_set_param:2142 dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),2143 fw_ddb_entry, fw_ddb_entry_dma);2144exit_set_param_no_free:2145 return rval;2146}2147 2148int qla4xxx_get_mgmt_data(struct scsi_qla_host *ha, uint16_t fw_ddb_index,2149 uint16_t stats_size, dma_addr_t stats_dma)2150{2151 int status = QLA_SUCCESS;2152 uint32_t mbox_cmd[MBOX_REG_COUNT];2153 uint32_t mbox_sts[MBOX_REG_COUNT];2154 2155 memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT);2156 memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT);2157 mbox_cmd[0] = MBOX_CMD_GET_MANAGEMENT_DATA;2158 mbox_cmd[1] = fw_ddb_index;2159 mbox_cmd[2] = LSDW(stats_dma);2160 mbox_cmd[3] = MSDW(stats_dma);2161 mbox_cmd[4] = stats_size;2162 2163 status = qla4xxx_mailbox_command(ha, 5, 1, &mbox_cmd[0], &mbox_sts[0]);2164 if (status != QLA_SUCCESS) {2165 DEBUG2(ql4_printk(KERN_WARNING, ha,2166 "%s: MBOX_CMD_GET_MANAGEMENT_DATA "2167 "failed w/ status %04X\n", __func__,2168 mbox_sts[0]));2169 }2170 return status;2171}2172 2173int qla4xxx_get_ip_state(struct scsi_qla_host *ha, uint32_t acb_idx,2174 uint32_t ip_idx, uint32_t *sts)2175{2176 uint32_t mbox_cmd[MBOX_REG_COUNT];2177 uint32_t mbox_sts[MBOX_REG_COUNT];2178 int status = QLA_SUCCESS;2179 2180 memset(&mbox_cmd, 0, sizeof(mbox_cmd));2181 memset(&mbox_sts, 0, sizeof(mbox_sts));2182 mbox_cmd[0] = MBOX_CMD_GET_IP_ADDR_STATE;2183 mbox_cmd[1] = acb_idx;2184 mbox_cmd[2] = ip_idx;2185 2186 status = qla4xxx_mailbox_command(ha, 3, 8, &mbox_cmd[0], &mbox_sts[0]);2187 if (status != QLA_SUCCESS) {2188 DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: "2189 "MBOX_CMD_GET_IP_ADDR_STATE failed w/ "2190 "status %04X\n", __func__, mbox_sts[0]));2191 }2192 memcpy(sts, mbox_sts, sizeof(mbox_sts));2193 return status;2194}2195 2196int qla4xxx_get_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma,2197 uint32_t offset, uint32_t size)2198{2199 int status = QLA_SUCCESS;2200 uint32_t mbox_cmd[MBOX_REG_COUNT];2201 uint32_t mbox_sts[MBOX_REG_COUNT];2202 2203 memset(&mbox_cmd, 0, sizeof(mbox_cmd));2204 memset(&mbox_sts, 0, sizeof(mbox_sts));2205 2206 mbox_cmd[0] = MBOX_CMD_GET_NVRAM;2207 mbox_cmd[1] = LSDW(nvram_dma);2208 mbox_cmd[2] = MSDW(nvram_dma);2209 mbox_cmd[3] = offset;2210 mbox_cmd[4] = size;2211 2212 status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],2213 &mbox_sts[0]);2214 if (status != QLA_SUCCESS) {2215 DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed "2216 "status %04X\n", ha->host_no, __func__,2217 mbox_sts[0]));2218 }2219 return status;2220}2221 2222int qla4xxx_set_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma,2223 uint32_t offset, uint32_t size)2224{2225 int status = QLA_SUCCESS;2226 uint32_t mbox_cmd[MBOX_REG_COUNT];2227 uint32_t mbox_sts[MBOX_REG_COUNT];2228 2229 memset(&mbox_cmd, 0, sizeof(mbox_cmd));2230 memset(&mbox_sts, 0, sizeof(mbox_sts));2231 2232 mbox_cmd[0] = MBOX_CMD_SET_NVRAM;2233 mbox_cmd[1] = LSDW(nvram_dma);2234 mbox_cmd[2] = MSDW(nvram_dma);2235 mbox_cmd[3] = offset;2236 mbox_cmd[4] = size;2237 2238 status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],2239 &mbox_sts[0]);2240 if (status != QLA_SUCCESS) {2241 DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed "2242 "status %04X\n", ha->host_no, __func__,2243 mbox_sts[0]));2244 }2245 return status;2246}2247 2248int qla4xxx_restore_factory_defaults(struct scsi_qla_host *ha,2249 uint32_t region, uint32_t field0,2250 uint32_t field1)2251{2252 int status = QLA_SUCCESS;2253 uint32_t mbox_cmd[MBOX_REG_COUNT];2254 uint32_t mbox_sts[MBOX_REG_COUNT];2255 2256 memset(&mbox_cmd, 0, sizeof(mbox_cmd));2257 memset(&mbox_sts, 0, sizeof(mbox_sts));2258 2259 mbox_cmd[0] = MBOX_CMD_RESTORE_FACTORY_DEFAULTS;2260 mbox_cmd[3] = region;2261 mbox_cmd[4] = field0;2262 mbox_cmd[5] = field1;2263 2264 status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0],2265 &mbox_sts[0]);2266 if (status != QLA_SUCCESS) {2267 DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed "2268 "status %04X\n", ha->host_no, __func__,2269 mbox_sts[0]));2270 }2271 return status;2272}2273 2274/**2275 * qla4_8xxx_set_param - set driver version in firmware.2276 * @ha: Pointer to host adapter structure.2277 * @param: Parameter to set i.e driver version2278 **/2279int qla4_8xxx_set_param(struct scsi_qla_host *ha, int param)2280{2281 uint32_t mbox_cmd[MBOX_REG_COUNT];2282 uint32_t mbox_sts[MBOX_REG_COUNT];2283 uint32_t status;2284 2285 memset(&mbox_cmd, 0, sizeof(mbox_cmd));2286 memset(&mbox_sts, 0, sizeof(mbox_sts));2287 2288 mbox_cmd[0] = MBOX_CMD_SET_PARAM;2289 if (param == SET_DRVR_VERSION) {2290 mbox_cmd[1] = SET_DRVR_VERSION;2291 strscpy((char *)&mbox_cmd[2], QLA4XXX_DRIVER_VERSION,2292 MAX_DRVR_VER_LEN);2293 } else {2294 ql4_printk(KERN_ERR, ha, "%s: invalid parameter 0x%x\n",2295 __func__, param);2296 status = QLA_ERROR;2297 goto exit_set_param;2298 }2299 2300 status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, mbox_cmd,2301 mbox_sts);2302 if (status == QLA_ERROR)2303 ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n",2304 __func__, mbox_sts[0]);2305 2306exit_set_param:2307 return status;2308}2309 2310/**2311 * qla4_83xx_post_idc_ack - post IDC ACK2312 * @ha: Pointer to host adapter structure.2313 *2314 * Posts IDC ACK for IDC Request Notification AEN.2315 **/2316int qla4_83xx_post_idc_ack(struct scsi_qla_host *ha)2317{2318 uint32_t mbox_cmd[MBOX_REG_COUNT];2319 uint32_t mbox_sts[MBOX_REG_COUNT];2320 int status;2321 2322 memset(&mbox_cmd, 0, sizeof(mbox_cmd));2323 memset(&mbox_sts, 0, sizeof(mbox_sts));2324 2325 mbox_cmd[0] = MBOX_CMD_IDC_ACK;2326 mbox_cmd[1] = ha->idc_info.request_desc;2327 mbox_cmd[2] = ha->idc_info.info1;2328 mbox_cmd[3] = ha->idc_info.info2;2329 mbox_cmd[4] = ha->idc_info.info3;2330 2331 status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT,2332 mbox_cmd, mbox_sts);2333 if (status == QLA_ERROR)2334 ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n", __func__,2335 mbox_sts[0]);2336 else2337 ql4_printk(KERN_INFO, ha, "%s: IDC ACK posted\n", __func__);2338 2339 return status;2340}2341 2342int qla4_84xx_config_acb(struct scsi_qla_host *ha, int acb_config)2343{2344 uint32_t mbox_cmd[MBOX_REG_COUNT];2345 uint32_t mbox_sts[MBOX_REG_COUNT];2346 struct addr_ctrl_blk *acb = NULL;2347 uint32_t acb_len = sizeof(struct addr_ctrl_blk);2348 int rval = QLA_SUCCESS;2349 dma_addr_t acb_dma;2350 2351 acb = dma_alloc_coherent(&ha->pdev->dev,2352 sizeof(struct addr_ctrl_blk),2353 &acb_dma, GFP_KERNEL);2354 if (!acb) {2355 ql4_printk(KERN_ERR, ha, "%s: Unable to alloc acb\n", __func__);2356 rval = QLA_ERROR;2357 goto exit_config_acb;2358 }2359 memset(acb, 0, acb_len);2360 2361 switch (acb_config) {2362 case ACB_CONFIG_DISABLE:2363 rval = qla4xxx_get_acb(ha, acb_dma, 0, acb_len);2364 if (rval != QLA_SUCCESS)2365 goto exit_free_acb;2366 2367 rval = qla4xxx_disable_acb(ha);2368 if (rval != QLA_SUCCESS)2369 goto exit_free_acb;2370 2371 if (!ha->saved_acb)2372 ha->saved_acb = kzalloc(acb_len, GFP_KERNEL);2373 2374 if (!ha->saved_acb) {2375 ql4_printk(KERN_ERR, ha, "%s: Unable to alloc acb\n",2376 __func__);2377 rval = QLA_ERROR;2378 goto exit_free_acb;2379 }2380 memcpy(ha->saved_acb, acb, acb_len);2381 break;2382 case ACB_CONFIG_SET:2383 2384 if (!ha->saved_acb) {2385 ql4_printk(KERN_ERR, ha, "%s: Can't set ACB, Saved ACB not available\n",2386 __func__);2387 rval = QLA_ERROR;2388 goto exit_free_acb;2389 }2390 2391 memcpy(acb, ha->saved_acb, acb_len);2392 2393 rval = qla4xxx_set_acb(ha, &mbox_cmd[0], &mbox_sts[0], acb_dma);2394 if (rval != QLA_SUCCESS)2395 goto exit_free_acb;2396 2397 break;2398 default:2399 ql4_printk(KERN_ERR, ha, "%s: Invalid ACB Configuration\n",2400 __func__);2401 }2402 2403exit_free_acb:2404 dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk), acb,2405 acb_dma);2406exit_config_acb:2407 if ((acb_config == ACB_CONFIG_SET) && ha->saved_acb) {2408 kfree(ha->saved_acb);2409 ha->saved_acb = NULL;2410 }2411 DEBUG2(ql4_printk(KERN_INFO, ha,2412 "%s %s\n", __func__,2413 rval == QLA_SUCCESS ? "SUCCEEDED" : "FAILED"));2414 return rval;2415}2416 2417int qla4_83xx_get_port_config(struct scsi_qla_host *ha, uint32_t *config)2418{2419 uint32_t mbox_cmd[MBOX_REG_COUNT];2420 uint32_t mbox_sts[MBOX_REG_COUNT];2421 int status;2422 2423 memset(&mbox_cmd, 0, sizeof(mbox_cmd));2424 memset(&mbox_sts, 0, sizeof(mbox_sts));2425 2426 mbox_cmd[0] = MBOX_CMD_GET_PORT_CONFIG;2427 2428 status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT,2429 mbox_cmd, mbox_sts);2430 if (status == QLA_SUCCESS)2431 *config = mbox_sts[1];2432 else2433 ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n", __func__,2434 mbox_sts[0]);2435 2436 return status;2437}2438 2439int qla4_83xx_set_port_config(struct scsi_qla_host *ha, uint32_t *config)2440{2441 uint32_t mbox_cmd[MBOX_REG_COUNT];2442 uint32_t mbox_sts[MBOX_REG_COUNT];2443 int status;2444 2445 memset(&mbox_cmd, 0, sizeof(mbox_cmd));2446 memset(&mbox_sts, 0, sizeof(mbox_sts));2447 2448 mbox_cmd[0] = MBOX_CMD_SET_PORT_CONFIG;2449 mbox_cmd[1] = *config;2450 2451 status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT,2452 mbox_cmd, mbox_sts);2453 if (status != QLA_SUCCESS)2454 ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n", __func__,2455 mbox_sts[0]);2456 2457 return status;2458}2459