void qla4xxx_process_mbox_intr(struct scsi_qla_host *ha, int out_count)
{ int intr_status;
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 = out_count;
ha->isp_ops->interrupt_service_routine(ha, intr_status);
}
}
/** * qla4xxx_is_intr_poll_mode - Are we allowed to poll for interrupts? * @ha: Pointer to host adapter structure. * returns: 1=polling mode, 0=non-polling mode
**/ staticint qla4xxx_is_intr_poll_mode(struct scsi_qla_host *ha)
{ int rval = 1;
/** * 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 issue 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; unsignedlong flags = 0;
uint32_t dev_state;
/* 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__)); return status;
}
if (is_qla40XX(ha)) { if (test_bit(AF_HA_REMOVAL, &ha->flags)) {
DEBUG2(ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: " "prematurely completing mbx cmd as " "adapter removal detected\n",
ha->host_no, __func__)); return status;
}
}
/* Mailbox code active */
wait_count = MBOX_TOV * 100;
while (wait_count--) {
mutex_lock(&ha->mbox_sem); if (!test_bit(AF_MBOX_COMMAND, &ha->flags)) {
set_bit(AF_MBOX_COMMAND, &ha->flags);
mutex_unlock(&ha->mbox_sem); break;
}
mutex_unlock(&ha->mbox_sem); if (!wait_count) {
DEBUG2(printk("scsi%ld: %s: mbox_sem failed\n",
ha->host_no, __func__)); return status;
}
msleep(10);
}
if (is_qla80XX(ha)) { if (test_bit(AF_FW_RECOVERY, &ha->flags)) {
DEBUG2(ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: prematurely completing mbx cmd as firmware recovery detected\n",
ha->host_no, __func__)); goto mbox_exit;
} /* Do not send any mbx cmd if h/w is in failed state*/
ha->isp_ops->idc_lock(ha);
dev_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DEV_STATE);
ha->isp_ops->idc_unlock(ha); if (dev_state == QLA8XXX_DEV_FAILED) {
ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: H/W is in failed state, do not send any mailbox commands\n",
ha->host_no, __func__); goto mbox_exit;
}
}
spin_lock_irqsave(&ha->hardware_lock, flags);
ha->mbox_status_count = outCount; for (i = 0; i < outCount; i++)
ha->mbox_status[i] = 0;
/* Queue the mailbox command to the firmware */
ha->isp_ops->queue_mailbox_command(ha, mbx_cmd, inCount);
/* * 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; goto mbox_exit;
}
/* * Wait for completion: Poll or completion queue
*/ if (qla4xxx_is_intr_poll_mode(ha)) { /* Poll 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; /* * Service the interrupt. * The ISR will save the mailbox status registers * to a temporary storage location in the adapter * structure.
*/
spin_lock_irqsave(&ha->hardware_lock, flags);
ha->isp_ops->process_mailbox_interrupt(ha, outCount);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
msleep(10);
}
} else { /* Do not poll for completion. Use completion queue */
set_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags);
wait_for_completion_timeout(&ha->mbx_intr_comp, MBOX_TOV * HZ);
clear_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags);
}
/* Check for mailbox timeout. */ if (!test_bit(AF_MBOX_COMMAND_DONE, &ha->flags)) { if (is_qla80XX(ha) &&
test_bit(AF_FW_RECOVERY, &ha->flags)) {
DEBUG2(ql4_printk(KERN_INFO, ha, "scsi%ld: %s: prematurely completing mbx cmd as " "firmware recovery detected\n",
ha->host_no, __func__)); goto mbox_exit;
}
ql4_printk(KERN_WARNING, ha, "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); if (is_qla8022(ha)) {
ql4_printk(KERN_INFO, ha, "disabling pause transmit on port 0 & 1.\n");
qla4_82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x98,
CRB_NIU_XG_PAUSE_CTL_P0 |
CRB_NIU_XG_PAUSE_CTL_P1);
} elseif (is_qla8032(ha) || is_qla8042(ha)) {
ql4_printk(KERN_INFO, ha, " %s: disabling pause transmit on port 0 & 1.\n",
__func__);
qla4_83xx_disable_pause(ha);
} 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:
ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: Cmd = %08X, ISP BUSY\n",
ha->host_no, __func__, mbx_cmd[0]);
ha->mailbox_timeout_count++; break;
/** * qla4xxx_get_minidump_template - Get the firmware template * @ha: Pointer to host adapter structure. * @phys_addr: dma address for template * * Obtain the minidump template from firmware during initialization * as it may not be available when minidump is desired.
**/ int qla4xxx_get_minidump_template(struct scsi_qla_host *ha,
dma_addr_t phys_addr)
{
uint32_t mbox_cmd[MBOX_REG_COUNT];
uint32_t mbox_sts[MBOX_REG_COUNT]; int status;
status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 8, &mbox_cmd[0],
&mbox_sts[0]); if (status == QLA_SUCCESS) {
ha->fw_dump_tmplt_size = mbox_sts[1];
DEBUG2(ql4_printk(KERN_INFO, ha, "%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",
__func__, mbox_sts[0], mbox_sts[1],
mbox_sts[2], mbox_sts[3], mbox_sts[4],
mbox_sts[5], mbox_sts[6], mbox_sts[7])); if (ha->fw_dump_tmplt_size == 0)
status = QLA_ERROR;
} else {
ql4_printk(KERN_WARNING, ha, "%s: Error sts[0]=0x%04x, mbx[1]=0x%04x\n",
__func__, mbox_sts[0], mbox_sts[1]);
status = QLA_ERROR;
}
return status;
}
void qla4xxx_mailbox_premature_completion(struct scsi_qla_host *ha)
{
set_bit(AF_FW_RECOVERY, &ha->flags);
ql4_printk(KERN_INFO, ha, "scsi%ld: %s: set FW RECOVERY!\n",
ha->host_no, __func__);
if (test_bit(AF_MBOX_COMMAND, &ha->flags)) { if (test_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags)) {
complete(&ha->mbx_intr_comp);
ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Due to fw " "recovery, doing premature completion of " "mbx cmd\n", ha->host_no, __func__);
} else {
set_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Due to fw " "recovery, doing premature completion of " "polling mbx cmd\n", ha->host_no, __func__);
}
}
}
/* High-water mark of IOCBs */
ha->iocb_hiwat = mbox_sts[2];
DEBUG2(ql4_printk(KERN_INFO, ha, "%s: firmware IOCBs available = %d\n", __func__,
ha->iocb_hiwat));
if (ha->iocb_hiwat > IOCB_HIWAT_CUSHION)
ha->iocb_hiwat -= IOCB_HIWAT_CUSHION;
/* Ideally, we should not enter this code, as the # of firmware * IOCBs is hard-coded in the firmware. We set a default
* iocb_hiwat here just in case */ if (ha->iocb_hiwat == 0) {
ha->iocb_hiwat = REQUEST_QUEUE_DEPTH / 4;
DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: Setting IOCB's to = %d\n", __func__,
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;
uint16_t options;
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: ddb [%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)); if (fw_ddb_entry)
memset(fw_ddb_entry, 0, sizeof(struct dev_db_entry));
if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 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: ddb mismatch [%d] != [%d].\n",
ha->host_no, __func__, fw_ddb_index,
mbox_sts[1])); goto exit_get_fwddb;
} if (fw_ddb_entry) {
options = le16_to_cpu(fw_ddb_entry->options); if (options & DDB_OPT_IPV6_DEVICE) {
ql4_printk(KERN_INFO, ha, "%s: DDB[%d] MB0 %04x Tot %d " "Next %d State %04x ConnErr %08x %pI6 " ":%04d \"%s\"\n", __func__, fw_ddb_index,
mbox_sts[0], mbox_sts[2], mbox_sts[3],
mbox_sts[4], mbox_sts[5],
fw_ddb_entry->ip_addr,
le16_to_cpu(fw_ddb_entry->port),
fw_ddb_entry->iscsi_name);
} else {
ql4_printk(KERN_INFO, ha, "%s: DDB[%d] MB0 %04x Tot %d " "Next %d State %04x ConnErr %08x %pI4 " ":%04d \"%s\"\n", __func__, fw_ddb_index,
mbox_sts[0], mbox_sts[2], mbox_sts[3],
mbox_sts[4], mbox_sts[5],
fw_ddb_entry->ip_addr,
le16_to_cpu(fw_ddb_entry->port),
fw_ddb_entry->iscsi_name);
}
} 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;
}
int qla4xxx_conn_open(struct scsi_qla_host *ha, uint16_t fw_ddb_index)
{
uint32_t mbox_cmd[MBOX_REG_COUNT];
uint32_t mbox_sts[MBOX_REG_COUNT]; int status;
status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0],
&mbox_sts[0]);
DEBUG2(ql4_printk(KERN_INFO, ha, "%s: status = %d mbx0 = 0x%x mbx1 = 0x%x\n",
__func__, status, mbox_sts[0], mbox_sts[1])); return status;
}
/** * qla4xxx_set_ddb_entry - sets a ddb entry. * @ha: Pointer to host adapter structure. * @fw_ddb_index: Firmware's device database index * @fw_ddb_entry_dma: dma address of ddb entry * @mbx_sts: mailbox 0 to be returned or NULL * * This routine initializes or updates the adapter's device database * entry for the specified device.
**/ int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index,
dma_addr_t fw_ddb_entry_dma, uint32_t *mbx_sts)
{
uint32_t mbox_cmd[MBOX_REG_COUNT];
uint32_t mbox_sts[MBOX_REG_COUNT]; int status;
/* 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));
if (ql4xextended_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_abort_task - issues Abort Task * @ha: Pointer to host adapter structure. * @srb: Pointer to srb entry * * 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_abort_task(struct scsi_qla_host *ha, struct srb *srb)
{
uint32_t mbox_cmd[MBOX_REG_COUNT];
uint32_t mbox_sts[MBOX_REG_COUNT]; struct scsi_cmnd *cmd = srb->cmd; int status = QLA_SUCCESS; unsignedlong flags = 0;
uint32_t index;
/* * Send abort task command to ISP, so that the ISP will return * request with ABORT status
*/
memset(&mbox_cmd, 0, sizeof(mbox_cmd));
memset(&mbox_sts, 0, sizeof(mbox_sts));
spin_lock_irqsave(&ha->hardware_lock, flags);
index = (unsignedlong)(unsignedchar *)cmd->host_scribble;
spin_unlock_irqrestore(&ha->hardware_lock, flags);
/* Firmware already posted completion on response queue */ if (index == MAX_SRBS) return status;
/** * qla4xxx_reset_lun - issues LUN Reset * @ha: Pointer to host adapter structure. * @ddb_entry: Pointer to device database entry * @lun: lun number * * 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,
uint64_t lun)
{
uint32_t mbox_cmd[MBOX_REG_COUNT];
uint32_t mbox_sts[MBOX_REG_COUNT];
uint32_t scsi_lun[2]; int status = QLA_SUCCESS;
/* * 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));
int_to_scsilun(lun, (struct scsi_lun *) scsi_lun);
qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 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;
}
/** * qla4xxx_reset_target - issues target Reset * @ha: Pointer to host adapter structure. * @ddb_entry: Pointer to device database entry * * This routine performs a TARGET RESET on the specified target. * The caller must ensure that the ddb_entry pointers * are valid before calling this routine.
**/ int qla4xxx_reset_target(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry)
{
uint32_t mbox_cmd[MBOX_REG_COUNT];
uint32_t mbox_sts[MBOX_REG_COUNT]; int status = QLA_SUCCESS;
/* * Send target 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));
/** * qla4xxx_about_firmware - gets FW, iscsi draft and boot loader version * @ha: Pointer to host adapter structure. * * Retrieves the FW version, iSCSI draft version & bootloader version of HBA. * Mailboxes 2 & 3 may hold an address for data. Make sure that we write 0 to * those mailboxes, if unused.
**/ int qla4xxx_about_firmware(struct scsi_qla_host *ha)
{ struct about_fw_info *about_fw = NULL;
dma_addr_t about_fw_dma;
uint32_t mbox_cmd[MBOX_REG_COUNT];
uint32_t mbox_sts[MBOX_REG_COUNT]; int status = QLA_ERROR;
about_fw = dma_alloc_coherent(&ha->pdev->dev, sizeof(struct about_fw_info),
&about_fw_dma, GFP_KERNEL); if (!about_fw) {
DEBUG2(ql4_printk(KERN_ERR, ha, "%s: Unable to alloc memory " "for about_fw\n", __func__)); return status;
}
if (dev_db_start_offset > dev_db_end_offset) {
DEBUG2(ql4_printk(KERN_ERR, ha, "%s:Invalid DDB index %d", __func__,
ddb_index)); goto exit_bootdb_failed;
}
if (qla4xxx_get_flash(ha, fw_ddb_entry_dma, dev_db_start_offset, sizeof(*fw_ddb_entry)) != QLA_SUCCESS) {
ql4_printk(KERN_ERR, ha, "scsi%ld: %s: Get Flash" "failed\n", ha->host_no, __func__); goto exit_bootdb_failed;
}
if (fw_ddb_entry->cookie == DDB_VALID_COOKIE)
status = QLA_SUCCESS;
exit_bootdb_failed: return status;
}
int qla4xxx_flashdb_by_index(struct scsi_qla_host *ha, struct dev_db_entry *fw_ddb_entry,
dma_addr_t fw_ddb_entry_dma, uint16_t ddb_index)
{
uint32_t dev_db_start_offset;
uint32_t dev_db_end_offset; int status = QLA_ERROR;
memset(fw_ddb_entry, 0, sizeof(*fw_ddb_entry));
if (is_qla40XX(ha)) {
dev_db_start_offset = FLASH_OFFSET_DB_INFO;
dev_db_end_offset = FLASH_OFFSET_DB_END;
} else {
dev_db_start_offset = FLASH_RAW_ACCESS_ADDR +
(ha->hw.flt_region_ddb << 2); /* flt_ddb_size is DDB table size for both ports * so divide it by 2 to calculate the offset for second port
*/ if (ha->port_num == 1)
dev_db_start_offset += (ha->hw.flt_ddb_size / 2);
if (is_qla40XX(ha))
offset = FLASH_CHAP_OFFSET | (idx * chap_size); else {
offset = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_region_chap << 2); /* flt_chap_size is CHAP table size for both ports * so divide it by 2 to calculate the offset for second port
*/ if (ha->port_num == 1)
offset += (ha->hw.flt_chap_size / 2);
offset += (idx * chap_size);
}
rval = qla4xxx_get_flash(ha, chap_dma, offset, chap_size); if (rval != QLA_SUCCESS) {
ret = -EINVAL; goto exit_get_chap;
}
DEBUG2(ql4_printk(KERN_INFO, ha, "Chap Cookie: x%x\n",
__le16_to_cpu(chap_table->cookie)));
if (__le16_to_cpu(chap_table->cookie) != CHAP_VALID_COOKIE) {
ql4_printk(KERN_ERR, ha, "No valid chap entry found\n"); goto exit_get_chap;
}
/** * qla4xxx_set_chap - Make a chap entry at the given index * @ha: pointer to adapter structure * @username: CHAP username to set * @password: CHAP password to set * @idx: CHAP index at which to make the entry * @bidi: type of chap entry (chap_in or chap_out) * * Create chap entry at the given index with the information provided. * * Note: Caller should acquire the chap lock before getting here.
**/ int qla4xxx_set_chap(struct scsi_qla_host *ha, char *username, char *password,
uint16_t idx, int bidi)
{ int ret = 0; int rval = QLA_ERROR;
uint32_t offset = 0; struct ql4_chap_table *chap_table;
uint32_t chap_size = 0;
dma_addr_t chap_dma;
ssize_t secret_len;
chap_table = dma_pool_zalloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma); if (chap_table == NULL) {
ret = -ENOMEM; goto exit_set_chap;
}
if (bidi)
chap_table->flags |= BIT_6; /* peer */ else
chap_table->flags |= BIT_7; /* local */
if (is_qla40XX(ha)) {
chap_size = MAX_CHAP_ENTRIES_40XX * sizeof(*chap_table);
offset = FLASH_CHAP_OFFSET;
} else { /* Single region contains CHAP info for both ports which is * divided into half for each port.
*/
chap_size = ha->hw.flt_chap_size / 2;
offset = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_region_chap << 2); if (ha->port_num == 1)
offset += chap_size;
}
/** * qla4xxx_get_chap_index - Get chap index given username and secret * @ha: pointer to adapter structure * @username: CHAP username to be searched * @password: CHAP password to be searched * @bidi: Is this a BIDI CHAP * @chap_index: CHAP index to be returned * * Match the username and password in the chap_list, return the index if a * match is found. If a match is not found then add the entry in FLASH and * return the index at which entry is written in the FLASH.
**/ int qla4xxx_get_chap_index(struct scsi_qla_host *ha, char *username, char *password, int bidi, uint16_t *chap_index)
{ int i, rval; int free_index = -1; int found_index = 0; int max_chap_entries = 0; struct ql4_chap_table *chap_table;
if (!ha->chap_list) {
ql4_printk(KERN_ERR, ha, "Do not have CHAP table cache\n"); return QLA_ERROR;
}
if (!username || !password) {
ql4_printk(KERN_ERR, ha, "Do not have username and psw\n"); return QLA_ERROR;
}
mutex_lock(&ha->chap_sem); for (i = 0; i < max_chap_entries; i++) {
chap_table = (struct ql4_chap_table *)ha->chap_list + i; if (chap_table->cookie !=
cpu_to_le16(CHAP_VALID_COOKIE)) { if (i > MAX_RESRV_CHAP_IDX && free_index == -1)
free_index = i; continue;
} if (bidi) { if (chap_table->flags & BIT_7) continue;
} else { if (chap_table->flags & BIT_6) continue;
} if (!strncmp(chap_table->secret, password,
MAX_CHAP_SECRET_LEN) &&
!strncmp(chap_table->name, username,
MAX_CHAP_NAME_LEN)) {
*chap_index = i;
found_index = 1; break;
}
}
/* If chap entry is not present and a free index is available then * write the entry in flash
*/ if (!found_index && free_index != -1) {
rval = qla4xxx_set_chap(ha, username, password,
free_index, bidi); if (!rval) {
*chap_index = free_index;
found_index = 1;
}
}
mutex_unlock(&ha->chap_sem);
if (found_index) return QLA_SUCCESS; return QLA_ERROR;
}
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]; int status = QLA_SUCCESS;
status = qla4xxx_mailbox_command(ha, 8, 5, &mbox_cmd[0], &mbox_sts[0]); if (status != QLA_SUCCESS) {
DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_DISABLE_ACB " "failed w/ status %04X %04X %04X", __func__,
mbox_sts[0], mbox_sts[1], mbox_sts[2]));
} else { if (is_qla8042(ha) &&
test_bit(DPC_POST_IDC_ACK, &ha->dpc_flags) &&
(mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE)) { /* * Disable ACB mailbox command takes time to complete * based on the total number of targets connected. * For 512 targets, it took approximately 5 secs to * complete. Setting the timeout value to 8, with the 3 * secs buffer.
*/
qla4_84xx_extend_idc_tmo(ha, IDC_EXTEND_TOV); if (!wait_for_completion_timeout(&ha->disable_acb_comp,
IDC_EXTEND_TOV * HZ)) {
ql4_printk(KERN_WARNING, ha, "%s: Disable ACB Completion not received\n",
__func__);
}
}
} return status;
}
int qla4xxx_get_acb(struct scsi_qla_host *ha, dma_addr_t acb_dma,
uint32_t acb_type, uint32_t len)
{
uint32_t mbox_cmd[MBOX_REG_COUNT];
uint32_t mbox_sts[MBOX_REG_COUNT]; int status = QLA_SUCCESS;
status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0],
&mbox_sts[0]); if (status != QLA_SUCCESS) {
DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed " "status %04X\n", ha->host_no, __func__,
mbox_sts[0]));
} return status;
}
/** * qla4_8xxx_set_param - set driver version in firmware. * @ha: Pointer to host adapter structure. * @param: Parameter to set i.e driver version
**/ int qla4_8xxx_set_param(struct scsi_qla_host *ha, int param)
{
uint32_t mbox_cmd[MBOX_REG_COUNT];
uint32_t mbox_sts[MBOX_REG_COUNT];
uint32_t status;
status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, mbox_cmd,
mbox_sts); if (status == QLA_ERROR)
ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n",
__func__, mbox_sts[0]);
exit_set_param: return status;
}
/** * qla4_83xx_post_idc_ack - post IDC ACK * @ha: Pointer to host adapter structure. * * Posts IDC ACK for IDC Request Notification AEN.
**/ int qla4_83xx_post_idc_ack(struct scsi_qla_host *ha)
{
uint32_t mbox_cmd[MBOX_REG_COUNT];
uint32_t mbox_sts[MBOX_REG_COUNT]; int status;
status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT,
mbox_cmd, mbox_sts); if (status != QLA_SUCCESS)
ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n", __func__,
mbox_sts[0]);
return status;
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.35 Sekunden
(vorverarbeitet am 2026-04-25)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.