From: David Somayajulu Subject: Update qla4xxx to 5.01.00-k8_sles11-03 References: bnc#444884 This patch updates the qla4xxx driver to 5.01.00-k8_sles11-03. Signed-off-by: David Somayajulu Signed-off-by: Hannes Reinecke --- drivers/scsi/qla4xxx/ql4_dbg.c | 36 -- drivers/scsi/qla4xxx/ql4_dbg.h | 59 ++-- drivers/scsi/qla4xxx/ql4_def.h | 11 drivers/scsi/qla4xxx/ql4_glbl.h | 10 drivers/scsi/qla4xxx/ql4_init.c | 172 +++++++----- drivers/scsi/qla4xxx/ql4_inline.h | 143 ++++++++++ drivers/scsi/qla4xxx/ql4_iocb.c | 161 +---------- drivers/scsi/qla4xxx/ql4_isr.c | 36 +- drivers/scsi/qla4xxx/ql4_mbx.c | 11 drivers/scsi/qla4xxx/ql4_os.c | 499 ++++++++++++++++++++----------------- drivers/scsi/qla4xxx/ql4_os.h | 125 +++++++++ drivers/scsi/qla4xxx/ql4_version.h | 3 12 files changed, 736 insertions(+), 530 deletions(-) --- a/drivers/scsi/qla4xxx/ql4_dbg.c +++ b/drivers/scsi/qla4xxx/ql4_dbg.c @@ -13,28 +13,6 @@ #include -static void qla4xxx_print_srb_info(struct srb * srb) -{ - printk("%s: srb = 0x%p, flags=0x%02x\n", __func__, srb, srb->flags); - printk("%s: cmd = 0x%p, saved_dma_handle = 0x%lx\n", - __func__, srb->cmd, (unsigned long) srb->dma_handle); - printk("%s: fw_ddb_index = %d, lun = %d\n", - __func__, srb->fw_ddb_index, srb->cmd->device->lun); - printk("%s: iocb_tov = %d\n", - __func__, srb->iocb_tov); - printk("%s: cc_stat = 0x%x\n", __func__, srb->cc_stat); -} - -void qla4xxx_print_scsi_cmd(struct scsi_cmnd *cmd) -{ - printk("SCSI Command = 0x%p, Handle=0x%p\n", cmd, cmd->host_scribble); - printk(" b=%d, t=%02xh, l=%02xh, cmd_len = %02xh\n", - cmd->device->channel, cmd->device->id, cmd->device->lun, - cmd->cmd_len); - scsi_print_command(cmd); - qla4xxx_print_srb_info((struct srb *) cmd->SCp.ptr); -} - void __dump_registers(struct scsi_qla_host *ha) { uint8_t i; @@ -143,17 +121,6 @@ void __dump_registers(struct scsi_qla_ho } } -void qla4xxx_dump_mbox_registers(struct scsi_qla_host *ha) -{ - unsigned long flags = 0; - int i = 0; - spin_lock_irqsave(&ha->hardware_lock, flags); - for (i = 1; i < MBOX_REG_COUNT; i++) - printk(KERN_INFO " Mailbox[%d] = %08x\n", i, - readw(&ha->reg->mailbox[i])); - spin_unlock_irqrestore(&ha->hardware_lock, flags); -} - void qla4xxx_dump_registers(struct scsi_qla_host *ha) { unsigned long flags = 0; @@ -179,6 +146,5 @@ void qla4xxx_dump_buffer(void *b, uint32 else printk(KERN_DEBUG " "); } - if (cnt % 16) - printk(KERN_DEBUG "\n"); + printk(KERN_DEBUG "\n"); } --- a/drivers/scsi/qla4xxx/ql4_dbg.h +++ b/drivers/scsi/qla4xxx/ql4_dbg.h @@ -14,49 +14,44 @@ /* #define QL_DEBUG_LEVEL_5 */ /* #define QL_DEBUG_LEVEL_6 */ /* #define QL_DEBUG_LEVEL_9 */ +#ifndef _QL4_DBG_ +#define _QL4_DBG_ #define QL_DEBUG_LEVEL_2 /* ALways enable error messagess */ #if defined(QL_DEBUG) -#define DEBUG(x) do {x;} while (0); +#define DEBUG(x) do {if(extended_error_logging & 0x01) x;} while (0); #else -#define DEBUG(x) do {} while (0); +#define DEBUG(x) #endif #if defined(QL_DEBUG_LEVEL_2) -#define DEBUG2(x) do {if(extended_error_logging == 2) x;} while (0); -#define DEBUG2_3(x) do {x;} while (0); -#else /* */ -#define DEBUG2(x) do {} while (0); -#endif /* */ +#define DEBUG2(x) do {if(extended_error_logging & 0x02) x;} while (0); +#else +#define DEBUG2(x) +#endif #if defined(QL_DEBUG_LEVEL_3) -#define DEBUG3(x) do {if(extended_error_logging == 3) x;} while (0); -#else /* */ -#define DEBUG3(x) do {} while (0); -#if !defined(QL_DEBUG_LEVEL_2) -#define DEBUG2_3(x) do {} while (0); -#endif /* */ -#endif /* */ +#define DEBUG3(x) do {if(extended_error_logging & 0x04) x;} while (0); +#else +#define DEBUG3(x) +#endif + #if defined(QL_DEBUG_LEVEL_4) -#define DEBUG4(x) do {x;} while (0); -#else /* */ -#define DEBUG4(x) do {} while (0); -#endif /* */ +#define DEBUG4(x) do {if(extended_error_logging & 0x08) x;} while (0); +#else +#define DEBUG4(x) +#endif #if defined(QL_DEBUG_LEVEL_5) -#define DEBUG5(x) do {x;} while (0); -#else /* */ -#define DEBUG5(x) do {} while (0); -#endif /* */ +#define DEBUG5(x) do {if(extended_error_logging & 0x10) x;} while (0); +#else +#define DEBUG5(x) +#endif #if defined(QL_DEBUG_LEVEL_6) -#define DEBUG6(x) do {x;} while (0); -#else /* */ -#define DEBUG6(x) do {} while (0); -#endif /* */ - -#if defined(QL_DEBUG_LEVEL_9) -#define DEBUG9(x) do {x;} while (0); -#else /* */ -#define DEBUG9(x) do {} while (0); -#endif /* */ +#define DEBUG6(x) do {if(extended_error_logging & 0x20) x;} while (0); +#else +#define DEBUG6(x) +#endif + +#endif /*_QL4_DBG_*/ --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h @@ -144,7 +144,6 @@ #define RESET_FIRMWARE_TOV 30 #define LOGOUT_TOV 10 #define IOCB_TOV_MARGIN 10 -#define RELOGIN_TOV 18 #define ISNS_DEREG_TOV 5 #define MAX_RESET_HA_RETRIES 2 @@ -252,6 +251,8 @@ struct ddb_entry { #define DF_NO_RELOGIN 1 /* Do not relogin if IOCTL * logged it out */ #define DF_SCAN_ISSUED 2 +#define DF_OFFLINE 3 /* Offline Device */ +#define DF_DELETED 4 /* Device has been removed */ /* * Asynchronous Event Queue structure @@ -286,7 +287,6 @@ struct scsi_qla_host { uint32_t tot_ddbs; unsigned long flags; -#define AF_ISNS_CMD_DONE 13 /* 0x00002000 */ #define AF_ONLINE 0 /* 0x00000001 */ #define AF_INIT_DONE 1 /* 0x00000002 */ #define AF_MBOX_COMMAND 2 /* 0x00000004 */ @@ -294,9 +294,9 @@ struct scsi_qla_host { #define AF_INTERRUPTS_ON 6 /* 0x00000040 Not Used */ #define AF_GET_CRASH_RECORD 7 /* 0x00000080 */ #define AF_LINK_UP 8 /* 0x00000100 */ -#define AF_TOPCAT_CHIP_PRESENT 9 /* 0x00000200 */ #define AF_IRQ_ATTACHED 10 /* 0x00000400 */ #define AF_DISABLE_ACB_COMPLETE 11 /* 0x00000800 */ +#define AF_OS_INDEX_VALID 12 /* 0x00001000 */ unsigned long dpc_flags; @@ -308,6 +308,8 @@ struct scsi_qla_host { #define DPC_ISNS_RESTART 7 /* 0x00000080 */ #define DPC_AEN 9 /* 0x00000200 */ #define DPC_GET_DHCP_IP_ADDR 15 /* 0x00008000 */ +#define DPC_OFFLINE_DEVICE 16 /* 0x00010000 */ +#define DPC_DELETE_DEVICE 17 /* 0x00020000 */ uint16_t iocb_cnt; uint16_t iocb_hiwat; @@ -460,7 +462,7 @@ struct scsi_qla_host { void (*ql4getaenlog)(struct scsi_qla_host *ha, struct ql4_aen_log *aenl); #define QL_INDICES_PER_ENTRY 32 #define QL_OSINDEX_ENTRIES (MAX_DDB_ENTRIES/QL_INDICES_PER_ENTRY) - volatile uint32_t os_map[QL_OSINDEX_ENTRIES]; + volatile unsigned long os_map[QL_OSINDEX_ENTRIES]; }; static inline int is_qla4010(struct scsi_qla_host *ha) @@ -468,6 +470,7 @@ static inline int is_qla4010(struct scsi return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP4010; } + static inline int is_qla4022(struct scsi_qla_host *ha) { return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP4022; --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h @@ -10,7 +10,7 @@ struct iscsi_cls_conn; -void qla4xxx_hw_reset(struct scsi_qla_host *ha); +void qla4xxx_hw_reset(struct scsi_qla_host *ha, int hw_lock); int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a); int qla4xxx_conn_start(struct iscsi_cls_conn *conn); int qla4xxx_send_tgts(struct scsi_qla_host *ha, char *ip, uint16_t port); @@ -18,9 +18,9 @@ int qla4xxx_send_command_to_isp(struct s int qla4xxx_initialize_adapter(struct scsi_qla_host * ha, uint8_t renew_ddb_list); int qla4xxx_soft_reset(struct scsi_qla_host *ha); -irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id); void qla4xxx_free_ddb_list(struct scsi_qla_host * ha); +void qla4xxx_free_ddb(struct scsi_qla_host *, struct ddb_entry *); void qla4xxx_process_aen(struct scsi_qla_host * ha, uint8_t process_aen); int qla4xxx_get_dhcp_ip_address(struct scsi_qla_host * ha); @@ -47,6 +47,8 @@ int qla4xxx_get_fwddb_entry(struct scsi_ uint16_t *tcp_source_port_num, uint16_t *connection_id); +struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host * ha, + uint32_t fw_ddb_index); int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index, dma_addr_t fw_ddb_entry_dma); @@ -77,10 +79,6 @@ int qla4xxx_process_ddb_changed(struct s int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, uint8_t outCount, uint32_t *mbx_cmd, uint32_t *mbx_sts); -int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha, - struct ddb_entry *ddb_entry, int lun); - - extern int extended_error_logging; extern int ql4xdiscoverywait; --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c @@ -10,6 +10,7 @@ #include "ql4_glbl.h" #include "ql4_dbg.h" #include "ql4_inline.h" +#include "ql4_os.h" /* link auto negotiation normally takes roughly 2s. */ /* If we don't have link in 3 times that period quit. */ @@ -19,9 +20,6 @@ * QLogic ISP4xxx Hardware Support Function Prototypes. */ -static struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha, - uint32_t fw_ddb_index); - static void ql4xxx_set_mac_number(struct scsi_qla_host *ha) { uint32_t value; @@ -52,15 +50,14 @@ static void ql4xxx_set_mac_number(struct } /** - * qla4xxx_free_ddb - deallocate ddb + * qla4xxx_free_ddb - deallocate ddb * @ha: pointer to host adapter structure. * @ddb_entry: pointer to device database entry * * This routine deallocates and unlinks the specified ddb_entry from the * adapter's **/ -static void qla4xxx_free_ddb(struct scsi_qla_host *ha, - struct ddb_entry *ddb_entry) +void qla4xxx_free_ddb(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry) { /* Remove device entry from list */ list_del_init(&ddb_entry->list); @@ -359,8 +356,8 @@ static void qla4xxx_fill_ddb(struct ddb_ * This routine allocates a ddb_entry, ititializes some values, and * inserts it into the ddb list. **/ -static struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha, - uint32_t fw_ddb_index) +struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha, + uint32_t fw_ddb_index) { struct ddb_entry *ddb_entry; @@ -478,7 +475,7 @@ static int qla4xxx_build_ddb_list(struct (strlen(fw_ddb_entry->iscsi_name) != 0)){ ddb_entry = qla4xxx_alloc_ddb(ha, fw_ddb_index); if (ddb_entry == NULL) { - DEBUG2(dev_info(&ha->pdev->dev,"%s alloc_ddb %d " + DEBUG2(dev_info(&ha->pdev->dev,"%s alloc_ddb %d" "failed\n", __func__, fw_ddb_index)); goto exit_ddb_list; } @@ -488,7 +485,7 @@ static int qla4xxx_build_ddb_list(struct ddb_entry->connection_id = conn_id; qla4xxx_fill_ddb(ddb_entry, fw_ddb_entry); ddb_entry->fw_ddb_device_state = ddb_state; - + if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) { atomic_set(&ddb_entry->state, DDB_STATE_ONLINE); dev_info(&ha->pdev->dev, @@ -695,6 +692,8 @@ static int qla4xxx_initialize_ddb_list(s qla4xxx_flush_AENS(ha); + /* Wait for an AEN */ + qla4xxx_devices_ready(ha); /* * First perform device discovery for active @@ -704,9 +703,6 @@ static int qla4xxx_initialize_ddb_list(s if ((status = qla4xxx_build_ddb_list(ha)) == QLA_ERROR) return status; - /* Wait for an AEN */ - qla4xxx_devices_ready(ha); - /* * Targets can come online after the inital discovery, so processing * the aens here will catch them. @@ -747,13 +743,15 @@ int qla4xxx_reinitialize_ddb_list(struct qla4xxx_fill_ddb(ddb_entry, fw_ddb_entry); - if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) { + if (ddb_entry->fw_ddb_device_state == + DDB_DS_SESSION_ACTIVE) { atomic_set(&ddb_entry->state, DDB_STATE_ONLINE); dev_info(&ha->pdev->dev, - "scsi%ld: %s: ddb[%d] os[%d] marked ONLINE\n", - ha->host_no, __func__, ddb_entry->fw_ddb_index, + "%s: ddb[%d] os[%d] marked ONLINE\n", + __func__, ddb_entry->fw_ddb_index, ddb_entry->os_target_id); - } else if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE) + } else if (atomic_read(&ddb_entry->state) == + DDB_STATE_ONLINE) qla4xxx_mark_device_missing(ha, ddb_entry); } } @@ -884,8 +882,8 @@ static int qla4xxx_start_firmware_from_f writel(set_rmask(NVR_WRITE_ENABLE), &ha->reg->u1.isp4022.nvram); - writel(2, &ha->reg->mailbox[6]); - readl(&ha->reg->mailbox[6]); + writel(2, &ha->reg->mailbox[6]); + readl(&ha->reg->mailbox[6]); writel(set_rmask(CSR_BOOT_ENABLE), &ha->reg->ctrl_status); readl(&ha->reg->ctrl_status); @@ -1054,7 +1052,7 @@ static int qla4xxx_start_firmware(struct } config_chip = 1; - /* Reset clears the semaphore, so acquire again */ + /* Reset clears the semaphore, so aquire again */ if (ql4xxx_lock_drvr_wait(ha) != QLA_SUCCESS) return QLA_ERROR; } @@ -1083,7 +1081,7 @@ static int qla4xxx_start_firmware(struct * @renew_ddb_list: Indicates what to do with the adapter's ddb list * after adapter recovery has completed. * 0=preserve ddb list, 1=destroy and rebuild ddb list - * + * * This routine parforms all of the steps necessary to initialize the adapter. * **/ @@ -1119,12 +1117,12 @@ int qla4xxx_initialize_adapter(struct sc * followed by 0x8014 aen" to trigger the tgt discovery process. */ if (ha->firmware_state & FW_STATE_DHCP_IN_PROGRESS) - goto exit_init_online; + goto exit_init_hba0; /* Skip device discovery if ip and subnet is zero */ if (memcmp(ha->ip_address, ip_address, IP_ADDR_LEN) == 0 || memcmp(ha->subnet_mask, ip_address, IP_ADDR_LEN) == 0) - goto exit_init_online; + goto exit_init_hba0; if (renew_ddb_list == PRESERVE_DDB_LIST) { /* @@ -1153,8 +1151,10 @@ int qla4xxx_initialize_adapter(struct sc ha->host_no)); } -exit_init_online: +exit_init_hba0: set_bit(AF_ONLINE, &ha->flags); + dev_info(&ha->pdev->dev, "%s: adapter ONLINE\n", __func__); + exit_init_hba: return status; } @@ -1204,40 +1204,63 @@ static void qla4xxx_add_device_dynamical } } - if (!found) - ddb_entry = qla4xxx_alloc_ddb(ha, fw_ddb_index); - else if (ddb_entry->fw_ddb_index != fw_ddb_index) { - /* Target has been bound to a new fw_ddb_index */ - qla4xxx_free_ddb(ha, ddb_entry); + if (!found) { ddb_entry = qla4xxx_alloc_ddb(ha, fw_ddb_index); - } - if (ddb_entry == NULL) { - DEBUG2(dev_info(&ha->pdev->dev, "%s NULL DDB %d\n", - __func__, fw_ddb_index)); - goto exit_dyn_add; - } + if (ddb_entry == NULL) { + DEBUG2(dev_info(&ha->pdev->dev, "%s NULL DDB %d\n", + __func__, fw_ddb_index)); + goto exit_dyn_add; + } - ddb_entry->fw_ddb_index = fw_ddb_index; - ha->fw_ddb_index_map[fw_ddb_index] = ddb_entry; - ddb_entry->tcp_source_port_num = src_port; - ddb_entry->connection_id = conn_id; - qla4xxx_fill_ddb(ddb_entry, fw_ddb_entry); - ddb_entry->fw_ddb_device_state = ddb_state; + ddb_entry->fw_ddb_index = fw_ddb_index; + ha->fw_ddb_index_map[fw_ddb_index] = ddb_entry; + ddb_entry->tcp_source_port_num = src_port; + ddb_entry->connection_id = conn_id; + qla4xxx_fill_ddb(ddb_entry, fw_ddb_entry); + ddb_entry->fw_ddb_device_state = ddb_state; + + if (probe) + goto exit_dyn_add; - if (!probe) { if (qla4xxx_add_sess(ddb_entry, 1)) { - DEBUG2(printk(KERN_WARNING - "scsi%ld: failed to add new device at index " - "[%d]\n Unable to add connection and session\n", - ha->host_no, fw_ddb_index)); + DEBUG2(dev_info(&ha->pdev->dev, + "%s: failed to add new ddb %d\n", + __func__, fw_ddb_index)); qla4xxx_free_ddb(ha, ddb_entry); + } else { + DEBUG6(dev_info(&ha->pdev->dev, + "%s added ddb 0x%p sess 0x%p" + " conn 0x%p state 0x%x\n", + __func__, ddb_entry, + ddb_entry->sess, ddb_entry->conn, + ddb_entry->state)); } - } + } else if (ddb_entry->fw_ddb_index != fw_ddb_index) { + /* Target has been bound to a new fw_ddb_index */ + ha->fw_ddb_index_map[ddb_entry->fw_ddb_index] = NULL; + ddb_entry->fw_ddb_index = fw_ddb_index; + ddb_entry->fw_ddb_device_state = ddb_state; + ha->fw_ddb_index_map[fw_ddb_index] = ddb_entry; + atomic_set(&ddb_entry->port_down_timer, + ha->port_down_retry_count); + atomic_set(&ddb_entry->relogin_retry_count, 0); + atomic_set(&ddb_entry->relogin_timer, 0); + clear_bit(DF_RELOGIN, &ddb_entry->flags); + clear_bit(DF_NO_RELOGIN, &ddb_entry->flags); + atomic_set(&ddb_entry->state, DDB_STATE_ONLINE); - DEBUG6(dev_info(&ha->pdev->dev, "%s added ddb 0x%p sess 0x%p conn 0x%p" - " state 0x%x\n", __func__, ddb_entry, ddb_entry->sess, - ddb_entry->conn, ddb_entry->state)); + dev_info(&ha->pdev->dev, + "scsi%ld: %s: ddb[%d] os[%d] marked ONLINE sess:%p conn:%p\n", + ha->host_no, __func__, ddb_entry->fw_ddb_index, + ddb_entry->os_target_id, ddb_entry->sess, ddb_entry->conn); + + if (!probe) + qla4xxx_conn_start(ddb_entry->conn); + DEBUG6(dev_info(&ha->pdev->dev, "%s calling conn_start ddb 0x%p sess 0x%p" + " conn 0x%p state 0x%x\n", __func__, ddb_entry, ddb_entry->sess, + ddb_entry->conn, ddb_entry->state)); + } exit_dyn_add: dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), fw_ddb_entry, fw_ddb_entry_dma); @@ -1272,15 +1295,15 @@ int qla4xxx_process_ddb_changed(struct s qla4xxx_add_device_dynamically(ha, fw_ddb_index, probe); return QLA_SUCCESS; } - DEBUG6(dev_info(&ha->pdev->dev, "%s ddb_entry 0x%p ostate 0x%x" - " sess 0x%p conn 0x%p\n", __func__, ddb_entry, - ddb_entry->state, ddb_entry->sess, ddb_entry->conn)); + DEBUG6(dev_info(&ha->pdev->dev, "%s ddb[%d] os[%d] ostate 0x%x" + " sess 0x%p conn 0x%p o_fwstate 0x%x n_fwstate ox%x \n", + __func__, ddb_entry->fw_ddb_index, ddb_entry->os_target_id, + ddb_entry->state, ddb_entry->sess, ddb_entry->conn, + ddb_entry->fw_ddb_device_state, state)); /* Device already exists in our database. */ old_fw_ddb_device_state = ddb_entry->fw_ddb_device_state; - DEBUG2(printk("scsi%ld: %s DDB - old state= 0x%x, new state=0x%x for " - "index [%d]\n", ha->host_no, __func__, - ddb_entry->fw_ddb_device_state, state, fw_ddb_index)); + if (old_fw_ddb_device_state == state && state == DDB_DS_SESSION_ACTIVE) { /* Do nothing, state not changed. */ @@ -1297,26 +1320,33 @@ int qla4xxx_process_ddb_changed(struct s atomic_set(&ddb_entry->port_down_timer, ha->port_down_retry_count); atomic_set(&ddb_entry->state, DDB_STATE_ONLINE); + dev_info(&ha->pdev->dev, + "%s: ddb[%d] os[%d] marked ONLINE\n", + __func__, ddb_entry->fw_ddb_index, + ddb_entry->os_target_id); + atomic_set(&ddb_entry->relogin_retry_count, 0); atomic_set(&ddb_entry->relogin_timer, 0); clear_bit(DF_RELOGIN, &ddb_entry->flags); clear_bit(DF_NO_RELOGIN, &ddb_entry->flags); - DEBUG6(dev_info(&ha->pdev->dev, "%s conn startddb_entry 0x%p" - " sess 0x%p conn 0x%p\n", - __func__, ddb_entry, ddb_entry->sess, ddb_entry->conn)); - - qla4xxx_conn_start(ddb_entry->conn); - - DEBUG6(dev_info(&ha->pdev->dev, "%s conn start done " - "ddb_entry 0x%p sess 0x%p conn 0x%p\n", - __func__, ddb_entry, ddb_entry->sess, ddb_entry->conn)); - - if (!test_bit(DF_SCAN_ISSUED, &ddb_entry->flags)) { - scsi_scan_target(&ddb_entry->sess->dev, 0, - ddb_entry->sess->target_id, - SCAN_WILD_CARD, 0); - set_bit(DF_SCAN_ISSUED, &ddb_entry->flags); + if (ddb_entry->conn) { + DEBUG6(dev_info(&ha->pdev->dev, + "%s conn startddb_entry 0x%p" + " sess 0x%p conn 0x%p\n", + __func__, + ddb_entry, ddb_entry->sess, ddb_entry->conn)); + + qla4xxx_conn_start(ddb_entry->conn); + + DEBUG6(dev_info(&ha->pdev->dev, "%s conn start done " + "ddb_entry 0x%p sess 0x%p conn 0x%p\n", + __func__, ddb_entry, ddb_entry->sess, ddb_entry->conn)); + + if (!test_bit(DF_SCAN_ISSUED, &ddb_entry->flags)) { + qla4xxx_scan_target(ddb_entry); + set_bit(DF_SCAN_ISSUED, &ddb_entry->flags); + } } } else { /* Device went away, try to relogin. */ --- a/drivers/scsi/qla4xxx/ql4_inline.h +++ b/drivers/scsi/qla4xxx/ql4_inline.h @@ -34,6 +34,34 @@ qla4xxx_lookup_ddb_by_fw_index(struct sc return ddb_entry; } +/* + * The MBOX_CMD_CLEAR_DATABASE_ENTRY (0x31) mailbox command does not + * result in an AEN, so we need to process it seperately. + */ +static inline void qla4xxx_check_for_clear_ddb(struct scsi_qla_host *ha, + uint32_t *mbox_cmd) +{ + uint32_t fw_ddb_index; + struct ddb_entry *ddb_entry = NULL; + + if (mbox_cmd[0] == MBOX_CMD_CLEAR_DATABASE_ENTRY) { + + fw_ddb_index = mbox_cmd[1]; + + if (fw_ddb_index < MAX_DDB_ENTRIES) + ddb_entry = ha->fw_ddb_index_map[fw_ddb_index]; + + if (ddb_entry) { + dev_info(&ha->pdev->dev, "%s: ddb[%d] os[%d] freed\n", + __func__, ddb_entry->fw_ddb_index, + ddb_entry->os_target_id); + set_bit(DF_DELETED, &ddb_entry->flags); + set_bit(DPC_DELETE_DEVICE, &ha->dpc_flags); + queue_work(ha->dpc_thread, &ha->dpc_work); + } + } +} + static inline void __qla4xxx_enable_intrs(struct scsi_qla_host *ha) { @@ -81,3 +109,118 @@ qla4xxx_disable_intrs(struct scsi_qla_ho __qla4xxx_disable_intrs(ha); spin_unlock_irqrestore(&ha->hardware_lock, flags); } + +static inline int qla4xxx_get_req_pkt(struct scsi_qla_host *ha, + struct queue_entry **queue_entry) +{ + uint16_t request_in; + uint8_t status = QLA_SUCCESS; + + *queue_entry = ha->request_ptr; + + /* get the latest request_in and request_out index */ + request_in = ha->request_in; + ha->request_out = (uint16_t) le32_to_cpu(ha->shadow_regs->req_q_out); + + /* Advance request queue pointer and check for queue full */ + if (request_in == (REQUEST_QUEUE_DEPTH - 1)) { + request_in = 0; + ha->request_ptr = ha->request_ring; + } else { + request_in++; + ha->request_ptr++; + } + + /* request queue is full, try again later */ + if ((ha->iocb_cnt + 1) >= ha->iocb_hiwat) { + /* restore request pointer */ + ha->request_ptr = *queue_entry; + status = QLA_ERROR; + } else { + ha->request_in = request_in; + memset(*queue_entry, 0, sizeof(**queue_entry)); + } + + return status; +} + +/** + * qla4xxx_send_marker_iocb - issues marker iocb to HBA + * @ha: Pointer to host adapter structure. + * @ddb_entry: Pointer to device database entry + * @lun: SCSI LUN + * @marker_type: marker identifier + * + * This routine issues a marker IOCB. + **/ +static inline int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha, + struct ddb_entry *ddb_entry, int lun) +{ + struct marker_entry *marker_entry; + unsigned long flags = 0; + uint8_t status = QLA_SUCCESS; + + /* Acquire hardware specific lock */ + spin_lock_irqsave(&ha->hardware_lock, flags); + + /* Get pointer to the queue entry for the marker */ + if (qla4xxx_get_req_pkt(ha, (struct queue_entry **) &marker_entry) != + QLA_SUCCESS) { + status = QLA_ERROR; + goto exit_send_marker; + } + + /* Put the marker in the request queue */ + marker_entry->hdr.entryType = ET_MARKER; + marker_entry->hdr.entryCount = 1; + marker_entry->target = cpu_to_le16(ddb_entry->fw_ddb_index); + marker_entry->modifier = cpu_to_le16(MM_LUN_RESET); + int_to_scsilun(lun, &marker_entry->lun); + wmb(); + + /* Tell ISP it's got a new I/O request */ + writel(ha->request_in, &ha->reg->req_q_in); + readl(&ha->reg->req_q_in); + +exit_send_marker: + spin_unlock_irqrestore(&ha->hardware_lock, flags); + return status; +} + +static inline struct continuation_t1_entry* qla4xxx_alloc_cont_entry( + struct scsi_qla_host *ha) +{ + struct continuation_t1_entry *cont_entry; + + cont_entry = (struct continuation_t1_entry *)ha->request_ptr; + + /* Advance request queue pointer */ + if (ha->request_in == (REQUEST_QUEUE_DEPTH - 1)) { + ha->request_in = 0; + ha->request_ptr = ha->request_ring; + } else { + ha->request_in++; + ha->request_ptr++; + } + + /* Load packet defaults */ + cont_entry->hdr.entryType = ET_CONTINUE; + cont_entry->hdr.entryCount = 1; + cont_entry->hdr.systemDefined = (uint8_t) cpu_to_le16(ha->request_in); + + return cont_entry; +} + +static inline uint16_t qla4xxx_calc_request_entries(uint16_t dsds) +{ + uint16_t iocbs; + + iocbs = 1; + if (dsds > COMMAND_SEG) { + iocbs += (dsds - COMMAND_SEG) / CONTINUE_SEG; + if ((dsds - COMMAND_SEG) % CONTINUE_SEG) + iocbs++; + } + return iocbs; +} + --- a/drivers/scsi/qla4xxx/ql4_iocb.c +++ b/drivers/scsi/qla4xxx/ql4_iocb.c @@ -11,133 +11,8 @@ #include "ql4_dbg.h" #include "ql4_inline.h" -#define VMWARE_CMD_TIMEOUT 30 #include -/** - * qla4xxx_get_req_pkt - returns a valid entry in request queue. - * @ha: Pointer to host adapter structure. - * @queue_entry: Pointer to pointer to queue entry structure - * - * This routine performs the following tasks: - * - returns the current request_in pointer (if queue not full) - * - advances the request_in pointer - * - checks for queue full - **/ -static int qla4xxx_get_req_pkt(struct scsi_qla_host *ha, - struct queue_entry **queue_entry) -{ - uint16_t request_in; - uint8_t status = QLA_SUCCESS; - - *queue_entry = ha->request_ptr; - - /* get the latest request_in and request_out index */ - request_in = ha->request_in; - ha->request_out = (uint16_t) le32_to_cpu(ha->shadow_regs->req_q_out); - - /* Advance request queue pointer and check for queue full */ - if (request_in == (REQUEST_QUEUE_DEPTH - 1)) { - request_in = 0; - ha->request_ptr = ha->request_ring; - } else { - request_in++; - ha->request_ptr++; - } - - /* request queue is full, try again later */ - if ((ha->iocb_cnt + 1) >= ha->iocb_hiwat) { - /* restore request pointer */ - ha->request_ptr = *queue_entry; - status = QLA_ERROR; - } else { - ha->request_in = request_in; - memset(*queue_entry, 0, sizeof(**queue_entry)); - } - - return status; -} - -/** - * qla4xxx_send_marker_iocb - issues marker iocb to HBA - * @ha: Pointer to host adapter structure. - * @ddb_entry: Pointer to device database entry - * @lun: SCSI LUN - * @marker_type: marker identifier - * - * This routine issues a marker IOCB. - **/ -int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha, - struct ddb_entry *ddb_entry, int lun) -{ - struct marker_entry *marker_entry; - unsigned long flags = 0; - uint8_t status = QLA_SUCCESS; - - /* Acquire hardware specific lock */ - spin_lock_irqsave(&ha->hardware_lock, flags); - - /* Get pointer to the queue entry for the marker */ - if (qla4xxx_get_req_pkt(ha, (struct queue_entry **) &marker_entry) != - QLA_SUCCESS) { - status = QLA_ERROR; - goto exit_send_marker; - } - - /* Put the marker in the request queue */ - marker_entry->hdr.entryType = ET_MARKER; - marker_entry->hdr.entryCount = 1; - marker_entry->target = cpu_to_le16(ddb_entry->fw_ddb_index); - marker_entry->modifier = cpu_to_le16(MM_LUN_RESET); - int_to_scsilun(lun, &marker_entry->lun); - wmb(); - - /* Tell ISP it's got a new I/O request */ - writel(ha->request_in, &ha->reg->req_q_in); - readl(&ha->reg->req_q_in); - -exit_send_marker: - spin_unlock_irqrestore(&ha->hardware_lock, flags); - return status; -} - -static struct continuation_t1_entry* qla4xxx_alloc_cont_entry( - struct scsi_qla_host *ha) -{ - struct continuation_t1_entry *cont_entry; - - cont_entry = (struct continuation_t1_entry *)ha->request_ptr; - - /* Advance request queue pointer */ - if (ha->request_in == (REQUEST_QUEUE_DEPTH - 1)) { - ha->request_in = 0; - ha->request_ptr = ha->request_ring; - } else { - ha->request_in++; - ha->request_ptr++; - } - - /* Load packet defaults */ - cont_entry->hdr.entryType = ET_CONTINUE; - cont_entry->hdr.entryCount = 1; - cont_entry->hdr.systemDefined = (uint8_t) cpu_to_le16(ha->request_in); - - return cont_entry; -} - -static uint16_t qla4xxx_calc_request_entries(uint16_t dsds) -{ - uint16_t iocbs; - - iocbs = 1; - if (dsds > COMMAND_SEG) { - iocbs += (dsds - COMMAND_SEG) / CONTINUE_SEG; - if ((dsds - COMMAND_SEG) % CONTINUE_SEG) - iocbs++; - } - return iocbs; -} - static void qla4xxx_build_scsi_iocbs(struct srb *srb, struct command_t3_entry *cmd_entry, uint16_t tot_dsds) @@ -224,6 +99,7 @@ int qla4xxx_send_command_to_isp(struct s /* Acquire hardware specific lock */ spin_lock_irqsave(&ha->hardware_lock, flags); + //index = (uint32_t)cmd->request->tag; index = ha->current_active_index; for (i = 0; i < MAX_SRBS; i++) { index++; @@ -242,10 +118,14 @@ int qla4xxx_send_command_to_isp(struct s } /* Calculate the number of request entries needed. */ - nseg = scsi_dma_map(cmd); - if (nseg < 0) - goto queuing_error; - tot_dsds = nseg; + if (srb->flags & SRB_SCSI_PASSTHRU) + tot_dsds = 1; + else { + nseg = scsi_dma_map(cmd); + if (nseg < 0) + goto queuing_error; + tot_dsds = nseg; + } req_cnt = qla4xxx_calc_request_entries(tot_dsds); @@ -281,9 +161,9 @@ int qla4xxx_send_command_to_isp(struct s cmd_entry->hdr.entryCount = req_cnt; /* Set data transfer direction control flags - * NOTE: Look at data_direction bits iff there is data to be - * transferred, as the data direction bit is sometimed filled - * in when there is no data to be transferred */ + * NOTE: Look at data_direction bits iff there is data to be + * transferred, as the data direction bit is sometimed filled + * in when there is no data to be transferred */ cmd_entry->control_flags = CF_NO_DATA; if (scsi_bufflen(cmd)) { if (cmd->sc_data_direction == DMA_TO_DEVICE) @@ -324,10 +204,10 @@ int qla4xxx_send_command_to_isp(struct s /* * Check to see if adapter is online before placing request on - * request queue. If a reset occurs and a request is in the queue, - * the firmware will still attempt to process the request, retrieving - * garbage for pointers. - */ + * request queue. If a reset occurs and a request is in the queue, + * the firmware will still attempt to process the request, retrieving + * garbage for pointers. + */ if (!test_bit(AF_ONLINE, &ha->flags)) { DEBUG2(printk("scsi%ld: %s: Adapter OFFLINE! " "Do not issue command.\n", @@ -355,13 +235,12 @@ int qla4xxx_send_command_to_isp(struct s return QLA_SUCCESS; queuing_error: - if (srb->flags & SRB_SCSI_PASSTHRU) - return QLA_ERROR; - - if (tot_dsds) - scsi_dma_unmap(cmd); + if (!(srb->flags & SRB_SCSI_PASSTHRU)) + if (tot_dsds) + scsi_dma_unmap(cmd); spin_unlock_irqrestore(&ha->hardware_lock, flags); return QLA_ERROR; } + --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c @@ -10,6 +10,7 @@ #include "ql4_glbl.h" #include "ql4_dbg.h" #include "ql4_inline.h" +#include "ql4_os.h" /** * qla4xxx_status_entry - processes status IOCBs @@ -59,8 +60,8 @@ static void qla4xxx_status_entry(struct break; } if (sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_UNDER) { - scsi_set_resid(cmd, residual); - if (!scsi_status && ((scsi_bufflen(cmd) - residual) < + QL_SET_SCSI_RESID(cmd, residual); + if (!scsi_status && ((QL_SCSI_BUFFLEN(cmd) - residual) < cmd->underflow)) { cmd->result = DID_ERROR << 16; break; @@ -144,7 +145,7 @@ static void qla4xxx_status_entry(struct break; } - scsi_set_resid(cmd, residual); + QL_SET_SCSI_RESID(cmd, residual); /* * If there is scsi_status, it takes precedense over @@ -184,7 +185,7 @@ static void qla4xxx_status_entry(struct if ((sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_UNDER) == 0) { cmd->result = DID_BUS_BUSY << 16; - } else if ((scsi_bufflen(cmd) - residual) < + } else if ((QL_SCSI_BUFFLEN(cmd) - residual) < cmd->underflow) { /* * Handle mid-layer underflow??? @@ -203,7 +204,7 @@ static void qla4xxx_status_entry(struct "resid = 0x%x, compstat = 0x%x\n", ha->host_no, cmd->device->channel, cmd->device->id, cmd->device->lun, - __func__, scsi_bufflen(cmd), + __func__, QL_SCSI_BUFFLEN(cmd), residual, sts_entry->completionStatus)); @@ -396,13 +397,13 @@ static void qla4xxx_isr_decode_mailbox(s /* Immediately process the AENs that don't require much work. * Only queue the database_changed AENs */ - dev_info(&ha->pdev->dev, "%s mbx0 0x%08x mbx1 0x%08x" + DEBUG6(dev_info(&ha->pdev->dev, "%s mbx0 0x%08x mbx1 0x%08x" " mbx2 0x%08x mbx3 0x%08x mbx4 0x%08x mbx5 0x%08x " "mbx6 0x%08x mbx7 0x%08x\n", __func__, readl(&ha->reg->mailbox[0]), readl(&ha->reg->mailbox[1]), readl(&ha->reg->mailbox[2]), readl(&ha->reg->mailbox[3]), readl(&ha->reg->mailbox[4]), readl(&ha->reg->mailbox[5]), - readl(&ha->reg->mailbox[6]), readl(&ha->reg->mailbox[7])); + readl(&ha->reg->mailbox[6]), readl(&ha->reg->mailbox[7]))); if (ha->aen_log.count < MAX_AEN_ENTRIES) { for (i = 0; i < MBOX_AEN_REG_COUNT; i++) @@ -412,11 +413,13 @@ static void qla4xxx_isr_decode_mailbox(s } switch (mbox_status) { case MBOX_ASTS_SYSTEM_ERROR: + dev_info(&ha->pdev->dev, "%s: System Err\n", __func__); /* Log Mailbox registers */ if (ql4xdontresethba) { DEBUG2(printk("%s:Dont Reset HBA\n", __func__)); } else { + qla4xxx_hw_reset(ha, 0); set_bit(AF_GET_CRASH_RECORD, &ha->flags); set_bit(DPC_RESET_HA, &ha->dpc_flags); } @@ -433,15 +436,13 @@ static void qla4xxx_isr_decode_mailbox(s break; case MBOX_ASTS_LINK_UP: - DEBUG2(printk("scsi%ld: AEN %04x Adapter LINK UP\n", - ha->host_no, mbox_status)); set_bit(AF_LINK_UP, &ha->flags); + dev_info(&ha->pdev->dev, "%s: LINK UP\n", __func__); break; case MBOX_ASTS_LINK_DOWN: - DEBUG2(printk("scsi%ld: AEN %04x Adapter LINK DOWN\n", - ha->host_no, mbox_status)); clear_bit(AF_LINK_UP, &ha->flags); + dev_info(&ha->pdev->dev, "%s: LINK DOWN\n", __func__); break; case MBOX_ASTS_HEARTBEAT: @@ -470,9 +471,9 @@ static void qla4xxx_isr_decode_mailbox(s mbox_stat2 = readl(&ha->reg->mailbox[2]); mbox_stat3 = readl(&ha->reg->mailbox[3]); - if ((mbox_stat3 == 5) && (mbox_stat2 == 3)) + if ((mbox_stat3 == 5) && (mbox_stat2 == 3)) set_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags); - else if ((mbox_stat3 == 2) && (mbox_stat2 == 5)) + else if ((mbox_stat3 == 2) && (mbox_stat2 == 5)) set_bit(DPC_RESET_HA, &ha->dpc_flags); break; @@ -591,10 +592,10 @@ void qla4xxx_interrupt_service_routine(s * qla4xxx_intr_handler - hardware interrupt handler. * @irq: Unused * @dev_id: Pointer to host adapter structure + * @regs: Unused **/ -irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id) +QL_DECLARE_INTR_HANDLER(qla4xxx_intr_handler, irq, dev_id, regs) { - struct scsi_qla_host *ha; uint32_t intr_status; unsigned long flags = 0; @@ -625,8 +626,7 @@ irqreturn_t qla4xxx_intr_handler(int irq intr_status = readl(&ha->reg->ctrl_status); if ((intr_status & - (CSR_SCSI_RESET_INTR|CSR_FATAL_ERROR|INTR_PENDING)) == - 0) { + (CSR_SCSI_RESET_INTR|CSR_FATAL_ERROR|INTR_PENDING)) == 0) { if (reqs_count == 0) ha->spurious_int_count++; break; @@ -662,6 +662,8 @@ irqreturn_t qla4xxx_intr_handler(int irq break; } else if (intr_status & CSR_SCSI_RESET_INTR) { clear_bit(AF_ONLINE, &ha->flags); + dev_info(&ha->pdev->dev,"%s: adapter OFFLINE\n", + __func__); __qla4xxx_disable_intrs(ha); writel(set_rmask(CSR_SCSI_RESET_INTR), --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -10,6 +10,7 @@ #include "ql4_glbl.h" #include "ql4_dbg.h" #include "ql4_inline.h" +#include "ql4_os.h" /** @@ -43,6 +44,7 @@ int qla4xxx_mailbox_command(struct scsi_ /* Mailbox code active */ wait_count = MBOX_TOV * 100; + while (wait_count--) { mutex_lock(&ha->mbox_sem); if (!test_bit(AF_MBOX_COMMAND, &ha->flags)) { @@ -166,6 +168,8 @@ int qla4xxx_mailbox_command(struct scsi_ spin_unlock_irqrestore(&ha->hardware_lock, flags); mbox_exit: + if (status == QLA_SUCCESS) + qla4xxx_check_for_clear_ddb(ha, mbx_cmd); mutex_lock(&ha->mbox_sem); clear_bit(AF_MBOX_COMMAND, &ha->flags); mutex_unlock(&ha->mbox_sem); @@ -851,8 +855,8 @@ int qla4xxx_get_flash(struct scsi_qla_ho * 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, + * 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) @@ -882,8 +886,7 @@ int qla4xxx_get_fw_version(struct scsi_q return QLA_SUCCESS; } -static int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, - dma_addr_t dma_addr) +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]; --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -15,6 +15,8 @@ #include "ql4_glbl.h" #include "ql4_dbg.h" #include "ql4_inline.h" +#include "ql4_os.h" + /* * Driver version @@ -56,24 +58,32 @@ MODULE_PARM_DESC(extended_error_logging, "Option to enable extended error logging, " "Default is 0 - no logging, 1 - debug logging"); +/* Command Timeout before ddb state goes to MISSING */ +int cmd_timeout = IOCB_CMD_TIMEOUT; +module_param(cmd_timeout, int, S_IRUGO | S_IRUSR); +MODULE_PARM_DESC(cmd_timeout, "Command Timeout"); + +/* Timeout before ddb state MISSING goes DEAD */ +int recovery_tmo = RECOVERY_TIMEOUT; +module_param(recovery_tmo, int, S_IRUGO | S_IRUSR); +MODULE_PARM_DESC(recovery_tmo, "Recovery Timeout"); + int ql4_mod_unload = 0; /* * SCSI host template entry points */ -static void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha); + +void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha); /* * iSCSI template entry points */ -static int qla4xxx_tgt_dscvr(struct Scsi_Host *shost, - enum iscsi_tgt_dscvr type, uint32_t enable, - struct sockaddr *dst_addr); +static int qla4xxx_host_get_param(struct Scsi_Host *, + enum iscsi_host_param, char *); static int qla4xxx_conn_get_param(struct iscsi_cls_conn *conn, enum iscsi_param param, char *buf); static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess, enum iscsi_param param, char *buf); -static int qla4xxx_host_get_param(struct Scsi_Host *shost, - enum iscsi_host_param param, char *buf); static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session); /* @@ -85,11 +95,13 @@ static int qla4xxx_eh_device_reset(struc static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd); static int qla4xxx_slave_alloc(struct scsi_device *device); static int qla4xxx_slave_configure(struct scsi_device *device); +static void qla4xxx_slave_destroy(struct scsi_device *device); static struct scsi_host_template qla4xxx_driver_template = { .module = THIS_MODULE, .name = DRIVER_NAME, .proc_name = DRIVER_NAME, + .proc_info = qla4xxx_proc_info, .queuecommand = qla4xxx_queuecommand, .eh_device_reset_handler = qla4xxx_eh_device_reset, @@ -97,6 +109,7 @@ static struct scsi_host_template qla4xxx .slave_configure = qla4xxx_slave_configure, .slave_alloc = qla4xxx_slave_alloc, + .slave_destroy = qla4xxx_slave_destroy, .this_id = -1, .cmd_per_lun = 3, @@ -113,10 +126,13 @@ static struct iscsi_transport qla4xxx_is ISCSI_CONN_ADDRESS | ISCSI_TARGET_NAME | ISCSI_TPGT, - .tgt_dscvr = qla4xxx_tgt_dscvr, + + QL_INIT_SESSION_DATASIZE(sessiondata_size) + QL_INIT_HOST_TEMPLATE(host_template) + + .get_host_param = qla4xxx_host_get_param, .get_conn_param = qla4xxx_conn_get_param, .get_session_param = qla4xxx_sess_get_param, - .get_host_param = qla4xxx_host_get_param, .session_recovery_timedout = qla4xxx_recovery_timedout, }; @@ -134,31 +150,9 @@ static void qla4xxx_recovery_timedout(st ddb_entry->fw_ddb_index, ddb_entry->os_target_id, ha->port_down_retry_count); - DEBUG2(printk("scsi%ld: %s: scheduling dpc routine - dpc flags = " - "0x%lx\n", ha->host_no, __func__, ha->dpc_flags)); - queue_work(ha->dpc_thread, &ha->dpc_work); -} - -static int qla4xxx_host_get_param(struct Scsi_Host *shost, - enum iscsi_host_param param, char *buf) -{ - struct scsi_qla_host *ha = to_qla_host(shost); - int len; - - switch (param) { - case ISCSI_HOST_PARAM_IPADDRESS: - len = sprintf(buf, "%d.%d.%d.%d", ha->ip_address[0], - ha->ip_address[1], ha->ip_address[2], - ha->ip_address[3]); - break; - case ISCSI_HOST_PARAM_INITIATOR_NAME: - len = sprintf(buf, "%s", ha->name_string); - break; - default: - return -ENOSYS; - } + QL_SET_DDB_OFFLINE(ha, ddb_entry); - return len; + queue_work(ha->dpc_thread, &ha->dpc_work); } int qla4xxx_conn_start(struct iscsi_cls_conn *conn) @@ -166,7 +160,8 @@ int qla4xxx_conn_start(struct iscsi_cls_ struct iscsi_cls_session *session; struct ddb_entry *ddb_entry; - session = iscsi_dev_to_session(conn->dev.parent); + session = QL_ISCSI_CONN_TO_SESS(conn); + ddb_entry = session->dd_data; DEBUG2(printk("scsi%ld: %s: index [%d] starting conn\n", @@ -181,7 +176,8 @@ static void qla4xxx_conn_stop(struct isc struct iscsi_cls_session *session; struct ddb_entry *ddb_entry; - session = iscsi_dev_to_session(conn->dev.parent); + session = QL_ISCSI_CONN_TO_SESS(conn); + ddb_entry = session->dd_data; DEBUG2(printk("scsi%ld: %s: index [%d] stopping conn\n", @@ -207,6 +203,12 @@ static int qla4xxx_sess_get_param(struct case ISCSI_PARAM_TPGT: len = sprintf(buf, "%u", ddb_entry->tpgt); break; + +#ifdef ISCSI_ISID + case ISCSI_PARAM_ISID: + len = sprintf(buf, "%u", QL_ISCSI_SESSION_ID(ddb_entry)); + break; +#endif default: return -ENOSYS; } @@ -221,7 +223,8 @@ static int qla4xxx_conn_get_param(struct struct ddb_entry *ddb_entry; int len; - session = iscsi_dev_to_session(conn->dev.parent); + session = QL_ISCSI_CONN_TO_SESS(conn); + ddb_entry = session->dd_data; switch (param) { @@ -240,47 +243,53 @@ static int qla4xxx_conn_get_param(struct return len; } -static int qla4xxx_tgt_dscvr(struct Scsi_Host *shost, - enum iscsi_tgt_dscvr type, uint32_t enable, - struct sockaddr *dst_addr) +static int qla4xxx_host_get_param(struct Scsi_Host *shost, + enum iscsi_host_param param, char *buf) { - struct scsi_qla_host *ha; - struct sockaddr_in *addr; - struct sockaddr_in6 *addr6; - int ret = 0; - - ha = (struct scsi_qla_host *) shost->hostdata; - - switch (type) { - case ISCSI_TGT_DSCVR_SEND_TARGETS: - if (dst_addr->sa_family == AF_INET) { - addr = (struct sockaddr_in *)dst_addr; - if (qla4xxx_send_tgts(ha, (char *)&addr->sin_addr, - addr->sin_port) != QLA_SUCCESS) - ret = -EIO; - } else if (dst_addr->sa_family == AF_INET6) { - /* - * TODO: fix qla4xxx_send_tgts - */ - addr6 = (struct sockaddr_in6 *)dst_addr; - if (qla4xxx_send_tgts(ha, (char *)&addr6->sin6_addr, - addr6->sin6_port) != QLA_SUCCESS) - ret = -EIO; - } else - ret = -ENOSYS; + struct scsi_qla_host *ha = to_qla_host(shost); + int len; + + switch (param) { + case ISCSI_HOST_PARAM_IPADDRESS: + len = sprintf(buf, "%d.%d.%d.%d", ha->ip_address[0], + ha->ip_address[1], ha->ip_address[2], + ha->ip_address[3]); + break; + case ISCSI_HOST_PARAM_INITIATOR_NAME: + len = sprintf(buf, "%s", ha->name_string); break; default: - ret = -ENOSYS; + return -ENOSYS; } - return ret; + + return len; +} + +static int ql_alloc_osindex(struct scsi_qla_host *ha) +{ + unsigned int idx; + + for (idx = 0; idx < MAX_DDB_ENTRIES; idx++) + if (test_and_set_bit((idx & 0x1F), &ha->os_map[(idx >> 5)]) == 0) + return idx; + return -1; +} + +static void free_osindex(struct scsi_qla_host *ha, uint32_t idx) +{ + clear_bit((idx & 0x1F), &ha->os_map[idx >> 5]); } + void qla4xxx_destroy_sess(struct ddb_entry *ddb_entry) { if (!ddb_entry->sess) return; + free_osindex(ddb_entry->ha, ddb_entry->os_target_id); if (ddb_entry->conn) { + QL_ISCSI_IF_DESTROY_SESSION_DONE(ddb_entry); + QL_ISCSI_DESTROY_CONN(ddb_entry); iscsi_remove_session(ddb_entry->sess); } iscsi_free_session(ddb_entry->sess); @@ -290,25 +299,27 @@ int qla4xxx_add_sess(struct ddb_entry *d { int err; - err = iscsi_add_session(ddb_entry->sess, ddb_entry->fw_ddb_index); + err = QL_ISCSI_ADD_SESS(ddb_entry); + if (err) { DEBUG2(printk(KERN_ERR "Could not add session.\n")); return err; } - ddb_entry->conn = iscsi_create_conn(ddb_entry->sess, 0, 0); + ddb_entry->conn = QL_ISCSI_CREATE_CONN(ddb_entry); + if (!ddb_entry->conn) { iscsi_remove_session(ddb_entry->sess); DEBUG2(printk(KERN_ERR "Could not add connection.\n")); return -ENOMEM; } - ddb_entry->sess->recovery_tmo = ddb_entry->ha->port_down_retry_count; - if (scan) - scsi_scan_target(&ddb_entry->sess->dev, 0, - ddb_entry->sess->target_id, - SCAN_WILD_CARD, 0); - iscsi_unblock_session(ddb_entry->sess); + ddb_entry->sess->recovery_tmo = QL_SESS_RECOVERY_TO(ddb_entry); + + qla4xxx_scan_target(ddb_entry); + + QL_ISCSI_CREATE_SESS_DONE(ddb_entry); + return 0; } @@ -317,13 +328,20 @@ struct ddb_entry *qla4xxx_alloc_sess(str struct ddb_entry *ddb_entry; struct iscsi_cls_session *sess; - sess = iscsi_alloc_session(ha->host, &qla4xxx_iscsi_transport, - sizeof(struct ddb_entry)); - if (!sess) + int os_idx; + + if ((os_idx = ql_alloc_osindex(ha)) >= MAX_DDB_ENTRIES) + return NULL; + + sess = QL_ISCSI_ALLOC_SESSION(ha, &qla4xxx_iscsi_transport); + if (!sess) { + free_osindex(ha, os_idx); return NULL; + } ddb_entry = sess->dd_data; memset(ddb_entry, 0, sizeof(*ddb_entry)); + ddb_entry->os_target_id = os_idx; ddb_entry->ha = ha; ddb_entry->sess = sess; return ddb_entry; @@ -371,9 +389,9 @@ void qla4xxx_mark_device_missing(struct } static struct srb* qla4xxx_get_new_srb(struct scsi_qla_host *ha, - struct ddb_entry *ddb_entry, - struct scsi_cmnd *cmd, - void (*done)(struct scsi_cmnd *)) + struct ddb_entry *ddb_entry, + struct scsi_cmnd *cmd, + void (*done)(struct scsi_cmnd *)) { struct srb *srb; @@ -392,17 +410,6 @@ static struct srb* qla4xxx_get_new_srb(s return srb; } -static void qla4xxx_srb_free_dma(struct scsi_qla_host *ha, struct srb *srb) -{ - struct scsi_cmnd *cmd = srb->cmd; - - if (srb->flags & SRB_DMA_VALID) { - scsi_dma_unmap(cmd); - srb->flags &= ~SRB_DMA_VALID; - } - cmd->SCp.ptr = NULL; -} - void qla4xxx_srb_compl(struct scsi_qla_host *ha, struct srb *srb) { struct scsi_cmnd *cmd = srb->cmd; @@ -418,14 +425,14 @@ void qla4xxx_srb_compl(struct scsi_qla_h * qla4xxx_queuecommand - scsi layer issues scsi command to driver. * @cmd: Pointer to Linux's SCSI command structure * @done_fn: Function that the driver calls to notify the SCSI mid-layer - * that the command has been processed. + * that the command has been processed. * * Remarks: * This routine is invoked by Linux to send a SCSI command to the driver. * The mid-level driver tries to ensure that queuecommand never gets * invoked concurrently with itself or the interrupt handler (although * the interrupt handler may call this routine as part of request- - * completion handling). Unfortunely, it sometimes calls the scheduler + * completion handling). Unfortunely, it sometimes calls the scheduler * in interrupt context which is a big NO! NO!. **/ static int qla4xxx_queuecommand(struct scsi_cmnd *cmd, @@ -546,7 +553,7 @@ static int qla4xxx_mem_alloc(struct scsi align = 0; if ((unsigned long)ha->queues_dma & (MEM_ALIGN_VALUE - 1)) align = MEM_ALIGN_VALUE - ((unsigned long)ha->queues_dma & - (MEM_ALIGN_VALUE - 1)); + (MEM_ALIGN_VALUE - 1)); /* Update request and response queue pointers. */ ha->request_dma = ha->queues_dma + align; @@ -554,16 +561,16 @@ static int qla4xxx_mem_alloc(struct scsi ha->response_dma = ha->queues_dma + align + (REQUEST_QUEUE_DEPTH * QUEUE_SIZE); ha->response_ring = (struct queue_entry *) (ha->queues + align + - (REQUEST_QUEUE_DEPTH * - QUEUE_SIZE)); + (REQUEST_QUEUE_DEPTH * + QUEUE_SIZE)); ha->shadow_regs_dma = ha->queues_dma + align + (REQUEST_QUEUE_DEPTH * QUEUE_SIZE) + (RESPONSE_QUEUE_DEPTH * QUEUE_SIZE); ha->shadow_regs = (struct shadow_regs *) (ha->queues + align + (REQUEST_QUEUE_DEPTH * - QUEUE_SIZE) + + QUEUE_SIZE) + (RESPONSE_QUEUE_DEPTH * - QUEUE_SIZE)); + QUEUE_SIZE)); /* Allocate memory for srb pool. */ ha->srb_mempool = mempool_create(SRB_MIN_REQ, mempool_alloc_slab, @@ -595,12 +602,12 @@ static void qla4xxx_timer(struct scsi_ql list_for_each_entry_safe(ddb_entry, dtemp, &ha->ddb_list, list) { /* Count down time between sending relogins */ if (adapter_up(ha) && - !test_bit(DF_RELOGIN, &ddb_entry->flags) && - atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) { + !test_bit(DF_RELOGIN, &ddb_entry->flags) && + atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) { if (atomic_read(&ddb_entry->retry_relogin_timer) != - INVALID_ENTRY) { + INVALID_ENTRY) { if (atomic_read(&ddb_entry->retry_relogin_timer) - == 0) { + == 0) { atomic_set(&ddb_entry-> retry_relogin_timer, INVALID_ENTRY); @@ -608,9 +615,9 @@ static void qla4xxx_timer(struct scsi_ql &ha->dpc_flags); set_bit(DF_RELOGIN, &ddb_entry->flags); DEBUG2(printk("scsi%ld: %s: index [%d]" - " login device\n", - ha->host_no, __func__, - ddb_entry->fw_ddb_index)); + " login device\n", + ha->host_no, __func__, + ddb_entry->fw_ddb_index)); } else atomic_dec(&ddb_entry-> retry_relogin_timer); @@ -619,64 +626,64 @@ static void qla4xxx_timer(struct scsi_ql /* Wait for relogin to timeout */ if (atomic_read(&ddb_entry->relogin_timer) && - (atomic_dec_and_test(&ddb_entry->relogin_timer) != 0)) { + (atomic_dec_and_test(&ddb_entry->relogin_timer) != 0)) { /* * If the relogin times out and the device is * still NOT ONLINE then try and relogin again. */ if (atomic_read(&ddb_entry->state) != - DDB_STATE_ONLINE && - ddb_entry->fw_ddb_device_state == - DDB_DS_SESSION_FAILED) { + DDB_STATE_ONLINE && + ddb_entry->fw_ddb_device_state == + DDB_DS_SESSION_FAILED) { /* Reset retry relogin timer */ atomic_inc(&ddb_entry->relogin_retry_count); DEBUG2(printk("scsi%ld: index[%d] relogin" - " timed out-retrying" - " relogin (%d)\n", - ha->host_no, - ddb_entry->fw_ddb_index, - atomic_read(&ddb_entry-> + " timed out-retrying" + " relogin (%d)\n", + ha->host_no, + ddb_entry->fw_ddb_index, + atomic_read(&ddb_entry-> relogin_retry_count)) ); start_dpc++; DEBUG(printk("scsi%ld:%d:%d: index [%d] " - "initate relogin after" - " %d seconds\n", - ha->host_no, ddb_entry->bus, - ddb_entry->target, - ddb_entry->fw_ddb_index, - ddb_entry->default_time2wait + 4) - ); + "initate relogin after" + " %d seconds\n", + ha->host_no, ddb_entry->bus, + ddb_entry->target, + ddb_entry->fw_ddb_index, + ddb_entry->default_time2wait + 4)); atomic_set(&ddb_entry->retry_relogin_timer, - ddb_entry->default_time2wait + 4); + ddb_entry->default_time2wait + 4); } } } /* Check for heartbeat interval. */ if (ha->firmware_options & FWOPT_HEARTBEAT_ENABLE && - ha->heartbeat_interval != 0) { + ha->heartbeat_interval != 0) { ha->seconds_since_last_heartbeat++; if (ha->seconds_since_last_heartbeat > - ha->heartbeat_interval + 2) + ha->heartbeat_interval + 2) set_bit(DPC_RESET_HA, &ha->dpc_flags); } /* Wakeup the dpc routine for this adapter, if needed. */ if ((start_dpc || - test_bit(DPC_RESET_HA, &ha->dpc_flags) || - test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags) || - test_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags) || - test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags) || - test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || - test_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags) || - test_bit(DPC_AEN, &ha->dpc_flags)) && - ha->dpc_thread) { + test_bit(DPC_RESET_HA, &ha->dpc_flags) || + test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags) || + test_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags) || + test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags) || + test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || + test_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags) || + QL_DPC_OFFLINE_SET(ha) || + test_bit(DPC_AEN, &ha->dpc_flags)) && + ha->dpc_thread) { DEBUG2(printk("scsi%ld: %s: scheduling dpc routine" - " - dpc flags = 0x%lx\n", - ha->host_no, __func__, ha->dpc_flags)); + " - dpc flags = 0x%lx\n", + ha->host_no, __func__, ha->dpc_flags)); queue_work(ha->dpc_thread, &ha->dpc_work); } @@ -732,14 +739,15 @@ static int qla4xxx_cmd_wait(struct scsi_ return stat; } -void qla4xxx_hw_reset(struct scsi_qla_host *ha) +void qla4xxx_hw_reset(struct scsi_qla_host *ha, int hw_lock) { uint32_t ctrl_status; unsigned long flags = 0; DEBUG2(printk(KERN_ERR "scsi%ld: %s\n", ha->host_no, __func__)); - spin_lock_irqsave(&ha->hardware_lock, flags); + if (hw_lock) + spin_lock_irqsave(&ha->hardware_lock, flags); /* * If the SCSI Reset Interrupt bit is set, clear it. * Otherwise, the Soft Reset won't work. @@ -752,7 +760,8 @@ void qla4xxx_hw_reset(struct scsi_qla_ho writel(set_rmask(CSR_SOFT_RESET), &ha->reg->ctrl_status); readl(&ha->reg->ctrl_status); - spin_unlock_irqrestore(&ha->hardware_lock, flags); + if (hw_lock) + spin_unlock_irqrestore(&ha->hardware_lock, flags); } /** @@ -766,7 +775,7 @@ int qla4xxx_soft_reset(struct scsi_qla_h int status = QLA_ERROR; uint32_t ctrl_status; - qla4xxx_hw_reset(ha); + qla4xxx_hw_reset(ha, 1); /* Wait until the Network Reset Intr bit is cleared */ max_wait_time = RESET_INTR_TOV; @@ -783,9 +792,9 @@ int qla4xxx_soft_reset(struct scsi_qla_h if ((ctrl_status & CSR_NET_RESET_INTR) != 0) { DEBUG2(printk(KERN_WARNING - "scsi%ld: Network Reset Intr not cleared by " - "Network function, clearing it now!\n", - ha->host_no)); + "scsi%ld: Network Reset Intr not cleared by " + "Network function, clearing it now!\n", + ha->host_no)); spin_lock_irqsave(&ha->hardware_lock, flags); writel(set_rmask(CSR_NET_RESET_INTR), &ha->reg->ctrl_status); readl(&ha->reg->ctrl_status); @@ -881,14 +890,13 @@ static void qla4xxx_flush_active_srbs(st * qla4xxx_recover_adapter - recovers adapter after a fatal error * @ha: Pointer to host adapter structure. **/ -static int qla4xxx_recover_adapter(struct scsi_qla_host *ha) +static int qla4xxx_recover_adapter(struct scsi_qla_host *ha) { int status; /* Stall incoming I/O until we are done */ clear_bit(AF_ONLINE, &ha->flags); - DEBUG2(printk("scsi%ld: %s calling qla4xxx_cmd_wait\n", ha->host_no, - __func__)); + dev_info(&ha->pdev->dev, "%s: adapter OFFLINE\n", __func__); /* Wait for outstanding commands to complete. * Stalls the driver for max 30 secs @@ -905,7 +913,7 @@ static int qla4xxx_recover_adapter(struc */ if (status == QLA_SUCCESS) { DEBUG2(printk(KERN_ERR "scsi%ld: %s - Performing soft reset..\n", - ha->host_no, __func__)); + ha->host_no, __func__)); qla4xxx_flush_active_srbs(ha); if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) status = qla4xxx_soft_reset(ha); @@ -920,24 +928,26 @@ static int qla4xxx_recover_adapter(struc * with ISP interrupts enabled */ if (status == QLA_SUCCESS) { DEBUG2(printk("scsi%ld: %s - Initializing adapter..\n", - ha->host_no, __func__)); + ha->host_no, __func__)); /* If successful, AF_ONLINE flag set in * qla4xxx_initialize_adapter */ + if (ha->mac_index == 3) + ssleep(6); status = qla4xxx_initialize_adapter(ha, PRESERVE_DDB_LIST); } /* Failed adapter initialization? * Retry reset_ha only if invoked via DPC (DPC_RESET_HA) */ if ((test_bit(AF_ONLINE, &ha->flags) == 0) && - (test_bit(DPC_RESET_HA, &ha->dpc_flags))) { + (test_bit(DPC_RESET_HA, &ha->dpc_flags))) { /* Adapter initialization failed, see if we can retry * resetting the ha */ if (!test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags)) { ha->retry_reset_ha_cnt = MAX_RESET_HA_RETRIES; DEBUG2(printk("scsi%ld: recover adapter - retrying " - "(%d) more times\n", ha->host_no, - ha->retry_reset_ha_cnt)); + "(%d) more times\n", ha->host_no, + ha->retry_reset_ha_cnt)); set_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags); status = QLA_ERROR; } else { @@ -945,9 +955,9 @@ static int qla4xxx_recover_adapter(struc /* Schedule another Reset HA--DPC will retry */ ha->retry_reset_ha_cnt--; DEBUG2(printk("scsi%ld: recover adapter - " - "retry remaining %d\n", - ha->host_no, - ha->retry_reset_ha_cnt)); + "retry remaining %d\n", + ha->host_no, + ha->retry_reset_ha_cnt)); status = QLA_ERROR; } @@ -955,8 +965,8 @@ static int qla4xxx_recover_adapter(struc /* Recover adapter retries have been exhausted. * Adapter DEAD */ DEBUG2(printk("scsi%ld: recover adapter " - "failed - board disabled\n", - ha->host_no)); + "failed - board disabled\n", + ha->host_no)); qla4xxx_flush_active_srbs(ha); clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags); clear_bit(DPC_RESET_HA, &ha->dpc_flags); @@ -991,10 +1001,9 @@ static int qla4xxx_recover_adapter(struc * the mid-level tries to sleep when it reaches the driver threshold * "host->can_queue". This can cause a panic if we were in our interrupt code. **/ -static void qla4xxx_do_dpc(struct work_struct *work) +static QL_DECLARE_DPC(qla4xxx_do_dpc, data) { - struct scsi_qla_host *ha = - container_of(work, struct scsi_qla_host, dpc_work); + struct scsi_qla_host *ha = QL_DPC_DATA_TO_HA(data); struct ddb_entry *ddb_entry, *dtemp; int status = QLA_ERROR; @@ -1009,11 +1018,11 @@ static void qla4xxx_do_dpc(struct work_s return; if (adapter_up(ha) || - test_bit(DPC_RESET_HA, &ha->dpc_flags) || - test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || - test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags)) { + test_bit(DPC_RESET_HA, &ha->dpc_flags) || + test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || + test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags)) { if (test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags) || - test_bit(DPC_RESET_HA, &ha->dpc_flags)) + test_bit(DPC_RESET_HA, &ha->dpc_flags)) qla4xxx_recover_adapter(ha); if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) { @@ -1025,14 +1034,15 @@ static void qla4xxx_do_dpc(struct work_s break; msleep(1000); } + if (wait_time == 0) DEBUG2(printk("scsi%ld: %s: SR|FSR " - "bit not cleared-- resetting\n", - ha->host_no, __func__)); + "bit not cleared-- resetting\n", + ha->host_no, __func__)); qla4xxx_flush_active_srbs(ha); if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) { qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); - status = qla4xxx_initialize_adapter(ha, + status = qla4xxx_initialize_adapter(ha, PRESERVE_DDB_LIST); } clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags); @@ -1049,13 +1059,42 @@ static void qla4xxx_do_dpc(struct work_s if (test_and_clear_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags)) qla4xxx_get_dhcp_ip_address(ha); + qla4xxx_check_dev_offline(ha); + + if (test_and_clear_bit(DPC_DELETE_DEVICE, &ha->dpc_flags)) { + list_for_each_entry_safe(ddb_entry, dtemp, + &ha->ddb_list, list) { + if (test_and_clear_bit(DF_DELETED, + &ddb_entry->flags)) { + if (atomic_read(&ddb_entry->state) == + DDB_STATE_DEAD) { + dev_info(&ha->pdev->dev, + "%s: ddb[%d] os[%d] - " + "delete\n", + __func__, + ddb_entry->fw_ddb_index, + ddb_entry->os_target_id); + } else { + dev_info(&ha->pdev->dev, + "%s: ddb[%d] os[%d] - " + "ddb state not dead but" + " marked for delete\n", + __func__, + ddb_entry->fw_ddb_index, + ddb_entry->os_target_id); + } + } + } + } + /* ---- relogin device? --- */ if (adapter_up(ha) && - test_and_clear_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags)) { + test_and_clear_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags)) { list_for_each_entry_safe(ddb_entry, dtemp, &ha->ddb_list, list) { if (test_and_clear_bit(DF_RELOGIN, &ddb_entry->flags) && - atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) + (atomic_read(&ddb_entry->state) != + DDB_STATE_ONLINE)) qla4xxx_relogin_device(ha, ddb_entry); /* @@ -1092,7 +1131,7 @@ static void qla4xxx_free_adapter(struct /* Issue Soft Reset to put firmware in unknown state */ if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) - qla4xxx_hw_reset(ha); + qla4xxx_hw_reset(ha, 1); /* Remove timer thread, if present */ if (ha->timer_active) @@ -1142,6 +1181,7 @@ static int qla4xxx_iospace_config(struct if (!(mmio_flags & IORESOURCE_MEM)) { dev_err(&ha->pdev->dev, "region #0 not an MMIO resource, aborting\n"); + goto iospace_error_exit; } if (mmio_len < MIN_IOBASE_LEN) { @@ -1173,14 +1213,6 @@ iospace_error_exit: return -ENOMEM; } -static void ql4_get_aen_log(struct scsi_qla_host *ha, struct ql4_aen_log *aenl) -{ - if (aenl) { - memcpy(aenl, &ha->aen_log, sizeof (ha->aen_log)); - ha->aen_log.count = 0; - } -} - /** * qla4xxx_probe_adapter - callback function to probe HBA * @pdev: pointer to pci_dev structure @@ -1191,7 +1223,7 @@ static void ql4_get_aen_log(struct scsi_ * the driver. **/ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, - const struct pci_device_id *ent) + const struct pci_device_id *ent) { int ret = -ENODEV, status; struct Scsi_Host *host; @@ -1206,7 +1238,7 @@ static int __devinit qla4xxx_probe_adapt host = scsi_host_alloc(&qla4xxx_driver_template, sizeof(*ha)); if (host == NULL) { printk(KERN_WARNING - "qla4xxx: Couldn't allocate host from scsi layer!\n"); + "qla4xxx: Couldn't allocate host from scsi layer!\n"); goto probe_disable_device; } @@ -1218,10 +1250,7 @@ static int __devinit qla4xxx_probe_adapt ha->pdev = pdev; ha->host = host; ha->host_no = host->host_no; - - ha->ql4mbx = qla4xxx_mailbox_command; - ha->ql4cmd = qla4xxx_send_command_to_isp; - ha->ql4getaenlog = ql4_get_aen_log; + set_bit(AF_OS_INDEX_VALID, &ha->flags); /* Configure PCI I/O space. */ ret = qla4xxx_iospace_config(ha); @@ -1229,7 +1258,7 @@ static int __devinit qla4xxx_probe_adapt goto probe_failed; dev_info(&ha->pdev->dev, "Found an ISP%04x, irq %d, iobase 0x%p\n", - pdev->device, pdev->irq, ha->reg); + pdev->device, pdev->irq, ha->reg); qla4xxx_config_dma_addressing(ha); @@ -1245,7 +1274,7 @@ static int __devinit qla4xxx_probe_adapt /* Allocate dma buffers */ if (qla4xxx_mem_alloc(ha)) { dev_warn(&ha->pdev->dev, - "[ERROR] Failed to allocate memory for adapter\n"); + "[ERROR] Failed to allocate memory for adapter\n"); ret = -ENOMEM; goto probe_failed; @@ -1258,8 +1287,8 @@ static int __devinit qla4xxx_probe_adapt */ status = qla4xxx_initialize_adapter(ha, REBUILD_DDB_LIST); while (status == QLA_ERROR && init_retry_count++ < MAX_INIT_RETRIES) { - DEBUG2(printk(KERN_ERR "scsi%ld: %s: retrying adapter initialization " - "(%d)\n", ha->host_no, __func__, init_retry_count)); + DEBUG2(dev_info(&ha->pdev->dev, "%s: retry adapter init %d\n", + __func__, init_retry_count)); qla4xxx_soft_reset(ha); status = qla4xxx_initialize_adapter(ha, REBUILD_DDB_LIST); } @@ -1280,7 +1309,7 @@ static int __devinit qla4xxx_probe_adapt /* Startup the kernel thread for this host adapter. */ DEBUG2(printk("scsi: %s: Starting kernel thread for " - "qla4xxx_dpc\n", __func__)); + "qla4xxx_dpc\n", __func__)); sprintf(buf, "qla4xxx_%lu_dpc", ha->host_no); ha->dpc_thread = create_singlethread_workqueue(buf); if (!ha->dpc_thread) { @@ -1288,9 +1317,11 @@ static int __devinit qla4xxx_probe_adapt ret = -ENODEV; goto probe_failed; } - INIT_WORK(&ha->dpc_work, qla4xxx_do_dpc); + QL_INIT_WORK(ha, qla4xxx_do_dpc); + ret = request_irq(pdev->irq, qla4xxx_intr_handler, - IRQF_DISABLED | IRQF_SHARED, "qla4xxx", ha); + QL_REQ_IRQ_FLAGS, "qla4xxx", ha); + if (ret) { dev_warn(&ha->pdev->dev, "Failed to reserve interrupt %d" " already in use.\n", pdev->irq); @@ -1298,7 +1329,7 @@ static int __devinit qla4xxx_probe_adapt } set_bit(AF_IRQ_ATTACHED, &ha->flags); host->irq = pdev->irq; - DEBUG(printk("scsi%d: irq %d attached\n", ha->host_no, ha->pdev->irq)); + dev_info(&ha->pdev->dev, "irq %d attached\n", ha->pdev->irq); qla4xxx_enable_intrs(ha); @@ -1313,6 +1344,9 @@ static int __devinit qla4xxx_probe_adapt if (ret) goto probe_failed; + if ((ret = QL_ISCSI_REGISTER_HOST(host, qla4xxx_scsi_transport))) + goto remove_host; + /* Update transport device information for all devices. */ list_for_each_entry_safe(ddb_entry, ddbtemp, &ha->ddb_list, list) { @@ -1320,25 +1354,36 @@ static int __devinit qla4xxx_probe_adapt set_bit(DF_SCAN_ISSUED, &ddb_entry->flags); if (qla4xxx_add_sess(ddb_entry, - test_bit(DF_SCAN_ISSUED, &ddb_entry->flags))) + test_bit(DF_SCAN_ISSUED, &ddb_entry->flags))) { + QL_ISCSI_UNREGISTER_HOST(host, qla4xxx_scsi_transport); goto remove_host; + } if (!test_bit(DF_SCAN_ISSUED, &ddb_entry->flags)) qla4xxx_mark_device_missing(ha, ddb_entry); } - printk(KERN_INFO - " QLogic iSCSI HBA Driver version: %s\n" - " QLogic ISP%04x @ %s, pdev = %p host#=%ld, fw=%02d.%02d.%02d.%02d\n", - qla4xxx_version_str, ha->pdev->device, pci_name(ha->pdev), pdev, - ha->host_no, ha->firmware_version[0], ha->firmware_version[1], - ha->patch_number, ha->build_number); + dev_info(&ha->pdev->dev, " QLogic iSCSI HBA Driver version: %s\n" + " QLogic ISP%04x @ %s, pdev = %p host#=%ld," + " fw=%02d.%02d.%02d.%02d\n", qla4xxx_version_str, + ha->pdev->device, pci_name(ha->pdev), pdev, + ha->host_no, ha->firmware_version[0], ha->firmware_version[1], + ha->patch_number, ha->build_number); /* Insert new entry into the list of adapters. */ klist_add_tail(&ha->node, &qla4xxx_hostlist); ha->instance = atomic_inc_return(&qla4xxx_hba_count) - 1; - DEBUG2(printk("qla4xxx: listhead=%p, done adding ha=%p i=%d\n", - &qla4xxx_hostlist, &ha->node, ha->instance)); + if (qla4xxx_ioctl_init(ha)) { + dev_info(&ha->pdev->dev, "ioctl init failed\n"); + QL_ISCSI_UNREGISTER_HOST(host, qla4xxx_scsi_transport); + goto remove_host; + } + + DEBUG2(dev_info(&ha->pdev->dev, "listhead=%p, done adding ha=%p i=%d\n", + &qla4xxx_hostlist, &ha->node, ha->instance)); + +// set_bit(AF_INIT_DONE, &ha->flags); + dev_info(&ha->pdev->dev, "%s: AF_INIT_DONE\n", __func__); return 0; @@ -1377,8 +1422,12 @@ static void __devexit qla4xxx_remove_ada /* remove devs from iscsi_sessions to scsi_devices */ qla4xxx_free_ddb_list(ha); + QL_ISCSI_UNREGISTER_HOST(ha->host, qla4xxx_scsi_transport); + scsi_remove_host(ha->host); + qla4xxx_ioctl_exit(ha); + qla4xxx_free_adapter(ha); scsi_host_put(ha->host); @@ -1393,7 +1442,7 @@ static void __devexit qla4xxx_remove_ada * At exit, the @ha's flags.enable_64bit_addressing set to indicated * supported addressing method. */ -static void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha) +void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha) { int retval; @@ -1402,9 +1451,9 @@ static void qla4xxx_config_dma_addressin if (pci_set_consistent_dma_mask(ha->pdev, DMA_64BIT_MASK)) { dev_dbg(&ha->pdev->dev, "Failed to set 64 bit PCI consistent mask; " - "using 32 bit.\n"); + "using 32 bit.\n"); retval = pci_set_consistent_dma_mask(ha->pdev, - DMA_32BIT_MASK); + DMA_32BIT_MASK); } } else retval = pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK); @@ -1412,7 +1461,7 @@ static void qla4xxx_config_dma_addressin static int qla4xxx_slave_alloc(struct scsi_device *sdev) { - struct iscsi_cls_session *sess = starget_to_session(sdev->sdev_target); + struct iscsi_cls_session *sess = QL_ISCSI_SDEV_TO_SESS(sdev); if (sess) { sdev->hostdata = sess->dd_data; @@ -1431,6 +1480,11 @@ static int qla4xxx_slave_configure(struc return 0; } +static void qla4xxx_slave_destroy(struct scsi_device *sdev) +{ + sdev->hostdata = NULL; +} + /** * qla4xxx_del_from_active_array - returns an active srb * @ha: Pointer to host adapter structure. @@ -1470,7 +1524,7 @@ struct srb * qla4xxx_del_from_active_arr * for some max time. **/ static int qla4xxx_eh_wait_on_command(struct scsi_qla_host *ha, - struct scsi_cmnd *cmd) + struct scsi_cmnd *cmd) { int done = 0; struct srb *rp; @@ -1564,8 +1618,8 @@ static int qla4xxx_eh_device_reset(struc return ret; dev_info(&ha->pdev->dev, - "scsi%ld:%d:%d:%d: DEVICE RESET ISSUED.\n", ha->host_no, - cmd->device->channel, cmd->device->id, cmd->device->lun); + "%s: %d:%d:%d: DEVICE RESET ISSUED.\n", __func__, + cmd->device->channel, cmd->device->id, cmd->device->lun); if (qla4xxx_wait_for_hba_online(ha) != QLA_SUCCESS) { dev_info(&ha->pdev->dev, "%s: HBA OFFLINE: FAILED\n", __func__); @@ -1584,12 +1638,12 @@ static int qla4xxx_eh_device_reset(struc */ if (cmd->device->host->shost_state == SHOST_RECOVERY) { if (qla4xxx_eh_wait_for_active_target_commands(ha, - cmd->device->id, - cmd->device-> - lun)) { + cmd->device->id, + cmd->device-> + lun)) { dev_info(&ha->pdev->dev, - "DEVICE RESET FAILED - waiting for " - "commands.\n"); + "DEVICE RESET FAILED - waiting for " + "commands.\n"); goto eh_dev_reset_done; } } @@ -1598,9 +1652,9 @@ static int qla4xxx_eh_device_reset(struc goto eh_dev_reset_done; dev_info(&ha->pdev->dev, - "scsi(%ld:%d:%d:%d): DEVICE RESET SUCCEEDED.\n", - ha->host_no, cmd->device->channel, cmd->device->id, - cmd->device->lun); + "scsi(%ld:%d:%d:%d): DEVICE RESET SUCCEEDED.\n", + ha->host_no, cmd->device->channel, cmd->device->id, + cmd->device->lun); ret = SUCCESS; @@ -1635,7 +1689,7 @@ static int qla4xxx_eh_host_reset(struct } dev_info(&ha->pdev->dev, "HOST RESET %s.\n", - return_status == FAILED ? "FAILED" : "SUCCEDED"); + return_status == FAILED ? "FAILED" : "SUCCEDED"); return return_status; } @@ -1664,7 +1718,7 @@ static struct pci_device_id qla4xxx_pci_ }; MODULE_DEVICE_TABLE(pci, qla4xxx_pci_tbl); -static struct pci_driver qla4xxx_pci_driver = { +struct pci_driver qla4xxx_pci_driver = { .name = DRIVER_NAME, .id_table = qla4xxx_pci_tbl, .probe = qla4xxx_probe_adapter, @@ -1678,12 +1732,11 @@ static int __init qla4xxx_module_init(vo atomic_set(&qla4xxx_hba_count, 0); klist_init(&qla4xxx_hostlist, NULL, NULL); /* Allocate cache for SRBs. */ - srb_cachep = kmem_cache_create("qla4xxx_srbs", sizeof(struct srb), 0, - SLAB_HWCACHE_ALIGN, NULL); + srb_cachep = ql_kmem_cache_create(); + if (srb_cachep == NULL) { - printk(KERN_ERR - "%s: Unable to allocate SRB cache..." - "Failing load!\n", DRIVER_NAME); + printk(KERN_ERR "%s: Unable to allocate SRB cache..." + "Failing load!\n", DRIVER_NAME); ret = -ENOMEM; goto no_srp_cache; } @@ -1700,7 +1753,14 @@ static int __init qla4xxx_module_init(vo goto release_srb_cache; } + ret = QL_MISC_INIT; + if (ret) { + printk(KERN_INFO "QLogic iSCSI HBA Driver ioctl init failed\n"); + goto unregister_transport; + } + printk(KERN_INFO "QLogic iSCSI HBA Driver\n"); + ret = pci_register_driver(&qla4xxx_pci_driver); if (ret) goto unregister_transport; @@ -1718,6 +1778,9 @@ no_srp_cache: static void __exit qla4xxx_module_exit(void) { ql4_mod_unload = 1; + + QL_MISC_EXIT; + pci_unregister_driver(&qla4xxx_pci_driver); iscsi_unregister_transport(&qla4xxx_iscsi_transport); kmem_cache_destroy(srb_cachep); --- /dev/null +++ b/drivers/scsi/qla4xxx/ql4_os.h @@ -0,0 +1,125 @@ +/* + * QLogic iSCSI HBA Driver + * Copyright (c) 2003-2006 QLogic Corporation + * + * See LICENSE.qla4xxx for copyright and licensing details. + */ + +/* + * This file encapsulates RHEL5 Specific Code + */ + +#ifndef __QLA4x_OS_H +#define __QLA4x_OS_H + +/* Common across all O.S platforms */ +#define IOCB_CMD_TIMEOUT 30 +#define RELOGIN_TOV 18 +#define RECOVERY_TIMEOUT 20 /* ddb state MISSING -> DEAD */ + +#define QL_IOCB_CMD_TIMEOUT(cmd) + +#define QL_SET_DDB_OFFLINE(ha, ddb_entry) + +#define QL_SESS_RECOVERY_TO(ddb_entry) ddb_entry->ha->port_down_retry_count + +#define QL_DPC_OFFLINE_SET(ha) 0 + +#define QL_ISCSI_CONN_TO_SESS(conn) iscsi_dev_to_session(conn->dev.parent) + +#define QL_ISCSI_SDEV_TO_SESS(sdev) starget_to_session(sdev->sdev_target) + +#define QL_ISCSI_ADD_SESS(ddb_entry) \ + iscsi_add_session(ddb_entry->sess, ddb_entry->os_target_id) + +#define QL_ISCSI_REGISTER_HOST(host, trans) 0 +#define QL_ISCSI_UNREGISTER_HOST(host, trans) + +#define QL_ISCSI_SESSION_ID(ddb_entry) ddb_entry->sess->sid +#define QL_ISCSI_IF_DESTROY_SESSION_DONE(ddb_entry) +#define QL_ISCSI_DESTROY_CONN(ddb_entry) +#define QL_ISCSI_CREATE_CONN(ddb_entry) \ + iscsi_create_conn(ddb_entry->sess, 0, 0) +#define QL_ISCSI_CREATE_SESS_DONE(ddb_entry) \ + iscsi_unblock_session(ddb_entry->sess) +#define QL_ISCSI_ALLOC_SESSION(ha, trans) \ + iscsi_alloc_session(ha->host, trans, sizeof(struct ddb_entry)) + + +#define QL_MISC_INIT 0 +#define QL_MISC_EXIT + +#define qla4xxx_check_dev_offline(ha) +#define qla4xxx_proc_info NULL + +#define QL_SET_SCSI_RESID(cmd, residual) scsi_set_resid(cmd, residual) +#define QL_SCSI_BUFFLEN(cmd) scsi_bufflen(cmd) + +#define QL_DPC_DATA_TO_HA(work) \ + container_of((struct work_struct *)work, struct scsi_qla_host, dpc_work) + +#define QL_INIT_WORK(ha, dpc_func) INIT_WORK(&ha->dpc_work, dpc_func) + +#define QL_REQ_IRQ_FLAGS (IRQF_DISABLED | IRQF_SHARED) + +#define QL_DECLARE_INTR_HANDLER(intr_func, irq, dev_id, regs) \ + irqreturn_t intr_func(int irq, void *dev_id) + +#define QL_DECLARE_DPC(dpc_func, data) \ + void dpc_func(struct work_struct *data) + +#define QL_INIT_SESSION_DATASIZE(sessiondata_size) +// .sessiondata_size = sizeof(struct ddb_entry), + +#define QL_INIT_HOST_TEMPLATE(host_template) +// .host_template = &qla4xxx_driver_template, + +QL_DECLARE_INTR_HANDLER(qla4xxx_intr_handler, irq, dev_id, regs); + +static inline struct kmem_cache *ql_kmem_cache_create(void) +{ + return (kmem_cache_create("qla4xxx_srbs", sizeof(struct srb), 0, + SLAB_HWCACHE_ALIGN, NULL)); +} + +static inline void qla4xxx_scan_target(struct ddb_entry * ddb_entry) +{ + scsi_scan_target(&ddb_entry->sess->dev, 0, + ddb_entry->sess->target_id, SCAN_WILD_CARD, 0); +} + +static void ql4_get_aen_log(struct scsi_qla_host *ha, struct ql4_aen_log *aenl) +{ + if (aenl) { + memcpy(aenl, &ha->aen_log, sizeof (ha->aen_log)); + ha->aen_log.count = 0; + } +} + +static inline int qla4xxx_ioctl_init(struct scsi_qla_host *ha) +{ + ha->ql4mbx = qla4xxx_mailbox_command; + ha->ql4cmd = qla4xxx_send_command_to_isp; + ha->ql4getaenlog = ql4_get_aen_log; + return 0; +} + +static inline void qla4xxx_ioctl_exit(struct scsi_qla_host *ha) +{ + return; +} + +static inline void qla4xxx_srb_free_dma(struct scsi_qla_host *ha, + struct srb *srb) +{ + struct scsi_cmnd *cmd = srb->cmd; + + if (srb->flags & SRB_DMA_VALID) { + scsi_dma_unmap(cmd); + srb->flags &= ~SRB_DMA_VALID; + } + + cmd->SCp.ptr = NULL; +} + +#endif /* _QLA4x_OS_H */ --- a/drivers/scsi/qla4xxx/ql4_version.h +++ b/drivers/scsi/qla4xxx/ql4_version.h @@ -5,6 +5,5 @@ * See LICENSE.qla4xxx for copyright and licensing details. */ -#define QLA4XXX_DRIVER_VERSION "5.01.00-k8_sles11-01" - +#define QLA4XXX_DRIVER_VERSION "5.01.00-k8_sles11-03"