diff options
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r-- | drivers/scsi/qla2xxx/Makefile | 2 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 37 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gbl.h | 10 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 17 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 60 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 31 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_rscn.c | 1425 |
7 files changed, 1 insertions, 1581 deletions
diff --git a/drivers/scsi/qla2xxx/Makefile b/drivers/scsi/qla2xxx/Makefile index c8f670ee60b4..6ff7bb0d8e20 100644 --- a/drivers/scsi/qla2xxx/Makefile +++ b/drivers/scsi/qla2xxx/Makefile @@ -1,7 +1,7 @@ EXTRA_CFLAGS += -DUNIQUE_FW_NAME qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \ - qla_dbg.o qla_sup.o qla_rscn.o qla_attr.o + qla_dbg.o qla_sup.o qla_attr.o obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 4bd67e9c2840..4c67494e9f75 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -1523,8 +1523,6 @@ typedef struct fc_port { unsigned int os_target_id; - uint16_t iodesc_idx_sent; - int port_login_retry_count; int login_retry; atomic_t port_down_timer; @@ -1940,34 +1938,6 @@ struct sns_cmd_pkt { } p; }; -/* IO descriptors */ -#define MAX_IO_DESCRIPTORS 32 - -#define ABORT_IOCB_CB 0 -#define ADISC_PORT_IOCB_CB 1 -#define LOGOUT_PORT_IOCB_CB 2 -#define LOGIN_PORT_IOCB_CB 3 -#define LAST_IOCB_CB 4 - -#define IODESC_INVALID_INDEX 0xFFFF -#define IODESC_ADISC_NEEDED 0xFFFE -#define IODESC_LOGIN_NEEDED 0xFFFD - -struct io_descriptor { - uint16_t used:1; - uint16_t idx:11; - uint16_t cb_idx:4; - - struct timer_list timer; - - struct scsi_qla_host *ha; - - port_id_t d_id; - fc_port_t *remote_fcport; - - uint32_t signature; -}; - struct qla_fw_info { unsigned short addressing; /* addressing method used to load fw */ #define FW_INFO_ADDR_NORMAL 0 @@ -2271,10 +2241,6 @@ typedef struct scsi_qla_host { /* Fibre Channel Device List. */ struct list_head fcports; - struct list_head rscn_fcports; - - struct io_descriptor io_descriptors[MAX_IO_DESCRIPTORS]; - uint16_t iodesc_signature; /* RSCN queue. */ uint32_t rscn_queue[MAX_RSCN_COUNT]; @@ -2313,9 +2279,6 @@ typedef struct scsi_qla_host { init_cb_t *init_cb; int init_cb_size; - dma_addr_t iodesc_pd_dma; - port_database_t *iodesc_pd; - /* These are used by mailbox operations. */ volatile uint16_t mailbox_out[MAILBOX_REGISTER_COUNT]; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 26d1181b3389..029222998716 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -64,7 +64,6 @@ extern int qlport_down_retry; extern int ql2xplogiabsentdevice; extern int ql2xloginretrycount; extern int ql2xfdmienable; -extern int ql2xprocessrscn; extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *); @@ -284,15 +283,6 @@ extern void *qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *, uint32_t, uint32_t); extern int qla2x00_fdmi_register(scsi_qla_host_t *); /* - * Global Function Prototypes in qla_rscn.c source file. - */ -extern fc_port_t *qla2x00_alloc_rscn_fcport(scsi_qla_host_t *, gfp_t); -extern int qla2x00_handle_port_rscn(scsi_qla_host_t *, uint32_t, fc_port_t *, - int); -extern void qla2x00_process_iodesc(scsi_qla_host_t *, struct mbx_entry *); -extern void qla2x00_cancel_io_descriptors(scsi_qla_host_t *); - -/* * Global Function Prototypes in qla_xioctl.c source file. */ #define qla2x00_enqueue_aen(ha, cmd, mode) do { } while (0) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 7e18b9c12654..7b48c655b766 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1708,7 +1708,6 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags) fcport->ha = ha; fcport->port_type = FCT_UNKNOWN; fcport->loop_id = FC_NO_LOOP_ID; - fcport->iodesc_idx_sent = IODESC_INVALID_INDEX; atomic_set(&fcport->state, FCS_UNCONFIGURED); fcport->flags = FCF_RLC_SUPPORT; fcport->supported_classes = FC_COS_UNSPECIFIED; @@ -2563,7 +2562,6 @@ static int qla2x00_device_resync(scsi_qla_host_t *ha) { int rval; - int rval2; uint32_t mask; fc_port_t *fcport; uint32_t rscn_entry; @@ -2619,17 +2617,6 @@ qla2x00_device_resync(scsi_qla_host_t *ha) switch (format) { case 0: - if (ql2xprocessrscn && - !IS_QLA2100(ha) && !IS_QLA2200(ha) && - !IS_QLA6312(ha) && !IS_QLA6322(ha) && - !IS_QLA24XX(ha) && !IS_QLA54XX(ha) && - ha->flags.init_done) { - /* Handle port RSCN via asyncronous IOCBs */ - rval2 = qla2x00_handle_port_rscn(ha, rscn_entry, - NULL, 0); - if (rval2 == QLA_SUCCESS) - continue; - } mask = 0xffffff; break; case 1: @@ -2647,10 +2634,6 @@ qla2x00_device_resync(scsi_qla_host_t *ha) rval = QLA_SUCCESS; - /* Abort any outstanding IO descriptors. */ - if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) - qla2x00_cancel_io_descriptors(ha); - list_for_each_entry(fcport, &ha->fcports, list) { if ((fcport->flags & FCF_FABRIC_DEVICE) == 0 || (fcport->d_id.b24 & mask) != d_id.b24 || diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 39b5082eb3bc..b28ac0a27e25 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -515,47 +515,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) case MBA_PORT_UPDATE: /* Port database update */ /* - * If a single remote port just logged into (or logged out of) - * us, create a new entry in our rscn fcports list and handle - * the event like an RSCN. - */ - if (ql2xprocessrscn && - !IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA6312(ha) && - !IS_QLA6322(ha) && !IS_QLA24XX(ha) && !IS_QLA54XX(ha) && - ha->flags.init_done && mb[1] != 0xffff && - ((ha->operating_mode == P2P && mb[1] != 0) || - (ha->operating_mode != P2P && mb[1] != - SNS_FIRST_LOOP_ID)) && (mb[2] == 6 || mb[2] == 7)) { - int rval; - fc_port_t *rscn_fcport; - - /* Create new fcport for login. */ - rscn_fcport = qla2x00_alloc_rscn_fcport(ha, GFP_ATOMIC); - if (rscn_fcport) { - DEBUG14(printk("scsi(%ld): Port Update -- " - "creating RSCN fcport %p for %x/%x/%x.\n", - ha->host_no, rscn_fcport, mb[1], mb[2], - mb[3])); - - rscn_fcport->loop_id = mb[1]; - rscn_fcport->d_id.b24 = INVALID_PORT_ID; - atomic_set(&rscn_fcport->state, - FCS_DEVICE_LOST); - list_add_tail(&rscn_fcport->list, - &ha->rscn_fcports); - - rval = qla2x00_handle_port_rscn(ha, 0, - rscn_fcport, 1); - if (rval == QLA_SUCCESS) - break; - } else { - DEBUG14(printk("scsi(%ld): Port Update -- " - "-- unable to allocate RSCN fcport " - "login.\n", ha->host_no)); - } - } - - /* * If PORT UPDATE is global (recieved LIP_OCCURED/LIP_RESET * event etc. earlier indicating loop is down) then process * it. Otherwise ignore it and Wait for RSCN to come in. @@ -753,25 +712,6 @@ qla2x00_process_response_queue(struct scsi_qla_host *ha) case MS_IOCB_TYPE: qla2x00_ms_entry(ha, (ms_iocb_entry_t *)pkt); break; - case MBX_IOCB_TYPE: - if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && - !IS_QLA6312(ha) && !IS_QLA6322(ha)) { - if (pkt->sys_define == SOURCE_ASYNC_IOCB) { - qla2x00_process_iodesc(ha, - (struct mbx_entry *)pkt); - } else { - /* MBX IOCB Type Not Supported. */ - DEBUG4(printk(KERN_WARNING - "scsi(%ld): Received unknown MBX " - "IOCB response pkt type=%x " - "source=%x entry status=%x.\n", - ha->host_no, pkt->entry_type, - pkt->sys_define, - pkt->entry_status)); - } - break; - } - /* Fallthrough. */ default: /* Type Not Supported. */ DEBUG4(printk(KERN_WARNING diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 77e67e1429ee..22e8714a91fd 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -71,12 +71,6 @@ MODULE_PARM_DESC(ql2xfdmienable, "Enables FDMI registratons " "Default is 0 - no FDMI. 1 - perfom FDMI."); -int ql2xprocessrscn; -module_param(ql2xprocessrscn, int, S_IRUGO|S_IRUSR); -MODULE_PARM_DESC(ql2xprocessrscn, - "Option to enable port RSCN handling via a series of less" - "fabric intrusive ADISCs and PLOGIs."); - /* * SCSI host template entry points */ @@ -1492,7 +1486,6 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) INIT_LIST_HEAD(&ha->list); INIT_LIST_HEAD(&ha->fcports); - INIT_LIST_HEAD(&ha->rscn_fcports); /* * These locks are used to prevent more than one CPU @@ -1669,10 +1662,6 @@ EXPORT_SYMBOL_GPL(qla2x00_remove_one); static void qla2x00_free_device(scsi_qla_host_t *ha) { - /* Abort any outstanding IO descriptors. */ - if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) - qla2x00_cancel_io_descriptors(ha); - /* Disable timer */ if (ha->timer_active) qla2x00_stop_timer(ha); @@ -1909,21 +1898,6 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha) } memset(ha->init_cb, 0, ha->init_cb_size); - /* Get consistent memory allocated for Get Port Database cmd */ - ha->iodesc_pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, - &ha->iodesc_pd_dma); - if (ha->iodesc_pd == NULL) { - /* error */ - qla_printk(KERN_WARNING, ha, - "Memory Allocation failed - iodesc_pd\n"); - - qla2x00_mem_free(ha); - msleep(100); - - continue; - } - memset(ha->iodesc_pd, 0, PORT_DATABASE_SIZE); - /* Allocate ioctl related memory. */ if (qla2x00_alloc_ioctl_mem(ha)) { qla_printk(KERN_WARNING, ha, @@ -2048,9 +2022,6 @@ qla2x00_mem_free(scsi_qla_host_t *ha) if (ha->ms_iocb) dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma); - if (ha->iodesc_pd) - dma_pool_free(ha->s_dma_pool, ha->iodesc_pd, ha->iodesc_pd_dma); - if (ha->init_cb) dma_pool_free(ha->s_dma_pool, ha->init_cb, ha->init_cb_dma); @@ -2077,8 +2048,6 @@ qla2x00_mem_free(scsi_qla_host_t *ha) ha->ct_sns_dma = 0; ha->ms_iocb = NULL; ha->ms_iocb_dma = 0; - ha->iodesc_pd = NULL; - ha->iodesc_pd_dma = 0; ha->init_cb = NULL; ha->init_cb_dma = 0; diff --git a/drivers/scsi/qla2xxx/qla_rscn.c b/drivers/scsi/qla2xxx/qla_rscn.c deleted file mode 100644 index 33e287b4f177..000000000000 --- a/drivers/scsi/qla2xxx/qla_rscn.c +++ /dev/null @@ -1,1425 +0,0 @@ -/* - * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2005 QLogic Corporation - * - * See LICENSE.qla2xxx for copyright and licensing details. - */ -#include "qla_def.h" - -/** - * IO descriptor handle definitions. - * - * Signature form: - * - * |31------28|27-------------------12|11-------0| - * | Type | Rolling Signature | Index | - * |----------|-----------------------|----------| - * - **/ - -#define HDL_TYPE_SCSI 0 -#define HDL_TYPE_ASYNC_IOCB 0x0A - -#define HDL_INDEX_BITS 12 -#define HDL_ITER_BITS 16 -#define HDL_TYPE_BITS 4 - -#define HDL_INDEX_MASK ((1UL << HDL_INDEX_BITS) - 1) -#define HDL_ITER_MASK ((1UL << HDL_ITER_BITS) - 1) -#define HDL_TYPE_MASK ((1UL << HDL_TYPE_BITS) - 1) - -#define HDL_INDEX_SHIFT 0 -#define HDL_ITER_SHIFT (HDL_INDEX_SHIFT + HDL_INDEX_BITS) -#define HDL_TYPE_SHIFT (HDL_ITER_SHIFT + HDL_ITER_BITS) - -/* Local Prototypes. */ -static inline uint32_t qla2x00_to_handle(uint16_t, uint16_t, uint16_t); -static inline uint16_t qla2x00_handle_to_idx(uint32_t); -static inline uint32_t qla2x00_iodesc_to_handle(struct io_descriptor *); -static inline struct io_descriptor *qla2x00_handle_to_iodesc(scsi_qla_host_t *, - uint32_t); - -static inline struct io_descriptor *qla2x00_alloc_iodesc(scsi_qla_host_t *); -static inline void qla2x00_free_iodesc(struct io_descriptor *); -static inline void qla2x00_init_io_descriptors(scsi_qla_host_t *); - -static void qla2x00_iodesc_timeout(unsigned long); -static inline void qla2x00_add_iodesc_timer(struct io_descriptor *); -static inline void qla2x00_remove_iodesc_timer(struct io_descriptor *); - -static inline void qla2x00_update_login_fcport(scsi_qla_host_t *, - struct mbx_entry *, fc_port_t *); - -static int qla2x00_send_abort_iocb(scsi_qla_host_t *, struct io_descriptor *, - uint32_t, int); -static int qla2x00_send_abort_iocb_cb(scsi_qla_host_t *, struct io_descriptor *, - struct mbx_entry *); - -static int qla2x00_send_adisc_iocb(scsi_qla_host_t *, struct io_descriptor *, - int); -static int qla2x00_send_adisc_iocb_cb(scsi_qla_host_t *, struct io_descriptor *, - struct mbx_entry *); - -static int qla2x00_send_logout_iocb(scsi_qla_host_t *, struct io_descriptor *, - int); -static int qla2x00_send_logout_iocb_cb(scsi_qla_host_t *, - struct io_descriptor *, struct mbx_entry *); - -static int qla2x00_send_login_iocb(scsi_qla_host_t *, struct io_descriptor *, - port_id_t *, int); -static int qla2x00_send_login_iocb_cb(scsi_qla_host_t *, struct io_descriptor *, - struct mbx_entry *); - -/** - * Mailbox IOCB callback array. - **/ -static int (*iocb_function_cb_list[LAST_IOCB_CB]) - (scsi_qla_host_t *, struct io_descriptor *, struct mbx_entry *) = { - - qla2x00_send_abort_iocb_cb, - qla2x00_send_adisc_iocb_cb, - qla2x00_send_logout_iocb_cb, - qla2x00_send_login_iocb_cb, -}; - - -/** - * Generic IO descriptor handle routines. - **/ - -/** - * qla2x00_to_handle() - Create a descriptor handle. - * @type: descriptor type - * @iter: descriptor rolling signature - * @idx: index to the descriptor array - * - * Returns a composite handle based in the @type, @iter, and @idx. - */ -static inline uint32_t -qla2x00_to_handle(uint16_t type, uint16_t iter, uint16_t idx) -{ - return ((uint32_t)(((uint32_t)type << HDL_TYPE_SHIFT) | - ((uint32_t)iter << HDL_ITER_SHIFT) | - ((uint32_t)idx << HDL_INDEX_SHIFT))); -} - -/** - * qla2x00_handle_to_idx() - Retrive the index for a given handle. - * @handle: descriptor handle - * - * Returns the index specified by the @handle. - */ -static inline uint16_t -qla2x00_handle_to_idx(uint32_t handle) -{ - return ((uint16_t)(((handle) >> HDL_INDEX_SHIFT) & HDL_INDEX_MASK)); -} - -/** - * qla2x00_iodesc_to_handle() - Convert an IO descriptor to a unique handle. - * @iodesc: io descriptor - * - * Returns a unique handle for @iodesc. - */ -static inline uint32_t -qla2x00_iodesc_to_handle(struct io_descriptor *iodesc) -{ - uint32_t handle; - - handle = qla2x00_to_handle(HDL_TYPE_ASYNC_IOCB, - ++iodesc->ha->iodesc_signature, iodesc->idx); - iodesc->signature = handle; - - return (handle); -} - -/** - * qla2x00_handle_to_iodesc() - Retrieve an IO descriptor given a unique handle. - * @ha: HA context - * @handle: handle to io descriptor - * - * Returns a pointer to the io descriptor, or NULL, if the io descriptor does - * not exist or the io descriptors signature does not @handle. - */ -static inline struct io_descriptor * -qla2x00_handle_to_iodesc(scsi_qla_host_t *ha, uint32_t handle) -{ - uint16_t idx; - struct io_descriptor *iodesc; - - idx = qla2x00_handle_to_idx(handle); - iodesc = &ha->io_descriptors[idx]; - if (iodesc) - if (iodesc->signature != handle) - iodesc = NULL; - - return (iodesc); -} - - -/** - * IO descriptor allocation routines. - **/ - -/** - * qla2x00_alloc_iodesc() - Allocate an IO descriptor from the pool. - * @ha: HA context - * - * Returns a pointer to the allocated io descriptor, or NULL, if none available. - */ -static inline struct io_descriptor * -qla2x00_alloc_iodesc(scsi_qla_host_t *ha) -{ - uint16_t iter; - struct io_descriptor *iodesc; - - iodesc = NULL; - for (iter = 0; iter < MAX_IO_DESCRIPTORS; iter++) { - if (ha->io_descriptors[iter].used) - continue; - - iodesc = &ha->io_descriptors[iter]; - iodesc->used = 1; - iodesc->idx = iter; - init_timer(&iodesc->timer); - iodesc->ha = ha; - iodesc->signature = qla2x00_iodesc_to_handle(iodesc); - break; - } - - return (iodesc); -} - -/** - * qla2x00_free_iodesc() - Free an IO descriptor. - * @iodesc: io descriptor - * - * NOTE: The io descriptors timer *must* be stopped before it can be free'd. - */ -static inline void -qla2x00_free_iodesc(struct io_descriptor *iodesc) -{ - iodesc->used = 0; - iodesc->signature = 0; -} - -/** - * qla2x00_remove_iodesc_timer() - Remove an active timer from an IO descriptor. - * @iodesc: io descriptor - */ -static inline void -qla2x00_remove_iodesc_timer(struct io_descriptor *iodesc) -{ - if (iodesc->timer.function != NULL) { - del_timer_sync(&iodesc->timer); - iodesc->timer.data = (unsigned long) NULL; - iodesc->timer.function = NULL; - } -} - -/** - * qla2x00_init_io_descriptors() - Initialize the pool of IO descriptors. - * @ha: HA context - */ -static inline void -qla2x00_init_io_descriptors(scsi_qla_host_t *ha) -{ - uint16_t iter; - - for (iter = 0; iter < MAX_IO_DESCRIPTORS; iter++) { - if (!ha->io_descriptors[iter].used) - continue; - - qla2x00_remove_iodesc_timer(&ha->io_descriptors[iter]); - qla2x00_free_iodesc(&ha->io_descriptors[iter]); - } -} - - -/** - * IO descriptor timer routines. - **/ - -/** - * qla2x00_iodesc_timeout() - Timeout IO descriptor handler. - * @data: io descriptor - */ -static void -qla2x00_iodesc_timeout(unsigned long data) -{ - struct io_descriptor *iodesc; - - iodesc = (struct io_descriptor *) data; - - DEBUG14(printk("scsi(%ld): IO descriptor timeout, index=%x " - "signature=%08x, scheduling ISP abort.\n", iodesc->ha->host_no, - iodesc->idx, iodesc->signature)); - - qla2x00_free_iodesc(iodesc); - - qla_printk(KERN_WARNING, iodesc->ha, - "IO descriptor timeout. Scheduling ISP abort.\n"); - set_bit(ISP_ABORT_NEEDED, &iodesc->ha->dpc_flags); -} - -/** - * qla2x00_add_iodesc_timer() - Add and start a timer for an IO descriptor. - * @iodesc: io descriptor - * - * NOTE: - * The firmware shall timeout an outstanding mailbox IOCB in 2 * R_A_TOV (in - * tenths of a second) after it hits the wire. But, if there are any request - * resource contraints (i.e. during heavy I/O), exchanges can be held off for - * at most R_A_TOV. Therefore, the driver will wait 4 * R_A_TOV before - * scheduling a recovery (big hammer). - */ -static inline void -qla2x00_add_iodesc_timer(struct io_descriptor *iodesc) -{ - unsigned long timeout; - - timeout = (iodesc->ha->r_a_tov * 4) / 10; - init_timer(&iodesc->timer); - iodesc->timer.data = (unsigned long) iodesc; - iodesc->timer.expires = jiffies + (timeout * HZ); - iodesc->timer.function = - (void (*) (unsigned long)) qla2x00_iodesc_timeout; - add_timer(&iodesc->timer); -} - -/** - * IO descriptor support routines. - **/ - -/** - * qla2x00_update_login_fcport() - Update fcport data after login processing. - * @ha: HA context - * @mbxstat: Mailbox command status IOCB - * @fcport: port to update - */ -static inline void -qla2x00_update_login_fcport(scsi_qla_host_t *ha, struct mbx_entry *mbxstat, - fc_port_t *fcport) -{ - if (le16_to_cpu(mbxstat->mb1) & BIT_0) { - fcport->port_type = FCT_INITIATOR; - } else { - fcport->port_type = FCT_TARGET; - if (le16_to_cpu(mbxstat->mb1) & BIT_1) { - fcport->flags |= FCF_TAPE_PRESENT; - } - } - fcport->login_retry = 0; - fcport->port_login_retry_count = ha->port_down_retry_count * - PORT_RETRY_TIME; - atomic_set(&fcport->port_down_timer, ha->port_down_retry_count * - PORT_RETRY_TIME); - fcport->flags |= FCF_FABRIC_DEVICE; - fcport->flags &= ~FCF_FAILOVER_NEEDED; - fcport->iodesc_idx_sent = IODESC_INVALID_INDEX; - atomic_set(&fcport->state, FCS_ONLINE); -} - - -/** - * Mailbox IOCB commands. - **/ - -/** - * qla2x00_get_mbx_iocb_entry() - Retrieve an IOCB from the request queue. - * @ha: HA context - * @handle: handle to io descriptor - * - * Returns a pointer to the reqest entry, or NULL, if none were available. - */ -static inline struct mbx_entry * -qla2x00_get_mbx_iocb_entry(scsi_qla_host_t *ha, uint32_t handle) -{ - uint16_t cnt; - struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; - struct mbx_entry *mbxentry; - - mbxentry = NULL; - - if (ha->req_q_cnt < 3) { - cnt = qla2x00_debounce_register(ISP_REQ_Q_OUT(ha, reg)); - if (ha->req_ring_index < cnt) - ha->req_q_cnt = cnt - ha->req_ring_index; - else - ha->req_q_cnt = ha->request_q_length - - (ha->req_ring_index - cnt); - } - if (ha->req_q_cnt >= 3) { - mbxentry = (struct mbx_entry *)ha->request_ring_ptr; - - memset(mbxentry, 0, sizeof(struct mbx_entry)); - mbxentry->entry_type = MBX_IOCB_TYPE; - mbxentry->entry_count = 1; - mbxentry->sys_define1 = SOURCE_ASYNC_IOCB; - mbxentry->handle = handle; - } - return (mbxentry); -} - -/** - * qla2x00_send_abort_iocb() - Issue an abort IOCB to the firmware. - * @ha: HA context - * @iodesc: io descriptor - * @handle_to_abort: firmware handle to abort - * @ha_locked: is function called with the hardware lock - * - * Returns QLA_SUCCESS if the IOCB was issued. - */ -static int -qla2x00_send_abort_iocb(scsi_qla_host_t *ha, struct io_descriptor *iodesc, - uint32_t handle_to_abort, int ha_locked) -{ - unsigned long flags = 0; - struct mbx_entry *mbxentry; - - /* Send marker if required. */ - if (qla2x00_issue_marker(ha, ha_locked) != QLA_SUCCESS) - return (QLA_FUNCTION_FAILED); - - if (!ha_locked) - spin_lock_irqsave(&ha->hardware_lock, flags); - - /* Build abort mailbox IOCB. */ - mbxentry = qla2x00_get_mbx_iocb_entry(ha, iodesc->signature); - if (mbxentry == NULL) { - if (!ha_locked) - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - return (QLA_FUNCTION_FAILED); - } - mbxentry->mb0 = __constant_cpu_to_le16(MBC_ABORT_COMMAND); - mbxentry->mb1 = mbxentry->loop_id.extended = - cpu_to_le16(iodesc->remote_fcport->loop_id); - mbxentry->mb2 = LSW(handle_to_abort); - mbxentry->mb3 = MSW(handle_to_abort); - wmb(); - - qla2x00_add_iodesc_timer(iodesc); - - /* Issue command to ISP. */ - qla2x00_isp_cmd(ha); - - if (!ha_locked) - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - DEBUG14(printk("scsi(%ld): Sending Abort IOCB (%08x) to [%x], aborting " - "%08x.\n", ha->host_no, iodesc->signature, - iodesc->remote_fcport->loop_id, handle_to_abort)); - - return (QLA_SUCCESS); -} - -/** - * qla2x00_send_abort_iocb_cb() - Abort IOCB callback. - * @ha: HA context - * @iodesc: io descriptor - * @mbxstat: mailbox status IOCB - * - * Returns QLA_SUCCESS if @iodesc can be freed by the caller, else, @iodesc - * will be used for a retry. - */ -static int -qla2x00_send_abort_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc, - struct mbx_entry *mbxstat) -{ - DEBUG14(printk("scsi(%ld): Abort IOCB -- sent to [%x/%02x%02x%02x], " - "status=%x mb0=%x.\n", ha->host_no, iodesc->remote_fcport->loop_id, - iodesc->d_id.b.domain, iodesc->d_id.b.area, iodesc->d_id.b.al_pa, - le16_to_cpu(mbxstat->status), le16_to_cpu(mbxstat->mb0))); - - return (QLA_SUCCESS); -} - - -/** - * qla2x00_send_adisc_iocb() - Issue a Get Port Database IOCB to the firmware. - * @ha: HA context - * @iodesc: io descriptor - * @ha_locked: is function called with the hardware lock - * - * Returns QLA_SUCCESS if the IOCB was issued. - */ -static int -qla2x00_send_adisc_iocb(scsi_qla_host_t *ha, struct io_descriptor *iodesc, - int ha_locked) -{ - unsigned long flags = 0; - struct mbx_entry *mbxentry; - - /* Send marker if required. */ - if (qla2x00_issue_marker(ha, ha_locked) != QLA_SUCCESS) - return (QLA_FUNCTION_FAILED); - - if (!ha_locked) - spin_lock_irqsave(&ha->hardware_lock, flags); - - /* Build Get Port Database IOCB. */ - mbxentry = qla2x00_get_mbx_iocb_entry(ha, iodesc->signature); - if (mbxentry == NULL) { - if (!ha_locked) - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - return (QLA_FUNCTION_FAILED); - } - mbxentry->mb0 = __constant_cpu_to_le16(MBC_GET_PORT_DATABASE); - mbxentry->mb1 = mbxentry->loop_id.extended = - cpu_to_le16(iodesc->remote_fcport->loop_id); - mbxentry->mb2 = cpu_to_le16(MSW(LSD(ha->iodesc_pd_dma))); - mbxentry->mb3 = cpu_to_le16(LSW(LSD(ha->iodesc_pd_dma))); - mbxentry->mb6 = cpu_to_le16(MSW(MSD(ha->iodesc_pd_dma))); - mbxentry->mb7 = cpu_to_le16(LSW(MSD(ha->iodesc_pd_dma))); - mbxentry->mb10 = __constant_cpu_to_le16(BIT_0); - wmb(); - - qla2x00_add_iodesc_timer(iodesc); - - /* Issue command to ISP. */ - qla2x00_isp_cmd(ha); - - if (!ha_locked) - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - DEBUG14(printk("scsi(%ld): Sending Adisc IOCB (%08x) to [%x].\n", - ha->host_no, iodesc->signature, iodesc->remote_fcport->loop_id)); - - return (QLA_SUCCESS); -} - -/** - * qla2x00_send_adisc_iocb_cb() - Get Port Database IOCB callback. - * @ha: HA context - * @iodesc: io descriptor - * @mbxstat: mailbox status IOCB - * - * Returns QLA_SUCCESS if @iodesc can be freed by the caller, else, @iodesc - * will be used for a retry. - */ -static int -qla2x00_send_adisc_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc, - struct mbx_entry *mbxstat) -{ - fc_port_t *remote_fcport; - - remote_fcport = iodesc->remote_fcport; - - /* Ensure the port IDs are consistent. */ - if (remote_fcport->d_id.b24 != iodesc->d_id.b24) { - DEBUG14(printk("scsi(%ld): Adisc IOCB -- ignoring, remote port " - "id changed from [%02x%02x%02x] to [%02x%02x%02x].\n", - ha->host_no, remote_fcport->d_id.b.domain, - remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa, - iodesc->d_id.b.domain, iodesc->d_id.b.area, - iodesc->d_id.b.al_pa)); - - return (QLA_SUCCESS); - } - - /* Only process the last command. */ - if (remote_fcport->iodesc_idx_sent != iodesc->idx) { - DEBUG14(printk("scsi(%ld): Adisc IOCB -- ignoring, sent to " - "[%02x%02x%02x], expected %x, received %x.\n", ha->host_no, - iodesc->d_id.b.domain, iodesc->d_id.b.area, - iodesc->d_id.b.al_pa, remote_fcport->iodesc_idx_sent, - iodesc->idx)); - - return (QLA_SUCCESS); - } - - if (le16_to_cpu(mbxstat->status) == CS_COMPLETE) { - DEBUG14(printk("scsi(%ld): Adisc IOCB -- marking " - "[%x/%02x%02x%02x] online.\n", ha->host_no, - remote_fcport->loop_id, remote_fcport->d_id.b.domain, - remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa)); - - atomic_set(&remote_fcport->state, FCS_ONLINE); - } else { - DEBUG14(printk("scsi(%ld): Adisc IOCB -- marking " - "[%x/%02x%02x%02x] lost, status=%x mb0=%x.\n", ha->host_no, - remote_fcport->loop_id, remote_fcport->d_id.b.domain, - remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa, - le16_to_cpu(mbxstat->status), le16_to_cpu(mbxstat->mb0))); - - if (atomic_read(&remote_fcport->state) != FCS_DEVICE_DEAD) - atomic_set(&remote_fcport->state, FCS_DEVICE_LOST); - } - remote_fcport->iodesc_idx_sent = IODESC_INVALID_INDEX; - - return (QLA_SUCCESS); -} - - -/** - * qla2x00_send_logout_iocb() - Issue a fabric port logout IOCB to the firmware. - * @ha: HA context - * @iodesc: io descriptor - * @ha_locked: is function called with the hardware lock - * - * Returns QLA_SUCCESS if the IOCB was issued. - */ -static int -qla2x00_send_logout_iocb(scsi_qla_host_t *ha, struct io_descriptor *iodesc, - int ha_locked) -{ - unsigned long flags = 0; - struct mbx_entry *mbxentry; - - /* Send marker if required. */ - if (qla2x00_issue_marker(ha, ha_locked) != QLA_SUCCESS) - return (QLA_FUNCTION_FAILED); - - if (!ha_locked) - spin_lock_irqsave(&ha->hardware_lock, flags); - - /* Build fabric port logout mailbox IOCB. */ - mbxentry = qla2x00_get_mbx_iocb_entry(ha, iodesc->signature); - if (mbxentry == NULL) { - if (!ha_locked) - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - return (QLA_FUNCTION_FAILED); - } - mbxentry->mb0 = __constant_cpu_to_le16(MBC_LOGOUT_FABRIC_PORT); - mbxentry->mb1 = mbxentry->loop_id.extended = - cpu_to_le16(iodesc->remote_fcport->loop_id); - wmb(); - - qla2x00_add_iodesc_timer(iodesc); - - /* Issue command to ISP. */ - qla2x00_isp_cmd(ha); - - if (!ha_locked) - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - DEBUG14(printk("scsi(%ld): Sending Logout IOCB (%08x) to [%x].\n", - ha->host_no, iodesc->signature, iodesc->remote_fcport->loop_id)); - - return (QLA_SUCCESS); -} - -/** - * qla2x00_send_logout_iocb_cb() - Fabric port logout IOCB callback. - * @ha: HA context - * @iodesc: io descriptor - * @mbxstat: mailbox status IOCB - * - * Returns QLA_SUCCESS if @iodesc can be freed by the caller, else, @iodesc - * will be used for a retry. - */ -static int -qla2x00_send_logout_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc, - struct mbx_entry *mbxstat) -{ - DEBUG14(printk("scsi(%ld): Logout IOCB -- sent to [%x/%02x%02x%02x], " - "status=%x mb0=%x mb1=%x.\n", ha->host_no, - iodesc->remote_fcport->loop_id, - iodesc->remote_fcport->d_id.b.domain, - iodesc->remote_fcport->d_id.b.area, - iodesc->remote_fcport->d_id.b.al_pa, le16_to_cpu(mbxstat->status), - le16_to_cpu(mbxstat->mb0), le16_to_cpu(mbxstat->mb1))); - - return (QLA_SUCCESS); -} - - -/** - * qla2x00_send_login_iocb() - Issue a fabric port login IOCB to the firmware. - * @ha: HA context - * @iodesc: io descriptor - * @d_id: port id for device - * @ha_locked: is function called with the hardware lock - * - * Returns QLA_SUCCESS if the IOCB was issued. - */ -static int -qla2x00_send_login_iocb(scsi_qla_host_t *ha, struct io_descriptor *iodesc, - port_id_t *d_id, int ha_locked) -{ - unsigned long flags = 0; - struct mbx_entry *mbxentry; - - /* Send marker if required. */ - if (qla2x00_issue_marker(ha, ha_locked) != QLA_SUCCESS) - return (QLA_FUNCTION_FAILED); - - if (!ha_locked) - spin_lock_irqsave(&ha->hardware_lock, flags); - - /* Build fabric port login mailbox IOCB. */ - mbxentry = qla2x00_get_mbx_iocb_entry(ha, iodesc->signature); - if (mbxentry == NULL) { - if (!ha_locked) - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - return (QLA_FUNCTION_FAILED); - } - mbxentry->mb0 = __constant_cpu_to_le16(MBC_LOGIN_FABRIC_PORT); - mbxentry->mb1 = mbxentry->loop_id.extended = - cpu_to_le16(iodesc->remote_fcport->loop_id); - mbxentry->mb2 = cpu_to_le16(d_id->b.domain); - mbxentry->mb3 = cpu_to_le16(d_id->b.area << 8 | d_id->b.al_pa); - mbxentry->mb10 = __constant_cpu_to_le16(BIT_0); - wmb(); - - qla2x00_add_iodesc_timer(iodesc); - - /* Issue command to ISP. */ - qla2x00_isp_cmd(ha); - - if (!ha_locked) - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - DEBUG14(printk("scsi(%ld): Sending Login IOCB (%08x) to " - "[%x/%02x%02x%02x].\n", ha->host_no, iodesc->signature, - iodesc->remote_fcport->loop_id, d_id->b.domain, d_id->b.area, - d_id->b.al_pa)); - - return (QLA_SUCCESS); -} - -/** - * qla2x00_send_login_iocb_cb() - Fabric port logout IOCB callback. - * @ha: HA context - * @iodesc: io descriptor - * @mbxstat: mailbox status IOCB - * - * Returns QLA_SUCCESS if @iodesc can be freed by the caller, else, @iodesc - * will be used for a retry. - */ -static int -qla2x00_send_login_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc, - struct mbx_entry *mbxstat) -{ - int rval; - fc_port_t *fcport, *remote_fcport, *exist_fcport; - struct io_descriptor *abort_iodesc, *login_iodesc; - uint16_t status, mb[8]; - uint16_t reuse; - uint16_t remote_loopid; - port_id_t remote_did, inuse_did; - - remote_fcport = iodesc->remote_fcport; - - /* Only process the last command. */ - if (remote_fcport->iodesc_idx_sent != iodesc->idx) { - DEBUG14(printk("scsi(%ld): Login IOCB -- ignoring, sent to " - "[%02x%02x%02x], expected %x, received %x.\n", - ha->host_no, iodesc->d_id.b.domain, iodesc->d_id.b.area, - iodesc->d_id.b.al_pa, remote_fcport->iodesc_idx_sent, - iodesc->idx)); - - /* Free RSCN fcport resources. */ - if (remote_fcport->port_type == FCT_RSCN) { - DEBUG14(printk("scsi(%ld): Login IOCB -- Freeing RSCN " - "fcport %p [%x/%02x%02x%02x] given ignored Login " - "IOCB.\n", ha->host_no, remote_fcport, - remote_fcport->loop_id, - remote_fcport->d_id.b.domain, - remote_fcport->d_id.b.area, - remote_fcport->d_id.b.al_pa)); - - list_del(&remote_fcport->list); - kfree(remote_fcport); - } - return (QLA_SUCCESS); - } - - status = le16_to_cpu(mbxstat->status); - mb[0] = le16_to_cpu(mbxstat->mb0); - mb[1] = le16_to_cpu(mbxstat->mb1); - mb[2] = le16_to_cpu(mbxstat->mb2); - mb[6] = le16_to_cpu(mbxstat->mb6); - mb[7] = le16_to_cpu(mbxstat->mb7); - - /* Good status? */ - if ((status == CS_COMPLETE || status == CS_COMPLETE_CHKCOND) && - mb[0] == MBS_COMMAND_COMPLETE) { - - DEBUG14(printk("scsi(%ld): Login IOCB -- status=%x mb1=%x pn=" - "%02x%02x%02x%02x%02x%02x%02x%02x.\n", ha->host_no, status, - mb[1], mbxstat->port_name[0], mbxstat->port_name[1], - mbxstat->port_name[2], mbxstat->port_name[3], - mbxstat->port_name[4], mbxstat->port_name[5], - mbxstat->port_name[6], mbxstat->port_name[7])); - - memcpy(remote_fcport->node_name, mbxstat->node_name, WWN_SIZE); - memcpy(remote_fcport->port_name, mbxstat->port_name, WWN_SIZE); - - /* Is the device already in our fcports list? */ - if (remote_fcport->port_type != FCT_RSCN) { - DEBUG14(printk("scsi(%ld): Login IOCB -- marking " - "[%x/%02x%02x%02x] online.\n", ha->host_no, - remote_fcport->loop_id, - remote_fcport->d_id.b.domain, - remote_fcport->d_id.b.area, - remote_fcport->d_id.b.al_pa)); - - qla2x00_update_login_fcport(ha, mbxstat, remote_fcport); - - return (QLA_SUCCESS); - } - - /* Does the RSCN portname already exist in our fcports list? */ - exist_fcport = NULL; - list_for_each_entry(fcport, &ha->fcports, list) { - if (memcmp(remote_fcport->port_name, fcport->port_name, - WWN_SIZE) == 0) { - exist_fcport = fcport; - break; - } - } - if (exist_fcport != NULL) { - DEBUG14(printk("scsi(%ld): Login IOCB -- found RSCN " - "fcport in fcports list [%p].\n", ha->host_no, - exist_fcport)); - - /* Abort any ADISC that could have been sent. */ - if (exist_fcport->iodesc_idx_sent != iodesc->idx && - exist_fcport->iodesc_idx_sent < - MAX_IO_DESCRIPTORS && - ha->io_descriptors[exist_fcport->iodesc_idx_sent]. - cb_idx == ADISC_PORT_IOCB_CB) { - - abort_iodesc = qla2x00_alloc_iodesc(ha); - if (abort_iodesc) { - DEBUG14(printk("scsi(%ld): Login IOCB " - "-- issuing abort to outstanding " - "Adisc [%x/%02x%02x%02x].\n", - ha->host_no, remote_fcport->loop_id, - exist_fcport->d_id.b.domain, - exist_fcport->d_id.b.area, - exist_fcport->d_id.b.al_pa)); - - abort_iodesc->cb_idx = ABORT_IOCB_CB; - abort_iodesc->d_id.b24 = - exist_fcport->d_id.b24; - abort_iodesc->remote_fcport = - exist_fcport; - exist_fcport->iodesc_idx_sent = - abort_iodesc->idx; - qla2x00_send_abort_iocb(ha, - abort_iodesc, ha->io_descriptors[ - exist_fcport->iodesc_idx_sent]. - signature, 1); - } else { - DEBUG14(printk("scsi(%ld): Login IOCB " - "-- unable to abort outstanding " - "Adisc [%x/%02x%02x%02x].\n", - ha->host_no, remote_fcport->loop_id, - exist_fcport->d_id.b.domain, - exist_fcport->d_id.b.area, - exist_fcport->d_id.b.al_pa)); - } - } - - /* - * If the existing fcport is waiting to send an ADISC - * or LOGIN, then reuse remote fcport (RSCN) to - * continue waiting. - */ - reuse = 0; - remote_loopid = remote_fcport->loop_id; - remote_did.b24 = remote_fcport->d_id.b24; - if (exist_fcport->iodesc_idx_sent == - IODESC_ADISC_NEEDED || - exist_fcport->iodesc_idx_sent == - IODESC_LOGIN_NEEDED) { - DEBUG14(printk("scsi(%ld): Login IOCB -- " - "existing fcport [%x/%02x%02x%02x] " - "waiting for IO descriptor, reuse RSCN " - "fcport.\n", ha->host_no, - exist_fcport->loop_id, - exist_fcport->d_id.b.domain, - exist_fcport->d_id.b.area, - exist_fcport->d_id.b.al_pa)); - - reuse++; - remote_fcport->iodesc_idx_sent = - exist_fcport->iodesc_idx_sent; - exist_fcport->iodesc_idx_sent = - IODESC_INVALID_INDEX; - remote_fcport->loop_id = exist_fcport->loop_id; - remote_fcport->d_id.b24 = - exist_fcport->d_id.b24; - } - - /* Logout the old loopid. */ - if (!reuse && - exist_fcport->loop_id != remote_fcport->loop_id && - exist_fcport->loop_id != FC_NO_LOOP_ID) { - login_iodesc = qla2x00_alloc_iodesc(ha); - if (login_iodesc) { - DEBUG14(printk("scsi(%ld): Login IOCB " - "-- issuing logout to free old " - "loop id [%x/%02x%02x%02x].\n", - ha->host_no, exist_fcport->loop_id, - exist_fcport->d_id.b.domain, - exist_fcport->d_id.b.area, - exist_fcport->d_id.b.al_pa)); - - login_iodesc->cb_idx = - LOGOUT_PORT_IOCB_CB; - login_iodesc->d_id.b24 = - exist_fcport->d_id.b24; - login_iodesc->remote_fcport = - exist_fcport; - exist_fcport->iodesc_idx_sent = - login_iodesc->idx; - qla2x00_send_logout_iocb(ha, - login_iodesc, 1); - } else { - /* Ran out of IO descriptiors. */ - DEBUG14(printk("scsi(%ld): Login IOCB " - "-- unable to logout to free old " - "loop id [%x/%02x%02x%02x].\n", - ha->host_no, exist_fcport->loop_id, - exist_fcport->d_id.b.domain, - exist_fcport->d_id.b.area, - exist_fcport->d_id.b.al_pa)); - - exist_fcport->iodesc_idx_sent = - IODESC_INVALID_INDEX; - } - - } - - /* Update existing fcport with remote fcport info. */ - DEBUG14(printk("scsi(%ld): Login IOCB -- marking " - "existing fcport [%x/%02x%02x%02x] online.\n", - ha->host_no, remote_loopid, remote_did.b.domain, - remote_did.b.area, remote_did.b.al_pa)); - - memcpy(exist_fcport->node_name, - remote_fcport->node_name, WWN_SIZE); - exist_fcport->loop_id = remote_loopid; - exist_fcport->d_id.b24 = remote_did.b24; - qla2x00_update_login_fcport(ha, mbxstat, exist_fcport); - - /* Finally, free the remote (RSCN) fcport. */ - if (!reuse) { - DEBUG14(printk("scsi(%ld): Login IOCB -- " - "Freeing RSCN fcport %p " - "[%x/%02x%02x%02x].\n", ha->host_no, - remote_fcport, remote_fcport->loop_id, - remote_fcport->d_id.b.domain, - remote_fcport->d_id.b.area, - remote_fcport->d_id.b.al_pa)); - - list_del(&remote_fcport->list); - kfree(remote_fcport); - } - - return (QLA_SUCCESS); - } - - /* - * A new device has been added, move the RSCN fcport to our - * fcports list. - */ - DEBUG14(printk("scsi(%ld): Login IOCB -- adding RSCN fcport " - "[%x/%02x%02x%02x] to fcports list.\n", ha->host_no, - remote_fcport->loop_id, remote_fcport->d_id.b.domain, - remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa)); - - list_del(&remote_fcport->list); - remote_fcport->flags = (FCF_RLC_SUPPORT | FCF_RESCAN_NEEDED); - qla2x00_update_login_fcport(ha, mbxstat, remote_fcport); - list_add_tail(&remote_fcport->list, &ha->fcports); - set_bit(FCPORT_RESCAN_NEEDED, &ha->dpc_flags); - } else { - /* Handle login failure. */ - if (remote_fcport->login_retry != 0) { - if (mb[0] == MBS_LOOP_ID_USED) { - inuse_did.b.domain = LSB(mb[1]); - inuse_did.b.area = MSB(mb[2]); - inuse_did.b.al_pa = LSB(mb[2]); - - DEBUG14(printk("scsi(%ld): Login IOCB -- loop " - "id [%x] used by port id [%02x%02x%02x].\n", - ha->host_no, remote_fcport->loop_id, - inuse_did.b.domain, inuse_did.b.area, - inuse_did.b.al_pa)); - - if (remote_fcport->d_id.b24 == - INVALID_PORT_ID) { - /* - * Invalid port id means we are trying - * to login to a remote port with just - * a loop id without knowing about the - * port id. Copy the port id and try - * again. - */ - remote_fcport->d_id.b24 = inuse_did.b24; - iodesc->d_id.b24 = inuse_did.b24; - } else { - remote_fcport->loop_id++; - rval = qla2x00_find_new_loop_id(ha, - remote_fcport); - if (rval == QLA_FUNCTION_FAILED) { - /* No more loop ids. */ - return (QLA_SUCCESS); - } - } - } else if (mb[0] == MBS_PORT_ID_USED) { - /* - * Device has another loop ID. The firmware - * group recommends the driver perform an - * implicit login with the specified ID. - */ - DEBUG14(printk("scsi(%ld): Login IOCB -- port " - "id [%02x%02x%02x] already assigned to " - "loop id [%x].\n", ha->host_no, - iodesc->d_id.b.domain, iodesc->d_id.b.area, - iodesc->d_id.b.al_pa, mb[1])); - - remote_fcport->loop_id = mb[1]; - - } else { - /* Unable to perform login, try again. */ - DEBUG14(printk("scsi(%ld): Login IOCB -- " - "failed login [%x/%02x%02x%02x], status=%x " - "mb0=%x mb1=%x mb2=%x mb6=%x mb7=%x.\n", - ha->host_no, remote_fcport->loop_id, - iodesc->d_id.b.domain, iodesc->d_id.b.area, - iodesc->d_id.b.al_pa, status, mb[0], mb[1], - mb[2], mb[6], mb[7])); - } - - /* Reissue Login with the same IO descriptor. */ - iodesc->signature = - qla2x00_iodesc_to_handle(iodesc); - iodesc->cb_idx = LOGIN_PORT_IOCB_CB; - iodesc->d_id.b24 = remote_fcport->d_id.b24; - remote_fcport->iodesc_idx_sent = iodesc->idx; - remote_fcport->login_retry--; - - DEBUG14(printk("scsi(%ld): Login IOCB -- retrying " - "login to [%x/%02x%02x%02x] (%d).\n", ha->host_no, - remote_fcport->loop_id, - remote_fcport->d_id.b.domain, - remote_fcport->d_id.b.area, - remote_fcport->d_id.b.al_pa, - remote_fcport->login_retry)); - - qla2x00_send_login_iocb(ha, iodesc, - &remote_fcport->d_id, 1); - - return (QLA_FUNCTION_FAILED); - } else { - /* No more logins, mark device dead. */ - DEBUG14(printk("scsi(%ld): Login IOCB -- failed " - "login [%x/%02x%02x%02x] after retries, status=%x " - "mb0=%x mb1=%x mb2=%x mb6=%x mb7=%x.\n", - ha->host_no, remote_fcport->loop_id, - iodesc->d_id.b.domain, iodesc->d_id.b.area, - iodesc->d_id.b.al_pa, status, mb[0], mb[1], - mb[2], mb[6], mb[7])); - - atomic_set(&remote_fcport->state, FCS_DEVICE_DEAD); - if (remote_fcport->port_type == FCT_RSCN) { - DEBUG14(printk("scsi(%ld): Login IOCB -- " - "Freeing dead RSCN fcport %p " - "[%x/%02x%02x%02x].\n", ha->host_no, - remote_fcport, remote_fcport->loop_id, - remote_fcport->d_id.b.domain, - remote_fcport->d_id.b.area, - remote_fcport->d_id.b.al_pa)); - - list_del(&remote_fcport->list); - kfree(remote_fcport); - } - } - } - - return (QLA_SUCCESS); -} - - -/** - * IO descriptor processing routines. - **/ - -/** - * qla2x00_alloc_rscn_fcport() - Allocate an RSCN type fcport. - * @ha: HA context - * @flags: allocation flags - * - * Returns a pointer to the allocated RSCN fcport, or NULL, if none available. - */ -fc_port_t * -qla2x00_alloc_rscn_fcport(scsi_qla_host_t *ha, gfp_t flags) -{ - fc_port_t *fcport; - - fcport = qla2x00_alloc_fcport(ha, flags); - if (fcport == NULL) - return (fcport); - - /* Setup RSCN fcport structure. */ - fcport->port_type = FCT_RSCN; - - return (fcport); -} - -/** - * qla2x00_handle_port_rscn() - Handle port RSCN. - * @ha: HA context - * @rscn_entry: RSCN entry - * @fcport: fcport entry to updated - * - * Returns QLA_SUCCESS if the port RSCN was handled. - */ -int -qla2x00_handle_port_rscn(scsi_qla_host_t *ha, uint32_t rscn_entry, - fc_port_t *known_fcport, int ha_locked) -{ - int rval; - port_id_t rscn_pid; - fc_port_t *fcport, *remote_fcport, *rscn_fcport; - struct io_descriptor *iodesc; - - remote_fcport = NULL; - rscn_fcport = NULL; - - /* Prepare port id based on incoming entries. */ - if (known_fcport) { - rscn_pid.b24 = known_fcport->d_id.b24; - remote_fcport = known_fcport; - - DEBUG14(printk("scsi(%ld): Handle RSCN -- process RSCN for " - "fcport [%02x%02x%02x].\n", ha->host_no, - remote_fcport->d_id.b.domain, remote_fcport->d_id.b.area, - remote_fcport->d_id.b.al_pa)); - } else { - rscn_pid.b.domain = LSB(MSW(rscn_entry)); - rscn_pid.b.area = MSB(LSW(rscn_entry)); - rscn_pid.b.al_pa = LSB(LSW(rscn_entry)); - - DEBUG14(printk("scsi(%ld): Handle RSCN -- process RSCN for " - "port id [%02x%02x%02x].\n", ha->host_no, - rscn_pid.b.domain, rscn_pid.b.area, rscn_pid.b.al_pa)); - - /* - * Search fcport lists for a known entry at the specified port - * ID. - */ - list_for_each_entry(fcport, &ha->fcports, list) { - if (rscn_pid.b24 == fcport->d_id.b24) { - remote_fcport = fcport; - break; - } - } - list_for_each_entry(fcport, &ha->rscn_fcports, list) { - if (rscn_pid.b24 == fcport->d_id.b24) { - rscn_fcport = fcport; - break; - } - } - if (remote_fcport == NULL) - remote_fcport = rscn_fcport; - } - - /* - * If the port is already in our fcport list and online, send an ADISC - * to see if it's still alive. Issue login if a new fcport or the known - * fcport is currently offline. - */ - if (remote_fcport) { - /* - * No need to send request if the remote fcport is currently - * waiting for an available io descriptor. - */ - if (known_fcport == NULL && - (remote_fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED || - remote_fcport->iodesc_idx_sent == IODESC_LOGIN_NEEDED)) { - /* - * If previous waiting io descriptor is an ADISC, then - * the new RSCN may come from a new remote fcport being - * plugged into the same location. - */ - if (remote_fcport->port_type == FCT_RSCN) { - remote_fcport->iodesc_idx_sent = - IODESC_LOGIN_NEEDED; - } else if (remote_fcport->iodesc_idx_sent == - IODESC_ADISC_NEEDED) { - fc_port_t *new_fcport; - - remote_fcport->iodesc_idx_sent = - IODESC_INVALID_INDEX; - - /* Create new fcport for later login. */ - new_fcport = qla2x00_alloc_rscn_fcport(ha, - ha_locked ? GFP_ATOMIC: GFP_KERNEL); - if (new_fcport) { - DEBUG14(printk("scsi(%ld): Handle RSCN " - "-- creating RSCN fcport %p for " - "future login.\n", ha->host_no, - new_fcport)); - - new_fcport->d_id.b24 = - remote_fcport->d_id.b24; - new_fcport->iodesc_idx_sent = - IODESC_LOGIN_NEEDED; - - list_add_tail(&new_fcport->list, - &ha->rscn_fcports); - set_bit(IODESC_PROCESS_NEEDED, - &ha->dpc_flags); - } else { - DEBUG14(printk("scsi(%ld): Handle RSCN " - "-- unable to allocate RSCN fcport " - "for future login.\n", - ha->host_no)); - } - } - return (QLA_SUCCESS); - } - - /* Send ADISC if the fcport is online */ - if (atomic_read(&remote_fcport->state) == FCS_ONLINE || - remote_fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED) { - - atomic_set(&remote_fcport->state, FCS_DEVICE_LOST); - - iodesc = qla2x00_alloc_iodesc(ha); - if (iodesc == NULL) { - /* Mark fcport for later adisc processing */ - DEBUG14(printk("scsi(%ld): Handle RSCN -- not " - "enough IO descriptors for Adisc, flag " - "for later processing.\n", ha->host_no)); - - remote_fcport->iodesc_idx_sent = - IODESC_ADISC_NEEDED; - set_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags); - - return (QLA_SUCCESS); - } - - iodesc->cb_idx = ADISC_PORT_IOCB_CB; - iodesc->d_id.b24 = rscn_pid.b24; - iodesc->remote_fcport = remote_fcport; - remote_fcport->iodesc_idx_sent = iodesc->idx; - qla2x00_send_adisc_iocb(ha, iodesc, ha_locked); - - return (QLA_SUCCESS); - } else if (remote_fcport->iodesc_idx_sent < - MAX_IO_DESCRIPTORS && - ha->io_descriptors[remote_fcport->iodesc_idx_sent].cb_idx == - ADISC_PORT_IOCB_CB) { - /* - * Receiving another RSCN while an ADISC is pending, - * abort the IOCB. Use the same descriptor for the - * abort. - */ - uint32_t handle_to_abort; - - iodesc = &ha->io_descriptors[ - remote_fcport->iodesc_idx_sent]; - qla2x00_remove_iodesc_timer(iodesc); - handle_to_abort = iodesc->signature; - iodesc->signature = qla2x00_iodesc_to_handle(iodesc); - iodesc->cb_idx = ABORT_IOCB_CB; - iodesc->d_id.b24 = remote_fcport->d_id.b24; - iodesc->remote_fcport = remote_fcport; - remote_fcport->iodesc_idx_sent = iodesc->idx; - - DEBUG14(printk("scsi(%ld): Handle RSCN -- issuing " - "abort to outstanding Adisc [%x/%02x%02x%02x].\n", - ha->host_no, remote_fcport->loop_id, - iodesc->d_id.b.domain, iodesc->d_id.b.area, - iodesc->d_id.b.al_pa)); - - qla2x00_send_abort_iocb(ha, iodesc, handle_to_abort, - ha_locked); - } - } - - /* We need to login to the remote port, find it. */ - if (known_fcport) { - remote_fcport = known_fcport; - } else if (rscn_fcport && rscn_fcport->d_id.b24 != INVALID_PORT_ID && - rscn_fcport->iodesc_idx_sent < MAX_IO_DESCRIPTORS && - ha->io_descriptors[rscn_fcport->iodesc_idx_sent].cb_idx == - LOGIN_PORT_IOCB_CB) { - /* - * Ignore duplicate RSCN on fcport which has already - * initiated a login IOCB. - */ - DEBUG14(printk("scsi(%ld): Handle RSCN -- ignoring, login " - "already sent to [%02x%02x%02x].\n", ha->host_no, - rscn_fcport->d_id.b.domain, rscn_fcport->d_id.b.area, - rscn_fcport->d_id.b.al_pa)); - - return (QLA_SUCCESS); - } else if (rscn_fcport && rscn_fcport->d_id.b24 != INVALID_PORT_ID && - rscn_fcport != remote_fcport) { - /* Reuse same rscn fcport. */ - DEBUG14(printk("scsi(%ld): Handle RSCN -- reusing RSCN fcport " - "[%02x%02x%02x].\n", ha->host_no, - rscn_fcport->d_id.b.domain, rscn_fcport->d_id.b.area, - rscn_fcport->d_id.b.al_pa)); - - remote_fcport = rscn_fcport; - } else { - /* Create new fcport for later login. */ - remote_fcport = qla2x00_alloc_rscn_fcport(ha, - ha_locked ? GFP_ATOMIC: GFP_KERNEL); - list_add_tail(&remote_fcport->list, &ha->rscn_fcports); - } - if (remote_fcport == NULL) - return (QLA_SUCCESS); - - /* Prepare fcport for login. */ - atomic_set(&remote_fcport->state, FCS_DEVICE_LOST); - remote_fcport->login_retry = 3; /* ha->login_retry_count; */ - remote_fcport->d_id.b24 = rscn_pid.b24; - - iodesc = qla2x00_alloc_iodesc(ha); - if (iodesc == NULL) { - /* Mark fcport for later adisc processing. */ - DEBUG14(printk("scsi(%ld): Handle RSCN -- not enough IO " - "descriptors for Login, flag for later processing.\n", - ha->host_no)); - - remote_fcport->iodesc_idx_sent = IODESC_LOGIN_NEEDED; - set_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags); - - return (QLA_SUCCESS); - } - - if (known_fcport == NULL || rscn_pid.b24 != INVALID_PORT_ID) { - remote_fcport->loop_id = ha->min_external_loopid; - - rval = qla2x00_find_new_loop_id(ha, remote_fcport); - if (rval == QLA_FUNCTION_FAILED) { - /* No more loop ids, failed. */ - DEBUG14(printk("scsi(%ld): Handle RSCN -- no available " - "loop id to perform Login, failed.\n", - ha->host_no)); - - return (rval); - } - } - - iodesc->cb_idx = LOGIN_PORT_IOCB_CB; - iodesc->d_id.b24 = rscn_pid.b24; - iodesc->remote_fcport = remote_fcport; - remote_fcport->iodesc_idx_sent = iodesc->idx; - - DEBUG14(printk("scsi(%ld): Handle RSCN -- attempting login to " - "[%x/%02x%02x%02x].\n", ha->host_no, remote_fcport->loop_id, - iodesc->d_id.b.domain, iodesc->d_id.b.area, iodesc->d_id.b.al_pa)); - - qla2x00_send_login_iocb(ha, iodesc, &rscn_pid, ha_locked); - - return (QLA_SUCCESS); -} - -/** - * qla2x00_process_iodesc() - Complete IO descriptor processing. - * @ha: HA context - * @mbxstat: Mailbox IOCB status - */ -void -qla2x00_process_iodesc(scsi_qla_host_t *ha, struct mbx_entry *mbxstat) -{ - int rval; - uint32_t signature; - fc_port_t *fcport; - struct io_descriptor *iodesc; - - signature = mbxstat->handle; - - DEBUG14(printk("scsi(%ld): Process IODesc -- processing %08x.\n", - ha->host_no, signature)); - - /* Retrieve proper IO descriptor. */ - iodesc = qla2x00_handle_to_iodesc(ha, signature); - if (iodesc == NULL) { - DEBUG14(printk("scsi(%ld): Process IODesc -- ignoring, " - "incorrect signature %08x.\n", ha->host_no, signature)); - - return; - } - - /* Stop IO descriptor timer. */ - qla2x00_remove_iodesc_timer(iodesc); - - /* Verify signature match. */ - if (iodesc->signature != signature) { - DEBUG14(printk("scsi(%ld): Process IODesc -- ignoring, " - "signature mismatch, sent %08x, received %08x.\n", - ha->host_no, iodesc->signature, signature)); - - return; - } - - /* Go with IOCB callback. */ - rval = iocb_function_cb_list[iodesc->cb_idx](ha, iodesc, mbxstat); - if (rval != QLA_SUCCESS) { - /* IO descriptor reused by callback. */ - return; - } - - qla2x00_free_iodesc(iodesc); - - if (test_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags)) { - /* Scan our fcports list for any RSCN requests. */ - list_for_each_entry(fcport, &ha->fcports, list) { - if (fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED || - fcport->iodesc_idx_sent == IODESC_LOGIN_NEEDED) { - qla2x00_handle_port_rscn(ha, 0, fcport, 1); - return; - } - } - - /* Scan our RSCN fcports list for any RSCN requests. */ - list_for_each_entry(fcport, &ha->rscn_fcports, list) { - if (fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED || - fcport->iodesc_idx_sent == IODESC_LOGIN_NEEDED) { - qla2x00_handle_port_rscn(ha, 0, fcport, 1); - return; - } - } - } - clear_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags); -} - -/** - * qla2x00_cancel_io_descriptors() - Cancel all outstanding io descriptors. - * @ha: HA context - * - * This routine will also delete any RSCN entries related to the outstanding - * IO descriptors. - */ -void -qla2x00_cancel_io_descriptors(scsi_qla_host_t *ha) -{ - fc_port_t *fcport, *fcptemp; - - clear_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags); - - /* Abort all IO descriptors. */ - qla2x00_init_io_descriptors(ha); - - /* Reset all pending IO descriptors in fcports list. */ - list_for_each_entry(fcport, &ha->fcports, list) { - fcport->iodesc_idx_sent = IODESC_INVALID_INDEX; - } - - /* Reset all pending IO descriptors in rscn fcports list. */ - list_for_each_entry_safe(fcport, fcptemp, &ha->rscn_fcports, list) { - DEBUG14(printk("scsi(%ld): Cancel IOs -- Freeing RSCN fcport " - "%p [%x/%02x%02x%02x].\n", ha->host_no, fcport, - fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, - fcport->d_id.b.al_pa)); - - list_del(&fcport->list); - kfree(fcport); - } -} |