123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930 |
- /*
- * QLogic iSCSI HBA Driver
- * Copyright (c) 2003-2006 QLogic Corporation
- *
- * See LICENSE.qla4xxx for copyright and licensing details.
- */
- #include "ql4_def.h"
- /**
- * qla4xxx_mailbox_command - issues mailbox commands
- * @ha: Pointer to host adapter structure.
- * @inCount: number of mailbox registers to load.
- * @outCount: number of mailbox registers to return.
- * @mbx_cmd: data pointer for mailbox in registers.
- * @mbx_sts: data pointer for mailbox out registers.
- *
- * This routine sssue mailbox commands and waits for completion.
- * If outCount is 0, this routine completes successfully WITHOUT waiting
- * for the mailbox command to complete.
- **/
- int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
- uint8_t outCount, uint32_t *mbx_cmd,
- uint32_t *mbx_sts)
- {
- int status = QLA_ERROR;
- uint8_t i;
- u_long wait_count;
- uint32_t intr_status;
- unsigned long flags = 0;
- DECLARE_WAITQUEUE(wait, current);
- mutex_lock(&ha->mbox_sem);
- /* Mailbox code active */
- set_bit(AF_MBOX_COMMAND, &ha->flags);
- /* Make sure that pointers are valid */
- if (!mbx_cmd || !mbx_sts) {
- DEBUG2(printk("scsi%ld: %s: Invalid mbx_cmd or mbx_sts "
- "pointer\n", ha->host_no, __func__));
- goto mbox_exit;
- }
- /* To prevent overwriting mailbox registers for a command that has
- * not yet been serviced, check to see if a previously issued
- * mailbox command is interrupting.
- * -----------------------------------------------------------------
- */
- spin_lock_irqsave(&ha->hardware_lock, flags);
- intr_status = readl(&ha->reg->ctrl_status);
- if (intr_status & CSR_SCSI_PROCESSOR_INTR) {
- /* Service existing interrupt */
- qla4xxx_interrupt_service_routine(ha, intr_status);
- clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
- }
- /* Send the mailbox command to the firmware */
- ha->mbox_status_count = outCount;
- for (i = 0; i < outCount; i++)
- ha->mbox_status[i] = 0;
- /* Load all mailbox registers, except mailbox 0. */
- for (i = 1; i < inCount; i++)
- writel(mbx_cmd[i], &ha->reg->mailbox[i]);
- /* Wakeup firmware */
- writel(mbx_cmd[0], &ha->reg->mailbox[0]);
- readl(&ha->reg->mailbox[0]);
- writel(set_rmask(CSR_INTR_RISC), &ha->reg->ctrl_status);
- readl(&ha->reg->ctrl_status);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
- /* Wait for completion */
- set_current_state(TASK_UNINTERRUPTIBLE);
- add_wait_queue(&ha->mailbox_wait_queue, &wait);
- /*
- * If we don't want status, don't wait for the mailbox command to
- * complete. For example, MBOX_CMD_RESET_FW doesn't return status,
- * you must poll the inbound Interrupt Mask for completion.
- */
- if (outCount == 0) {
- status = QLA_SUCCESS;
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&ha->mailbox_wait_queue, &wait);
- goto mbox_exit;
- }
- /* Wait for command to complete */
- wait_count = jiffies + MBOX_TOV * HZ;
- while (test_bit(AF_MBOX_COMMAND_DONE, &ha->flags) == 0) {
- if (time_after_eq(jiffies, wait_count))
- break;
- spin_lock_irqsave(&ha->hardware_lock, flags);
- intr_status = readl(&ha->reg->ctrl_status);
- if (intr_status & INTR_PENDING) {
- /*
- * Service the interrupt.
- * The ISR will save the mailbox status registers
- * to a temporary storage location in the adapter
- * structure.
- */
- ha->mbox_status_count = outCount;
- qla4xxx_interrupt_service_routine(ha, intr_status);
- }
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
- msleep(10);
- }
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&ha->mailbox_wait_queue, &wait);
- /* Check for mailbox timeout. */
- if (!test_bit(AF_MBOX_COMMAND_DONE, &ha->flags)) {
- DEBUG2(printk("scsi%ld: Mailbox Cmd 0x%08X timed out ...,"
- " Scheduling Adapter Reset\n", ha->host_no,
- mbx_cmd[0]));
- ha->mailbox_timeout_count++;
- mbx_sts[0] = (-1);
- set_bit(DPC_RESET_HA, &ha->dpc_flags);
- goto mbox_exit;
- }
- /*
- * Copy the mailbox out registers to the caller's mailbox in/out
- * structure.
- */
- spin_lock_irqsave(&ha->hardware_lock, flags);
- for (i = 0; i < outCount; i++)
- mbx_sts[i] = ha->mbox_status[i];
- /* Set return status and error flags (if applicable). */
- switch (ha->mbox_status[0]) {
- case MBOX_STS_COMMAND_COMPLETE:
- status = QLA_SUCCESS;
- break;
- case MBOX_STS_INTERMEDIATE_COMPLETION:
- status = QLA_SUCCESS;
- break;
- case MBOX_STS_BUSY:
- DEBUG2( printk("scsi%ld: %s: Cmd = %08X, ISP BUSY\n",
- ha->host_no, __func__, mbx_cmd[0]));
- ha->mailbox_timeout_count++;
- break;
- default:
- DEBUG2(printk("scsi%ld: %s: **** FAILED, cmd = %08X, "
- "sts = %08X ****\n", ha->host_no, __func__,
- mbx_cmd[0], mbx_sts[0]));
- break;
- }
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
- mbox_exit:
- clear_bit(AF_MBOX_COMMAND, &ha->flags);
- clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
- mutex_unlock(&ha->mbox_sem);
- return status;
- }
- /**
- * qla4xxx_issue_iocb - issue mailbox iocb command
- * @ha: adapter state pointer.
- * @buffer: buffer pointer.
- * @phys_addr: physical address of buffer.
- * @size: size of buffer.
- *
- * Issues iocbs via mailbox commands.
- * TARGET_QUEUE_LOCK must be released.
- * ADAPTER_STATE_LOCK must be released.
- **/
- int
- qla4xxx_issue_iocb(struct scsi_qla_host * ha, void *buffer,
- dma_addr_t phys_addr, size_t size)
- {
- uint32_t mbox_cmd[MBOX_REG_COUNT];
- uint32_t mbox_sts[MBOX_REG_COUNT];
- int status;
- memset(&mbox_cmd, 0, sizeof(mbox_cmd));
- memset(&mbox_sts, 0, sizeof(mbox_sts));
- mbox_cmd[0] = MBOX_CMD_EXECUTE_IOCB_A64;
- mbox_cmd[1] = 0;
- mbox_cmd[2] = LSDW(phys_addr);
- mbox_cmd[3] = MSDW(phys_addr);
- status = qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]);
- return status;
- }
- int qla4xxx_conn_close_sess_logout(struct scsi_qla_host * ha,
- uint16_t fw_ddb_index,
- uint16_t connection_id,
- uint16_t option)
- {
- uint32_t mbox_cmd[MBOX_REG_COUNT];
- uint32_t mbox_sts[MBOX_REG_COUNT];
- memset(&mbox_cmd, 0, sizeof(mbox_cmd));
- memset(&mbox_sts, 0, sizeof(mbox_sts));
- mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT;
- mbox_cmd[1] = fw_ddb_index;
- mbox_cmd[2] = connection_id;
- mbox_cmd[3] = LOGOUT_OPTION_RELOGIN;
- if (qla4xxx_mailbox_command(ha, 4, 2, &mbox_cmd[0], &mbox_sts[0]) !=
- QLA_SUCCESS) {
- DEBUG2(printk("scsi%ld: %s: MBOX_CMD_CONN_CLOSE_SESS_LOGOUT "
- "option %04x failed sts %04X %04X",
- ha->host_no, __func__,
- option, mbox_sts[0], mbox_sts[1]));
- if (mbox_sts[0] == 0x4005)
- DEBUG2(printk("%s reason %04X\n", __func__,
- mbox_sts[1]));
- }
- return QLA_SUCCESS;
- }
- int qla4xxx_clear_database_entry(struct scsi_qla_host * ha,
- uint16_t fw_ddb_index)
- {
- uint32_t mbox_cmd[MBOX_REG_COUNT];
- uint32_t mbox_sts[MBOX_REG_COUNT];
- memset(&mbox_cmd, 0, sizeof(mbox_cmd));
- memset(&mbox_sts, 0, sizeof(mbox_sts));
- mbox_cmd[0] = MBOX_CMD_CLEAR_DATABASE_ENTRY;
- mbox_cmd[1] = fw_ddb_index;
- if (qla4xxx_mailbox_command(ha, 2, 5, &mbox_cmd[0], &mbox_sts[0]) !=
- QLA_SUCCESS)
- return QLA_ERROR;
- return QLA_SUCCESS;
- }
- /**
- * qla4xxx_initialize_fw_cb - initializes firmware control block.
- * @ha: Pointer to host adapter structure.
- **/
- int qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha)
- {
- struct init_fw_ctrl_blk *init_fw_cb;
- dma_addr_t init_fw_cb_dma;
- uint32_t mbox_cmd[MBOX_REG_COUNT];
- uint32_t mbox_sts[MBOX_REG_COUNT];
- int status = QLA_ERROR;
- init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
- sizeof(struct init_fw_ctrl_blk),
- &init_fw_cb_dma, GFP_KERNEL);
- if (init_fw_cb == NULL) {
- DEBUG2(printk("scsi%ld: %s: Unable to alloc init_cb\n",
- ha->host_no, __func__));
- return 10;
- }
- memset(init_fw_cb, 0, sizeof(struct init_fw_ctrl_blk));
- /* Get Initialize Firmware Control Block. */
- memset(&mbox_cmd, 0, sizeof(mbox_cmd));
- memset(&mbox_sts, 0, sizeof(mbox_sts));
- mbox_cmd[0] = MBOX_CMD_GET_INIT_FW_CTRL_BLOCK;
- mbox_cmd[2] = LSDW(init_fw_cb_dma);
- mbox_cmd[3] = MSDW(init_fw_cb_dma);
- if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) !=
- QLA_SUCCESS) {
- dma_free_coherent(&ha->pdev->dev,
- sizeof(struct init_fw_ctrl_blk),
- init_fw_cb, init_fw_cb_dma);
- return status;
- }
- /* Initialize request and response queues. */
- qla4xxx_init_rings(ha);
- /* Fill in the request and response queue information. */
- init_fw_cb->ReqQConsumerIndex = cpu_to_le16(ha->request_out);
- init_fw_cb->ComplQProducerIndex = cpu_to_le16(ha->response_in);
- init_fw_cb->ReqQLen = __constant_cpu_to_le16(REQUEST_QUEUE_DEPTH);
- init_fw_cb->ComplQLen = __constant_cpu_to_le16(RESPONSE_QUEUE_DEPTH);
- init_fw_cb->ReqQAddrLo = cpu_to_le32(LSDW(ha->request_dma));
- init_fw_cb->ReqQAddrHi = cpu_to_le32(MSDW(ha->request_dma));
- init_fw_cb->ComplQAddrLo = cpu_to_le32(LSDW(ha->response_dma));
- init_fw_cb->ComplQAddrHi = cpu_to_le32(MSDW(ha->response_dma));
- init_fw_cb->ShadowRegBufAddrLo =
- cpu_to_le32(LSDW(ha->shadow_regs_dma));
- init_fw_cb->ShadowRegBufAddrHi =
- cpu_to_le32(MSDW(ha->shadow_regs_dma));
- /* Set up required options. */
- init_fw_cb->FwOptions |=
- __constant_cpu_to_le16(FWOPT_SESSION_MODE |
- FWOPT_INITIATOR_MODE);
- init_fw_cb->FwOptions &= __constant_cpu_to_le16(~FWOPT_TARGET_MODE);
- /* Save some info in adapter structure. */
- ha->firmware_options = le16_to_cpu(init_fw_cb->FwOptions);
- ha->tcp_options = le16_to_cpu(init_fw_cb->TCPOptions);
- ha->heartbeat_interval = init_fw_cb->HeartbeatInterval;
- memcpy(ha->ip_address, init_fw_cb->IPAddr,
- min(sizeof(ha->ip_address), sizeof(init_fw_cb->IPAddr)));
- memcpy(ha->subnet_mask, init_fw_cb->SubnetMask,
- min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->SubnetMask)));
- memcpy(ha->gateway, init_fw_cb->GatewayIPAddr,
- min(sizeof(ha->gateway), sizeof(init_fw_cb->GatewayIPAddr)));
- memcpy(ha->name_string, init_fw_cb->iSCSINameString,
- min(sizeof(ha->name_string),
- sizeof(init_fw_cb->iSCSINameString)));
- memcpy(ha->alias, init_fw_cb->Alias,
- min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));
- /* Save Command Line Paramater info */
- ha->port_down_retry_count = le16_to_cpu(init_fw_cb->KeepAliveTimeout);
- ha->discovery_wait = ql4xdiscoverywait;
- /* Send Initialize Firmware Control Block. */
- mbox_cmd[0] = MBOX_CMD_INITIALIZE_FIRMWARE;
- mbox_cmd[1] = 0;
- mbox_cmd[2] = LSDW(init_fw_cb_dma);
- mbox_cmd[3] = MSDW(init_fw_cb_dma);
- if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) ==
- QLA_SUCCESS)
- status = QLA_SUCCESS;
- else {
- DEBUG2(printk("scsi%ld: %s: MBOX_CMD_INITIALIZE_FIRMWARE "
- "failed w/ status %04X\n", ha->host_no, __func__,
- mbox_sts[0]));
- }
- dma_free_coherent(&ha->pdev->dev, sizeof(struct init_fw_ctrl_blk),
- init_fw_cb, init_fw_cb_dma);
- return status;
- }
- /**
- * qla4xxx_get_dhcp_ip_address - gets HBA ip address via DHCP
- * @ha: Pointer to host adapter structure.
- **/
- int qla4xxx_get_dhcp_ip_address(struct scsi_qla_host * ha)
- {
- struct init_fw_ctrl_blk *init_fw_cb;
- dma_addr_t init_fw_cb_dma;
- uint32_t mbox_cmd[MBOX_REG_COUNT];
- uint32_t mbox_sts[MBOX_REG_COUNT];
- init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
- sizeof(struct init_fw_ctrl_blk),
- &init_fw_cb_dma, GFP_KERNEL);
- if (init_fw_cb == NULL) {
- printk("scsi%ld: %s: Unable to alloc init_cb\n", ha->host_no,
- __func__);
- return 10;
- }
- /* Get Initialize Firmware Control Block. */
- memset(&mbox_cmd, 0, sizeof(mbox_cmd));
- memset(&mbox_sts, 0, sizeof(mbox_sts));
- memset(init_fw_cb, 0, sizeof(struct init_fw_ctrl_blk));
- mbox_cmd[0] = MBOX_CMD_GET_INIT_FW_CTRL_BLOCK;
- mbox_cmd[2] = LSDW(init_fw_cb_dma);
- mbox_cmd[3] = MSDW(init_fw_cb_dma);
- if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) !=
- QLA_SUCCESS) {
- DEBUG2(printk("scsi%ld: %s: Failed to get init_fw_ctrl_blk\n",
- ha->host_no, __func__));
- dma_free_coherent(&ha->pdev->dev,
- sizeof(struct init_fw_ctrl_blk),
- init_fw_cb, init_fw_cb_dma);
- return QLA_ERROR;
- }
- /* Save IP Address. */
- memcpy(ha->ip_address, init_fw_cb->IPAddr,
- min(sizeof(ha->ip_address), sizeof(init_fw_cb->IPAddr)));
- memcpy(ha->subnet_mask, init_fw_cb->SubnetMask,
- min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->SubnetMask)));
- memcpy(ha->gateway, init_fw_cb->GatewayIPAddr,
- min(sizeof(ha->gateway), sizeof(init_fw_cb->GatewayIPAddr)));
- dma_free_coherent(&ha->pdev->dev, sizeof(struct init_fw_ctrl_blk),
- init_fw_cb, init_fw_cb_dma);
- return QLA_SUCCESS;
- }
- /**
- * qla4xxx_get_firmware_state - gets firmware state of HBA
- * @ha: Pointer to host adapter structure.
- **/
- int qla4xxx_get_firmware_state(struct scsi_qla_host * ha)
- {
- uint32_t mbox_cmd[MBOX_REG_COUNT];
- uint32_t mbox_sts[MBOX_REG_COUNT];
- /* Get firmware version */
- memset(&mbox_cmd, 0, sizeof(mbox_cmd));
- memset(&mbox_sts, 0, sizeof(mbox_sts));
- mbox_cmd[0] = MBOX_CMD_GET_FW_STATE;
- if (qla4xxx_mailbox_command(ha, 1, 4, &mbox_cmd[0], &mbox_sts[0]) !=
- QLA_SUCCESS) {
- DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATE failed w/ "
- "status %04X\n", ha->host_no, __func__,
- mbox_sts[0]));
- return QLA_ERROR;
- }
- ha->firmware_state = mbox_sts[1];
- ha->board_id = mbox_sts[2];
- ha->addl_fw_state = mbox_sts[3];
- DEBUG2(printk("scsi%ld: %s firmware_state=0x%x\n",
- ha->host_no, __func__, ha->firmware_state);)
- return QLA_SUCCESS;
- }
- /**
- * qla4xxx_get_firmware_status - retrieves firmware status
- * @ha: Pointer to host adapter structure.
- **/
- int qla4xxx_get_firmware_status(struct scsi_qla_host * ha)
- {
- uint32_t mbox_cmd[MBOX_REG_COUNT];
- uint32_t mbox_sts[MBOX_REG_COUNT];
- /* Get firmware version */
- memset(&mbox_cmd, 0, sizeof(mbox_cmd));
- memset(&mbox_sts, 0, sizeof(mbox_sts));
- mbox_cmd[0] = MBOX_CMD_GET_FW_STATUS;
- if (qla4xxx_mailbox_command(ha, 1, 3, &mbox_cmd[0], &mbox_sts[0]) !=
- QLA_SUCCESS) {
- DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATUS failed w/ "
- "status %04X\n", ha->host_no, __func__,
- mbox_sts[0]));
- return QLA_ERROR;
- }
- /* High-water mark of IOCBs */
- ha->iocb_hiwat = mbox_sts[2];
- if (ha->iocb_hiwat > IOCB_HIWAT_CUSHION)
- ha->iocb_hiwat -= IOCB_HIWAT_CUSHION;
- else
- dev_info(&ha->pdev->dev, "WARNING!!! You have less than %d "
- "firmare IOCBs available (%d).\n",
- IOCB_HIWAT_CUSHION, ha->iocb_hiwat);
- return QLA_SUCCESS;
- }
- /**
- * qla4xxx_get_fwddb_entry - retrieves firmware ddb entry
- * @ha: Pointer to host adapter structure.
- * @fw_ddb_index: Firmware's device database index
- * @fw_ddb_entry: Pointer to firmware's device database entry structure
- * @num_valid_ddb_entries: Pointer to number of valid ddb entries
- * @next_ddb_index: Pointer to next valid device database index
- * @fw_ddb_device_state: Pointer to device state
- **/
- int qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha,
- uint16_t fw_ddb_index,
- struct dev_db_entry *fw_ddb_entry,
- dma_addr_t fw_ddb_entry_dma,
- uint32_t *num_valid_ddb_entries,
- uint32_t *next_ddb_index,
- uint32_t *fw_ddb_device_state,
- uint32_t *conn_err_detail,
- uint16_t *tcp_source_port_num,
- uint16_t *connection_id)
- {
- int status = QLA_ERROR;
- uint32_t mbox_cmd[MBOX_REG_COUNT];
- uint32_t mbox_sts[MBOX_REG_COUNT];
- /* Make sure the device index is valid */
- if (fw_ddb_index >= MAX_DDB_ENTRIES) {
- DEBUG2(printk("scsi%ld: %s: index [%d] out of range.\n",
- ha->host_no, __func__, fw_ddb_index));
- goto exit_get_fwddb;
- }
- memset(&mbox_cmd, 0, sizeof(mbox_cmd));
- memset(&mbox_sts, 0, sizeof(mbox_sts));
- mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY;
- mbox_cmd[1] = (uint32_t) fw_ddb_index;
- mbox_cmd[2] = LSDW(fw_ddb_entry_dma);
- mbox_cmd[3] = MSDW(fw_ddb_entry_dma);
- if (qla4xxx_mailbox_command(ha, 4, 7, &mbox_cmd[0], &mbox_sts[0]) ==
- QLA_ERROR) {
- DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_DATABASE_ENTRY failed"
- " with status 0x%04X\n", ha->host_no, __func__,
- mbox_sts[0]));
- goto exit_get_fwddb;
- }
- if (fw_ddb_index != mbox_sts[1]) {
- DEBUG2(printk("scsi%ld: %s: index mismatch [%d] != [%d].\n",
- ha->host_no, __func__, fw_ddb_index,
- mbox_sts[1]));
- goto exit_get_fwddb;
- }
- if (fw_ddb_entry) {
- dev_info(&ha->pdev->dev, "DDB[%d] MB0 %04x Tot %d Next %d "
- "State %04x ConnErr %08x %d.%d.%d.%d:%04d \"%s\"\n",
- fw_ddb_index, mbox_sts[0], mbox_sts[2], mbox_sts[3],
- mbox_sts[4], mbox_sts[5], fw_ddb_entry->ipAddr[0],
- fw_ddb_entry->ipAddr[1], fw_ddb_entry->ipAddr[2],
- fw_ddb_entry->ipAddr[3],
- le16_to_cpu(fw_ddb_entry->portNumber),
- fw_ddb_entry->iscsiName);
- }
- if (num_valid_ddb_entries)
- *num_valid_ddb_entries = mbox_sts[2];
- if (next_ddb_index)
- *next_ddb_index = mbox_sts[3];
- if (fw_ddb_device_state)
- *fw_ddb_device_state = mbox_sts[4];
- /*
- * RA: This mailbox has been changed to pass connection error and
- * details. Its true for ISP4010 as per Version E - Not sure when it
- * was changed. Get the time2wait from the fw_dd_entry field :
- * default_time2wait which we call it as minTime2Wait DEV_DB_ENTRY
- * struct.
- */
- if (conn_err_detail)
- *conn_err_detail = mbox_sts[5];
- if (tcp_source_port_num)
- *tcp_source_port_num = (uint16_t) mbox_sts[6] >> 16;
- if (connection_id)
- *connection_id = (uint16_t) mbox_sts[6] & 0x00FF;
- status = QLA_SUCCESS;
- exit_get_fwddb:
- return status;
- }
- /**
- * qla4xxx_set_fwddb_entry - sets a ddb entry.
- * @ha: Pointer to host adapter structure.
- * @fw_ddb_index: Firmware's device database index
- * @fw_ddb_entry: Pointer to firmware's ddb entry structure, or NULL.
- *
- * This routine initializes or updates the adapter's device database
- * entry for the specified device. It also triggers a login for the
- * specified device. Therefore, it may also be used as a secondary
- * login routine when a NULL pointer is specified for the fw_ddb_entry.
- **/
- int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index,
- dma_addr_t fw_ddb_entry_dma)
- {
- uint32_t mbox_cmd[MBOX_REG_COUNT];
- uint32_t mbox_sts[MBOX_REG_COUNT];
- /* Do not wait for completion. The firmware will send us an
- * ASTS_DATABASE_CHANGED (0x8014) to notify us of the login status.
- */
- memset(&mbox_cmd, 0, sizeof(mbox_cmd));
- memset(&mbox_sts, 0, sizeof(mbox_sts));
- mbox_cmd[0] = MBOX_CMD_SET_DATABASE_ENTRY;
- mbox_cmd[1] = (uint32_t) fw_ddb_index;
- mbox_cmd[2] = LSDW(fw_ddb_entry_dma);
- mbox_cmd[3] = MSDW(fw_ddb_entry_dma);
- return qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]);
- }
- int qla4xxx_conn_open_session_login(struct scsi_qla_host * ha,
- uint16_t fw_ddb_index)
- {
- int status = QLA_ERROR;
- uint32_t mbox_cmd[MBOX_REG_COUNT];
- uint32_t mbox_sts[MBOX_REG_COUNT];
- /* Do not wait for completion. The firmware will send us an
- * ASTS_DATABASE_CHANGED (0x8014) to notify us of the login status.
- */
- memset(&mbox_cmd, 0, sizeof(mbox_cmd));
- memset(&mbox_sts, 0, sizeof(mbox_sts));
- mbox_cmd[0] = MBOX_CMD_CONN_OPEN_SESS_LOGIN;
- mbox_cmd[1] = (uint32_t) fw_ddb_index;
- mbox_cmd[2] = 0;
- mbox_cmd[3] = 0;
- mbox_cmd[4] = 0;
- status = qla4xxx_mailbox_command(ha, 4, 0, &mbox_cmd[0], &mbox_sts[0]);
- DEBUG2(printk("%s fw_ddb_index=%d status=%d mbx0_1=0x%x :0x%x\n",
- __func__, fw_ddb_index, status, mbox_sts[0],
- mbox_sts[1]);)
- return status;
- }
- /**
- * qla4xxx_get_crash_record - retrieves crash record.
- * @ha: Pointer to host adapter structure.
- *
- * This routine retrieves a crash record from the QLA4010 after an 8002h aen.
- **/
- void qla4xxx_get_crash_record(struct scsi_qla_host * ha)
- {
- uint32_t mbox_cmd[MBOX_REG_COUNT];
- uint32_t mbox_sts[MBOX_REG_COUNT];
- struct crash_record *crash_record = NULL;
- dma_addr_t crash_record_dma = 0;
- uint32_t crash_record_size = 0;
- memset(&mbox_cmd, 0, sizeof(mbox_cmd));
- memset(&mbox_sts, 0, sizeof(mbox_cmd));
- /* Get size of crash record. */
- mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD;
- if (qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]) !=
- QLA_SUCCESS) {
- DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve size!\n",
- ha->host_no, __func__));
- goto exit_get_crash_record;
- }
- crash_record_size = mbox_sts[4];
- if (crash_record_size == 0) {
- DEBUG2(printk("scsi%ld: %s: ERROR: Crash record size is 0!\n",
- ha->host_no, __func__));
- goto exit_get_crash_record;
- }
- /* Alloc Memory for Crash Record. */
- crash_record = dma_alloc_coherent(&ha->pdev->dev, crash_record_size,
- &crash_record_dma, GFP_KERNEL);
- if (crash_record == NULL)
- goto exit_get_crash_record;
- /* Get Crash Record. */
- mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD;
- mbox_cmd[2] = LSDW(crash_record_dma);
- mbox_cmd[3] = MSDW(crash_record_dma);
- mbox_cmd[4] = crash_record_size;
- if (qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]) !=
- QLA_SUCCESS)
- goto exit_get_crash_record;
- /* Dump Crash Record. */
- exit_get_crash_record:
- if (crash_record)
- dma_free_coherent(&ha->pdev->dev, crash_record_size,
- crash_record, crash_record_dma);
- }
- /**
- * qla4xxx_get_conn_event_log - retrieves connection event log
- * @ha: Pointer to host adapter structure.
- **/
- void qla4xxx_get_conn_event_log(struct scsi_qla_host * ha)
- {
- uint32_t mbox_cmd[MBOX_REG_COUNT];
- uint32_t mbox_sts[MBOX_REG_COUNT];
- struct conn_event_log_entry *event_log = NULL;
- dma_addr_t event_log_dma = 0;
- uint32_t event_log_size = 0;
- uint32_t num_valid_entries;
- uint32_t oldest_entry = 0;
- uint32_t max_event_log_entries;
- uint8_t i;
- memset(&mbox_cmd, 0, sizeof(mbox_cmd));
- memset(&mbox_sts, 0, sizeof(mbox_cmd));
- /* Get size of crash record. */
- mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG;
- if (qla4xxx_mailbox_command(ha, 4, 5, &mbox_cmd[0], &mbox_sts[0]) !=
- QLA_SUCCESS)
- goto exit_get_event_log;
- event_log_size = mbox_sts[4];
- if (event_log_size == 0)
- goto exit_get_event_log;
- /* Alloc Memory for Crash Record. */
- event_log = dma_alloc_coherent(&ha->pdev->dev, event_log_size,
- &event_log_dma, GFP_KERNEL);
- if (event_log == NULL)
- goto exit_get_event_log;
- /* Get Crash Record. */
- mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG;
- mbox_cmd[2] = LSDW(event_log_dma);
- mbox_cmd[3] = MSDW(event_log_dma);
- if (qla4xxx_mailbox_command(ha, 4, 5, &mbox_cmd[0], &mbox_sts[0]) !=
- QLA_SUCCESS) {
- DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve event "
- "log!\n", ha->host_no, __func__));
- goto exit_get_event_log;
- }
- /* Dump Event Log. */
- num_valid_entries = mbox_sts[1];
- max_event_log_entries = event_log_size /
- sizeof(struct conn_event_log_entry);
- if (num_valid_entries > max_event_log_entries)
- oldest_entry = num_valid_entries % max_event_log_entries;
- DEBUG3(printk("scsi%ld: Connection Event Log Dump (%d entries):\n",
- ha->host_no, num_valid_entries));
- if (qla4_extended_error_logging == 3) {
- if (oldest_entry == 0) {
- /* Circular Buffer has not wrapped around */
- for (i=0; i < num_valid_entries; i++) {
- qla4xxx_dump_buffer((uint8_t *)event_log+
- (i*sizeof(*event_log)),
- sizeof(*event_log));
- }
- }
- else {
- /* Circular Buffer has wrapped around -
- * display accordingly*/
- for (i=oldest_entry; i < max_event_log_entries; i++) {
- qla4xxx_dump_buffer((uint8_t *)event_log+
- (i*sizeof(*event_log)),
- sizeof(*event_log));
- }
- for (i=0; i < oldest_entry; i++) {
- qla4xxx_dump_buffer((uint8_t *)event_log+
- (i*sizeof(*event_log)),
- sizeof(*event_log));
- }
- }
- }
- exit_get_event_log:
- if (event_log)
- dma_free_coherent(&ha->pdev->dev, event_log_size, event_log,
- event_log_dma);
- }
- /**
- * qla4xxx_reset_lun - issues LUN Reset
- * @ha: Pointer to host adapter structure.
- * @db_entry: Pointer to device database entry
- * @un_entry: Pointer to lun entry structure
- *
- * This routine performs a LUN RESET on the specified target/lun.
- * The caller must ensure that the ddb_entry and lun_entry pointers
- * are valid before calling this routine.
- **/
- int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry,
- int lun)
- {
- uint32_t mbox_cmd[MBOX_REG_COUNT];
- uint32_t mbox_sts[MBOX_REG_COUNT];
- int status = QLA_SUCCESS;
- DEBUG2(printk("scsi%ld:%d:%d: lun reset issued\n", ha->host_no,
- ddb_entry->os_target_id, lun));
- /*
- * Send lun reset command to ISP, so that the ISP will return all
- * outstanding requests with RESET status
- */
- memset(&mbox_cmd, 0, sizeof(mbox_cmd));
- memset(&mbox_sts, 0, sizeof(mbox_sts));
- mbox_cmd[0] = MBOX_CMD_LUN_RESET;
- mbox_cmd[1] = ddb_entry->fw_ddb_index;
- mbox_cmd[2] = lun << 8;
- mbox_cmd[5] = 0x01; /* Immediate Command Enable */
- qla4xxx_mailbox_command(ha, 6, 1, &mbox_cmd[0], &mbox_sts[0]);
- if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE &&
- mbox_sts[0] != MBOX_STS_COMMAND_ERROR)
- status = QLA_ERROR;
- return status;
- }
- int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr,
- uint32_t offset, uint32_t len)
- {
- uint32_t mbox_cmd[MBOX_REG_COUNT];
- uint32_t mbox_sts[MBOX_REG_COUNT];
- memset(&mbox_cmd, 0, sizeof(mbox_cmd));
- memset(&mbox_sts, 0, sizeof(mbox_sts));
- mbox_cmd[0] = MBOX_CMD_READ_FLASH;
- mbox_cmd[1] = LSDW(dma_addr);
- mbox_cmd[2] = MSDW(dma_addr);
- mbox_cmd[3] = offset;
- mbox_cmd[4] = len;
- if (qla4xxx_mailbox_command(ha, 5, 2, &mbox_cmd[0], &mbox_sts[0]) !=
- QLA_SUCCESS) {
- DEBUG2(printk("scsi%ld: %s: MBOX_CMD_READ_FLASH, failed w/ "
- "status %04X %04X, offset %08x, len %08x\n", ha->host_no,
- __func__, mbox_sts[0], mbox_sts[1], offset, len));
- return QLA_ERROR;
- }
- return QLA_SUCCESS;
- }
- /**
- * qla4xxx_get_fw_version - gets firmware version
- * @ha: Pointer to host adapter structure.
- *
- * Retrieves the firmware version on HBA. In QLA4010, mailboxes 2 & 3 may
- * hold an address for data. Make sure that we write 0 to those mailboxes,
- * if unused.
- **/
- int qla4xxx_get_fw_version(struct scsi_qla_host * ha)
- {
- uint32_t mbox_cmd[MBOX_REG_COUNT];
- uint32_t mbox_sts[MBOX_REG_COUNT];
- /* Get firmware version. */
- memset(&mbox_cmd, 0, sizeof(mbox_cmd));
- memset(&mbox_sts, 0, sizeof(mbox_sts));
- mbox_cmd[0] = MBOX_CMD_ABOUT_FW;
- if (qla4xxx_mailbox_command(ha, 4, 5, &mbox_cmd[0], &mbox_sts[0]) !=
- QLA_SUCCESS) {
- DEBUG2(printk("scsi%ld: %s: MBOX_CMD_ABOUT_FW failed w/ "
- "status %04X\n", ha->host_no, __func__, mbox_sts[0]));
- return QLA_ERROR;
- }
- /* Save firmware version information. */
- ha->firmware_version[0] = mbox_sts[1];
- ha->firmware_version[1] = mbox_sts[2];
- ha->patch_number = mbox_sts[3];
- ha->build_number = mbox_sts[4];
- return QLA_SUCCESS;
- }
- int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, dma_addr_t dma_addr)
- {
- uint32_t mbox_cmd[MBOX_REG_COUNT];
- uint32_t mbox_sts[MBOX_REG_COUNT];
- memset(&mbox_cmd, 0, sizeof(mbox_cmd));
- memset(&mbox_sts, 0, sizeof(mbox_sts));
- mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY_DEFAULTS;
- mbox_cmd[2] = LSDW(dma_addr);
- mbox_cmd[3] = MSDW(dma_addr);
- if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) !=
- QLA_SUCCESS) {
- DEBUG2(printk("scsi%ld: %s: failed status %04X\n",
- ha->host_no, __func__, mbox_sts[0]));
- return QLA_ERROR;
- }
- return QLA_SUCCESS;
- }
- int qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t *ddb_index)
- {
- uint32_t mbox_cmd[MBOX_REG_COUNT];
- uint32_t mbox_sts[MBOX_REG_COUNT];
- memset(&mbox_cmd, 0, sizeof(mbox_cmd));
- memset(&mbox_sts, 0, sizeof(mbox_sts));
- mbox_cmd[0] = MBOX_CMD_REQUEST_DATABASE_ENTRY;
- mbox_cmd[1] = MAX_PRST_DEV_DB_ENTRIES;
- if (qla4xxx_mailbox_command(ha, 2, 3, &mbox_cmd[0], &mbox_sts[0]) !=
- QLA_SUCCESS) {
- if (mbox_sts[0] == MBOX_STS_COMMAND_ERROR) {
- *ddb_index = mbox_sts[2];
- } else {
- DEBUG2(printk("scsi%ld: %s: failed status %04X\n",
- ha->host_no, __func__, mbox_sts[0]));
- return QLA_ERROR;
- }
- } else {
- *ddb_index = MAX_PRST_DEV_DB_ENTRIES;
- }
- return QLA_SUCCESS;
- }
- int qla4xxx_send_tgts(struct scsi_qla_host *ha, char *ip, uint16_t port)
- {
- struct dev_db_entry *fw_ddb_entry;
- dma_addr_t fw_ddb_entry_dma;
- uint32_t ddb_index;
- int ret_val = QLA_SUCCESS;
- fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev,
- sizeof(*fw_ddb_entry),
- &fw_ddb_entry_dma, GFP_KERNEL);
- if (!fw_ddb_entry) {
- DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n",
- ha->host_no, __func__));
- ret_val = QLA_ERROR;
- goto qla4xxx_send_tgts_exit;
- }
- ret_val = qla4xxx_get_default_ddb(ha, fw_ddb_entry_dma);
- if (ret_val != QLA_SUCCESS)
- goto qla4xxx_send_tgts_exit;
- ret_val = qla4xxx_req_ddb_entry(ha, &ddb_index);
- if (ret_val != QLA_SUCCESS)
- goto qla4xxx_send_tgts_exit;
- memset((void *)fw_ddb_entry->iSCSIAlias, 0,
- sizeof(fw_ddb_entry->iSCSIAlias));
- memset((void *)fw_ddb_entry->iscsiName, 0,
- sizeof(fw_ddb_entry->iscsiName));
- memset((void *)fw_ddb_entry->ipAddr, 0, sizeof(fw_ddb_entry->ipAddr));
- memset((void *)fw_ddb_entry->targetAddr, 0,
- sizeof(fw_ddb_entry->targetAddr));
- fw_ddb_entry->options = (DDB_OPT_DISC_SESSION | DDB_OPT_TARGET);
- fw_ddb_entry->portNumber = cpu_to_le16(ntohs(port));
- fw_ddb_entry->ipAddr[0] = *ip;
- fw_ddb_entry->ipAddr[1] = *(ip + 1);
- fw_ddb_entry->ipAddr[2] = *(ip + 2);
- fw_ddb_entry->ipAddr[3] = *(ip + 3);
- ret_val = qla4xxx_set_ddb_entry(ha, ddb_index, fw_ddb_entry_dma);
- qla4xxx_send_tgts_exit:
- dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
- fw_ddb_entry, fw_ddb_entry_dma);
- return ret_val;
- }
|