aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAndrew Vasquez <andrew.vasquez@qlogic.com>2006-05-17 18:09:27 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-05-20 10:43:44 -0400
commit4971cd221ad3f1266b87aa0e996d082d91bac2a6 (patch)
treed4fc40793c825ecdb788533efc2d1376fa51b03f /drivers
parent75bc4190701d3c6bdffdc21c8a9e17751de9f77a (diff)
[SCSI] qla2xxx: Remove unused port-type RSCN handling code.
Expandind on the previous commit: commit 79f89a4296ff22f09baf538d4ff2a6d0c3097a73 Author: andrew.vasquez@qlogic.com <andrew.vasquez@qlogic.com> Date: Fri Jan 13 17:05:58 2006 -0800 [SCSI] qla2xxx: Disable port-type RSCN handling via driver state-machine. and given: - the process-context requirements of the FC transport rport-APIs. - lack of port-type RSCN processing logic for ISP24xx and newer chips. it's time now to remove the state-machine logic from mainline. Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/qla2xxx/Makefile2
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h37
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h10
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c17
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c60
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c31
-rw-r--r--drivers/scsi/qla2xxx/qla_rscn.c1425
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 @@
1EXTRA_CFLAGS += -DUNIQUE_FW_NAME 1EXTRA_CFLAGS += -DUNIQUE_FW_NAME
2 2
3qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \ 3qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \
4 qla_dbg.o qla_sup.o qla_rscn.o qla_attr.o 4 qla_dbg.o qla_sup.o qla_attr.o
5 5
6obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o 6obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o
7 7
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 {
1523 1523
1524 unsigned int os_target_id; 1524 unsigned int os_target_id;
1525 1525
1526 uint16_t iodesc_idx_sent;
1527
1528 int port_login_retry_count; 1526 int port_login_retry_count;
1529 int login_retry; 1527 int login_retry;
1530 atomic_t port_down_timer; 1528 atomic_t port_down_timer;
@@ -1940,34 +1938,6 @@ struct sns_cmd_pkt {
1940 } p; 1938 } p;
1941}; 1939};
1942 1940
1943/* IO descriptors */
1944#define MAX_IO_DESCRIPTORS 32
1945
1946#define ABORT_IOCB_CB 0
1947#define ADISC_PORT_IOCB_CB 1
1948#define LOGOUT_PORT_IOCB_CB 2
1949#define LOGIN_PORT_IOCB_CB 3
1950#define LAST_IOCB_CB 4
1951
1952#define IODESC_INVALID_INDEX 0xFFFF
1953#define IODESC_ADISC_NEEDED 0xFFFE
1954#define IODESC_LOGIN_NEEDED 0xFFFD
1955
1956struct io_descriptor {
1957 uint16_t used:1;
1958 uint16_t idx:11;
1959 uint16_t cb_idx:4;
1960
1961 struct timer_list timer;
1962
1963 struct scsi_qla_host *ha;
1964
1965 port_id_t d_id;
1966 fc_port_t *remote_fcport;
1967
1968 uint32_t signature;
1969};
1970
1971struct qla_fw_info { 1941struct qla_fw_info {
1972 unsigned short addressing; /* addressing method used to load fw */ 1942 unsigned short addressing; /* addressing method used to load fw */
1973#define FW_INFO_ADDR_NORMAL 0 1943#define FW_INFO_ADDR_NORMAL 0
@@ -2271,10 +2241,6 @@ typedef struct scsi_qla_host {
2271 2241
2272 /* Fibre Channel Device List. */ 2242 /* Fibre Channel Device List. */
2273 struct list_head fcports; 2243 struct list_head fcports;
2274 struct list_head rscn_fcports;
2275
2276 struct io_descriptor io_descriptors[MAX_IO_DESCRIPTORS];
2277 uint16_t iodesc_signature;
2278 2244
2279 /* RSCN queue. */ 2245 /* RSCN queue. */
2280 uint32_t rscn_queue[MAX_RSCN_COUNT]; 2246 uint32_t rscn_queue[MAX_RSCN_COUNT];
@@ -2313,9 +2279,6 @@ typedef struct scsi_qla_host {
2313 init_cb_t *init_cb; 2279 init_cb_t *init_cb;
2314 int init_cb_size; 2280 int init_cb_size;
2315 2281
2316 dma_addr_t iodesc_pd_dma;
2317 port_database_t *iodesc_pd;
2318
2319 /* These are used by mailbox operations. */ 2282 /* These are used by mailbox operations. */
2320 volatile uint16_t mailbox_out[MAILBOX_REGISTER_COUNT]; 2283 volatile uint16_t mailbox_out[MAILBOX_REGISTER_COUNT];
2321 2284
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;
64extern int ql2xplogiabsentdevice; 64extern int ql2xplogiabsentdevice;
65extern int ql2xloginretrycount; 65extern int ql2xloginretrycount;
66extern int ql2xfdmienable; 66extern int ql2xfdmienable;
67extern int ql2xprocessrscn;
68 67
69extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *); 68extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *);
70 69
@@ -284,15 +283,6 @@ extern void *qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *, uint32_t, uint32_t);
284extern int qla2x00_fdmi_register(scsi_qla_host_t *); 283extern int qla2x00_fdmi_register(scsi_qla_host_t *);
285 284
286/* 285/*
287 * Global Function Prototypes in qla_rscn.c source file.
288 */
289extern fc_port_t *qla2x00_alloc_rscn_fcport(scsi_qla_host_t *, gfp_t);
290extern int qla2x00_handle_port_rscn(scsi_qla_host_t *, uint32_t, fc_port_t *,
291 int);
292extern void qla2x00_process_iodesc(scsi_qla_host_t *, struct mbx_entry *);
293extern void qla2x00_cancel_io_descriptors(scsi_qla_host_t *);
294
295/*
296 * Global Function Prototypes in qla_xioctl.c source file. 286 * Global Function Prototypes in qla_xioctl.c source file.
297 */ 287 */
298#define qla2x00_enqueue_aen(ha, cmd, mode) do { } while (0) 288#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)
1708 fcport->ha = ha; 1708 fcport->ha = ha;
1709 fcport->port_type = FCT_UNKNOWN; 1709 fcport->port_type = FCT_UNKNOWN;
1710 fcport->loop_id = FC_NO_LOOP_ID; 1710 fcport->loop_id = FC_NO_LOOP_ID;
1711 fcport->iodesc_idx_sent = IODESC_INVALID_INDEX;
1712 atomic_set(&fcport->state, FCS_UNCONFIGURED); 1711 atomic_set(&fcport->state, FCS_UNCONFIGURED);
1713 fcport->flags = FCF_RLC_SUPPORT; 1712 fcport->flags = FCF_RLC_SUPPORT;
1714 fcport->supported_classes = FC_COS_UNSPECIFIED; 1713 fcport->supported_classes = FC_COS_UNSPECIFIED;
@@ -2563,7 +2562,6 @@ static int
2563qla2x00_device_resync(scsi_qla_host_t *ha) 2562qla2x00_device_resync(scsi_qla_host_t *ha)
2564{ 2563{
2565 int rval; 2564 int rval;
2566 int rval2;
2567 uint32_t mask; 2565 uint32_t mask;
2568 fc_port_t *fcport; 2566 fc_port_t *fcport;
2569 uint32_t rscn_entry; 2567 uint32_t rscn_entry;
@@ -2619,17 +2617,6 @@ qla2x00_device_resync(scsi_qla_host_t *ha)
2619 2617
2620 switch (format) { 2618 switch (format) {
2621 case 0: 2619 case 0:
2622 if (ql2xprocessrscn &&
2623 !IS_QLA2100(ha) && !IS_QLA2200(ha) &&
2624 !IS_QLA6312(ha) && !IS_QLA6322(ha) &&
2625 !IS_QLA24XX(ha) && !IS_QLA54XX(ha) &&
2626 ha->flags.init_done) {
2627 /* Handle port RSCN via asyncronous IOCBs */
2628 rval2 = qla2x00_handle_port_rscn(ha, rscn_entry,
2629 NULL, 0);
2630 if (rval2 == QLA_SUCCESS)
2631 continue;
2632 }
2633 mask = 0xffffff; 2620 mask = 0xffffff;
2634 break; 2621 break;
2635 case 1: 2622 case 1:
@@ -2647,10 +2634,6 @@ qla2x00_device_resync(scsi_qla_host_t *ha)
2647 2634
2648 rval = QLA_SUCCESS; 2635 rval = QLA_SUCCESS;
2649 2636
2650 /* Abort any outstanding IO descriptors. */
2651 if (!IS_QLA2100(ha) && !IS_QLA2200(ha))
2652 qla2x00_cancel_io_descriptors(ha);
2653
2654 list_for_each_entry(fcport, &ha->fcports, list) { 2637 list_for_each_entry(fcport, &ha->fcports, list) {
2655 if ((fcport->flags & FCF_FABRIC_DEVICE) == 0 || 2638 if ((fcport->flags & FCF_FABRIC_DEVICE) == 0 ||
2656 (fcport->d_id.b24 & mask) != d_id.b24 || 2639 (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)
515 515
516 case MBA_PORT_UPDATE: /* Port database update */ 516 case MBA_PORT_UPDATE: /* Port database update */
517 /* 517 /*
518 * If a single remote port just logged into (or logged out of)
519 * us, create a new entry in our rscn fcports list and handle
520 * the event like an RSCN.
521 */
522 if (ql2xprocessrscn &&
523 !IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA6312(ha) &&
524 !IS_QLA6322(ha) && !IS_QLA24XX(ha) && !IS_QLA54XX(ha) &&
525 ha->flags.init_done && mb[1] != 0xffff &&
526 ((ha->operating_mode == P2P && mb[1] != 0) ||
527 (ha->operating_mode != P2P && mb[1] !=
528 SNS_FIRST_LOOP_ID)) && (mb[2] == 6 || mb[2] == 7)) {
529 int rval;
530 fc_port_t *rscn_fcport;
531
532 /* Create new fcport for login. */
533 rscn_fcport = qla2x00_alloc_rscn_fcport(ha, GFP_ATOMIC);
534 if (rscn_fcport) {
535 DEBUG14(printk("scsi(%ld): Port Update -- "
536 "creating RSCN fcport %p for %x/%x/%x.\n",
537 ha->host_no, rscn_fcport, mb[1], mb[2],
538 mb[3]));
539
540 rscn_fcport->loop_id = mb[1];
541 rscn_fcport->d_id.b24 = INVALID_PORT_ID;
542 atomic_set(&rscn_fcport->state,
543 FCS_DEVICE_LOST);
544 list_add_tail(&rscn_fcport->list,
545 &ha->rscn_fcports);
546
547 rval = qla2x00_handle_port_rscn(ha, 0,
548 rscn_fcport, 1);
549 if (rval == QLA_SUCCESS)
550 break;
551 } else {
552 DEBUG14(printk("scsi(%ld): Port Update -- "
553 "-- unable to allocate RSCN fcport "
554 "login.\n", ha->host_no));
555 }
556 }
557
558 /*
559 * If PORT UPDATE is global (recieved LIP_OCCURED/LIP_RESET 518 * If PORT UPDATE is global (recieved LIP_OCCURED/LIP_RESET
560 * event etc. earlier indicating loop is down) then process 519 * event etc. earlier indicating loop is down) then process
561 * it. Otherwise ignore it and Wait for RSCN to come in. 520 * it. Otherwise ignore it and Wait for RSCN to come in.
@@ -753,25 +712,6 @@ qla2x00_process_response_queue(struct scsi_qla_host *ha)
753 case MS_IOCB_TYPE: 712 case MS_IOCB_TYPE:
754 qla2x00_ms_entry(ha, (ms_iocb_entry_t *)pkt); 713 qla2x00_ms_entry(ha, (ms_iocb_entry_t *)pkt);
755 break; 714 break;
756 case MBX_IOCB_TYPE:
757 if (!IS_QLA2100(ha) && !IS_QLA2200(ha) &&
758 !IS_QLA6312(ha) && !IS_QLA6322(ha)) {
759 if (pkt->sys_define == SOURCE_ASYNC_IOCB) {
760 qla2x00_process_iodesc(ha,
761 (struct mbx_entry *)pkt);
762 } else {
763 /* MBX IOCB Type Not Supported. */
764 DEBUG4(printk(KERN_WARNING
765 "scsi(%ld): Received unknown MBX "
766 "IOCB response pkt type=%x "
767 "source=%x entry status=%x.\n",
768 ha->host_no, pkt->entry_type,
769 pkt->sys_define,
770 pkt->entry_status));
771 }
772 break;
773 }
774 /* Fallthrough. */
775 default: 715 default:
776 /* Type Not Supported. */ 716 /* Type Not Supported. */
777 DEBUG4(printk(KERN_WARNING 717 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,
71 "Enables FDMI registratons " 71 "Enables FDMI registratons "
72 "Default is 0 - no FDMI. 1 - perfom FDMI."); 72 "Default is 0 - no FDMI. 1 - perfom FDMI.");
73 73
74int ql2xprocessrscn;
75module_param(ql2xprocessrscn, int, S_IRUGO|S_IRUSR);
76MODULE_PARM_DESC(ql2xprocessrscn,
77 "Option to enable port RSCN handling via a series of less"
78 "fabric intrusive ADISCs and PLOGIs.");
79
80/* 74/*
81 * SCSI host template entry points 75 * SCSI host template entry points
82 */ 76 */
@@ -1492,7 +1486,6 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
1492 1486
1493 INIT_LIST_HEAD(&ha->list); 1487 INIT_LIST_HEAD(&ha->list);
1494 INIT_LIST_HEAD(&ha->fcports); 1488 INIT_LIST_HEAD(&ha->fcports);
1495 INIT_LIST_HEAD(&ha->rscn_fcports);
1496 1489
1497 /* 1490 /*
1498 * These locks are used to prevent more than one CPU 1491 * These locks are used to prevent more than one CPU
@@ -1669,10 +1662,6 @@ EXPORT_SYMBOL_GPL(qla2x00_remove_one);
1669static void 1662static void
1670qla2x00_free_device(scsi_qla_host_t *ha) 1663qla2x00_free_device(scsi_qla_host_t *ha)
1671{ 1664{
1672 /* Abort any outstanding IO descriptors. */
1673 if (!IS_QLA2100(ha) && !IS_QLA2200(ha))
1674 qla2x00_cancel_io_descriptors(ha);
1675
1676 /* Disable timer */ 1665 /* Disable timer */
1677 if (ha->timer_active) 1666 if (ha->timer_active)
1678 qla2x00_stop_timer(ha); 1667 qla2x00_stop_timer(ha);
@@ -1909,21 +1898,6 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha)
1909 } 1898 }
1910 memset(ha->init_cb, 0, ha->init_cb_size); 1899 memset(ha->init_cb, 0, ha->init_cb_size);
1911 1900
1912 /* Get consistent memory allocated for Get Port Database cmd */
1913 ha->iodesc_pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
1914 &ha->iodesc_pd_dma);
1915 if (ha->iodesc_pd == NULL) {
1916 /* error */
1917 qla_printk(KERN_WARNING, ha,
1918 "Memory Allocation failed - iodesc_pd\n");
1919
1920 qla2x00_mem_free(ha);
1921 msleep(100);
1922
1923 continue;
1924 }
1925 memset(ha->iodesc_pd, 0, PORT_DATABASE_SIZE);
1926
1927 /* Allocate ioctl related memory. */ 1901 /* Allocate ioctl related memory. */
1928 if (qla2x00_alloc_ioctl_mem(ha)) { 1902 if (qla2x00_alloc_ioctl_mem(ha)) {
1929 qla_printk(KERN_WARNING, ha, 1903 qla_printk(KERN_WARNING, ha,
@@ -2048,9 +2022,6 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
2048 if (ha->ms_iocb) 2022 if (ha->ms_iocb)
2049 dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma); 2023 dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma);
2050 2024
2051 if (ha->iodesc_pd)
2052 dma_pool_free(ha->s_dma_pool, ha->iodesc_pd, ha->iodesc_pd_dma);
2053
2054 if (ha->init_cb) 2025 if (ha->init_cb)
2055 dma_pool_free(ha->s_dma_pool, ha->init_cb, ha->init_cb_dma); 2026 dma_pool_free(ha->s_dma_pool, ha->init_cb, ha->init_cb_dma);
2056 2027
@@ -2077,8 +2048,6 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
2077 ha->ct_sns_dma = 0; 2048 ha->ct_sns_dma = 0;
2078 ha->ms_iocb = NULL; 2049 ha->ms_iocb = NULL;
2079 ha->ms_iocb_dma = 0; 2050 ha->ms_iocb_dma = 0;
2080 ha->iodesc_pd = NULL;
2081 ha->iodesc_pd_dma = 0;
2082 ha->init_cb = NULL; 2051 ha->init_cb = NULL;
2083 ha->init_cb_dma = 0; 2052 ha->init_cb_dma = 0;
2084 2053
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 @@
1/*
2 * QLogic Fibre Channel HBA Driver
3 * Copyright (c) 2003-2005 QLogic Corporation
4 *
5 * See LICENSE.qla2xxx for copyright and licensing details.
6 */
7#include "qla_def.h"
8
9/**
10 * IO descriptor handle definitions.
11 *
12 * Signature form:
13 *
14 * |31------28|27-------------------12|11-------0|
15 * | Type | Rolling Signature | Index |
16 * |----------|-----------------------|----------|
17 *
18 **/
19
20#define HDL_TYPE_SCSI 0
21#define HDL_TYPE_ASYNC_IOCB 0x0A
22
23#define HDL_INDEX_BITS 12
24#define HDL_ITER_BITS 16
25#define HDL_TYPE_BITS 4
26
27#define HDL_INDEX_MASK ((1UL << HDL_INDEX_BITS) - 1)
28#define HDL_ITER_MASK ((1UL << HDL_ITER_BITS) - 1)
29#define HDL_TYPE_MASK ((1UL << HDL_TYPE_BITS) - 1)
30
31#define HDL_INDEX_SHIFT 0
32#define HDL_ITER_SHIFT (HDL_INDEX_SHIFT + HDL_INDEX_BITS)
33#define HDL_TYPE_SHIFT (HDL_ITER_SHIFT + HDL_ITER_BITS)
34
35/* Local Prototypes. */
36static inline uint32_t qla2x00_to_handle(uint16_t, uint16_t, uint16_t);
37static inline uint16_t qla2x00_handle_to_idx(uint32_t);
38static inline uint32_t qla2x00_iodesc_to_handle(struct io_descriptor *);
39static inline struct io_descriptor *qla2x00_handle_to_iodesc(scsi_qla_host_t *,
40 uint32_t);
41
42static inline struct io_descriptor *qla2x00_alloc_iodesc(scsi_qla_host_t *);
43static inline void qla2x00_free_iodesc(struct io_descriptor *);
44static inline void qla2x00_init_io_descriptors(scsi_qla_host_t *);
45
46static void qla2x00_iodesc_timeout(unsigned long);
47static inline void qla2x00_add_iodesc_timer(struct io_descriptor *);
48static inline void qla2x00_remove_iodesc_timer(struct io_descriptor *);
49
50static inline void qla2x00_update_login_fcport(scsi_qla_host_t *,
51 struct mbx_entry *, fc_port_t *);
52
53static int qla2x00_send_abort_iocb(scsi_qla_host_t *, struct io_descriptor *,
54 uint32_t, int);
55static int qla2x00_send_abort_iocb_cb(scsi_qla_host_t *, struct io_descriptor *,
56 struct mbx_entry *);
57
58static int qla2x00_send_adisc_iocb(scsi_qla_host_t *, struct io_descriptor *,
59 int);
60static int qla2x00_send_adisc_iocb_cb(scsi_qla_host_t *, struct io_descriptor *,
61 struct mbx_entry *);
62
63static int qla2x00_send_logout_iocb(scsi_qla_host_t *, struct io_descriptor *,
64 int);
65static int qla2x00_send_logout_iocb_cb(scsi_qla_host_t *,
66 struct io_descriptor *, struct mbx_entry *);
67
68static int qla2x00_send_login_iocb(scsi_qla_host_t *, struct io_descriptor *,
69 port_id_t *, int);
70static int qla2x00_send_login_iocb_cb(scsi_qla_host_t *, struct io_descriptor *,
71 struct mbx_entry *);
72
73/**
74 * Mailbox IOCB callback array.
75 **/
76static int (*iocb_function_cb_list[LAST_IOCB_CB])
77 (scsi_qla_host_t *, struct io_descriptor *, struct mbx_entry *) = {
78
79 qla2x00_send_abort_iocb_cb,
80 qla2x00_send_adisc_iocb_cb,
81 qla2x00_send_logout_iocb_cb,
82 qla2x00_send_login_iocb_cb,
83};
84
85
86/**
87 * Generic IO descriptor handle routines.
88 **/
89
90/**
91 * qla2x00_to_handle() - Create a descriptor handle.
92 * @type: descriptor type
93 * @iter: descriptor rolling signature
94 * @idx: index to the descriptor array
95 *
96 * Returns a composite handle based in the @type, @iter, and @idx.
97 */
98static inline uint32_t
99qla2x00_to_handle(uint16_t type, uint16_t iter, uint16_t idx)
100{
101 return ((uint32_t)(((uint32_t)type << HDL_TYPE_SHIFT) |
102 ((uint32_t)iter << HDL_ITER_SHIFT) |
103 ((uint32_t)idx << HDL_INDEX_SHIFT)));
104}
105
106/**
107 * qla2x00_handle_to_idx() - Retrive the index for a given handle.
108 * @handle: descriptor handle
109 *
110 * Returns the index specified by the @handle.
111 */
112static inline uint16_t
113qla2x00_handle_to_idx(uint32_t handle)
114{
115 return ((uint16_t)(((handle) >> HDL_INDEX_SHIFT) & HDL_INDEX_MASK));
116}
117
118/**
119 * qla2x00_iodesc_to_handle() - Convert an IO descriptor to a unique handle.
120 * @iodesc: io descriptor
121 *
122 * Returns a unique handle for @iodesc.
123 */
124static inline uint32_t
125qla2x00_iodesc_to_handle(struct io_descriptor *iodesc)
126{
127 uint32_t handle;
128
129 handle = qla2x00_to_handle(HDL_TYPE_ASYNC_IOCB,
130 ++iodesc->ha->iodesc_signature, iodesc->idx);
131 iodesc->signature = handle;
132
133 return (handle);
134}
135
136/**
137 * qla2x00_handle_to_iodesc() - Retrieve an IO descriptor given a unique handle.
138 * @ha: HA context
139 * @handle: handle to io descriptor
140 *
141 * Returns a pointer to the io descriptor, or NULL, if the io descriptor does
142 * not exist or the io descriptors signature does not @handle.
143 */
144static inline struct io_descriptor *
145qla2x00_handle_to_iodesc(scsi_qla_host_t *ha, uint32_t handle)
146{
147 uint16_t idx;
148 struct io_descriptor *iodesc;
149
150 idx = qla2x00_handle_to_idx(handle);
151 iodesc = &ha->io_descriptors[idx];
152 if (iodesc)
153 if (iodesc->signature != handle)
154 iodesc = NULL;
155
156 return (iodesc);
157}
158
159
160/**
161 * IO descriptor allocation routines.
162 **/
163
164/**
165 * qla2x00_alloc_iodesc() - Allocate an IO descriptor from the pool.
166 * @ha: HA context
167 *
168 * Returns a pointer to the allocated io descriptor, or NULL, if none available.
169 */
170static inline struct io_descriptor *
171qla2x00_alloc_iodesc(scsi_qla_host_t *ha)
172{
173 uint16_t iter;
174 struct io_descriptor *iodesc;
175
176 iodesc = NULL;
177 for (iter = 0; iter < MAX_IO_DESCRIPTORS; iter++) {
178 if (ha->io_descriptors[iter].used)
179 continue;
180
181 iodesc = &ha->io_descriptors[iter];
182 iodesc->used = 1;
183 iodesc->idx = iter;
184 init_timer(&iodesc->timer);
185 iodesc->ha = ha;
186 iodesc->signature = qla2x00_iodesc_to_handle(iodesc);
187 break;
188 }
189
190 return (iodesc);
191}
192
193/**
194 * qla2x00_free_iodesc() - Free an IO descriptor.
195 * @iodesc: io descriptor
196 *
197 * NOTE: The io descriptors timer *must* be stopped before it can be free'd.
198 */
199static inline void
200qla2x00_free_iodesc(struct io_descriptor *iodesc)
201{
202 iodesc->used = 0;
203 iodesc->signature = 0;
204}
205
206/**
207 * qla2x00_remove_iodesc_timer() - Remove an active timer from an IO descriptor.
208 * @iodesc: io descriptor
209 */
210static inline void
211qla2x00_remove_iodesc_timer(struct io_descriptor *iodesc)
212{
213 if (iodesc->timer.function != NULL) {
214 del_timer_sync(&iodesc->timer);
215 iodesc->timer.data = (unsigned long) NULL;
216 iodesc->timer.function = NULL;
217 }
218}
219
220/**
221 * qla2x00_init_io_descriptors() - Initialize the pool of IO descriptors.
222 * @ha: HA context
223 */
224static inline void
225qla2x00_init_io_descriptors(scsi_qla_host_t *ha)
226{
227 uint16_t iter;
228
229 for (iter = 0; iter < MAX_IO_DESCRIPTORS; iter++) {
230 if (!ha->io_descriptors[iter].used)
231 continue;
232
233 qla2x00_remove_iodesc_timer(&ha->io_descriptors[iter]);
234 qla2x00_free_iodesc(&ha->io_descriptors[iter]);
235 }
236}
237
238
239/**
240 * IO descriptor timer routines.
241 **/
242
243/**
244 * qla2x00_iodesc_timeout() - Timeout IO descriptor handler.
245 * @data: io descriptor
246 */
247static void
248qla2x00_iodesc_timeout(unsigned long data)
249{
250 struct io_descriptor *iodesc;
251
252 iodesc = (struct io_descriptor *) data;
253
254 DEBUG14(printk("scsi(%ld): IO descriptor timeout, index=%x "
255 "signature=%08x, scheduling ISP abort.\n", iodesc->ha->host_no,
256 iodesc->idx, iodesc->signature));
257
258 qla2x00_free_iodesc(iodesc);
259
260 qla_printk(KERN_WARNING, iodesc->ha,
261 "IO descriptor timeout. Scheduling ISP abort.\n");
262 set_bit(ISP_ABORT_NEEDED, &iodesc->ha->dpc_flags);
263}
264
265/**
266 * qla2x00_add_iodesc_timer() - Add and start a timer for an IO descriptor.
267 * @iodesc: io descriptor
268 *
269 * NOTE:
270 * The firmware shall timeout an outstanding mailbox IOCB in 2 * R_A_TOV (in
271 * tenths of a second) after it hits the wire. But, if there are any request
272 * resource contraints (i.e. during heavy I/O), exchanges can be held off for
273 * at most R_A_TOV. Therefore, the driver will wait 4 * R_A_TOV before
274 * scheduling a recovery (big hammer).
275 */
276static inline void
277qla2x00_add_iodesc_timer(struct io_descriptor *iodesc)
278{
279 unsigned long timeout;
280
281 timeout = (iodesc->ha->r_a_tov * 4) / 10;
282 init_timer(&iodesc->timer);
283 iodesc->timer.data = (unsigned long) iodesc;
284 iodesc->timer.expires = jiffies + (timeout * HZ);
285 iodesc->timer.function =
286 (void (*) (unsigned long)) qla2x00_iodesc_timeout;
287 add_timer(&iodesc->timer);
288}
289
290/**
291 * IO descriptor support routines.
292 **/
293
294/**
295 * qla2x00_update_login_fcport() - Update fcport data after login processing.
296 * @ha: HA context
297 * @mbxstat: Mailbox command status IOCB
298 * @fcport: port to update
299 */
300static inline void
301qla2x00_update_login_fcport(scsi_qla_host_t *ha, struct mbx_entry *mbxstat,
302 fc_port_t *fcport)
303{
304 if (le16_to_cpu(mbxstat->mb1) & BIT_0) {
305 fcport->port_type = FCT_INITIATOR;
306 } else {
307 fcport->port_type = FCT_TARGET;
308 if (le16_to_cpu(mbxstat->mb1) & BIT_1) {
309 fcport->flags |= FCF_TAPE_PRESENT;
310 }
311 }
312 fcport->login_retry = 0;
313 fcport->port_login_retry_count = ha->port_down_retry_count *
314 PORT_RETRY_TIME;
315 atomic_set(&fcport->port_down_timer, ha->port_down_retry_count *
316 PORT_RETRY_TIME);
317 fcport->flags |= FCF_FABRIC_DEVICE;
318 fcport->flags &= ~FCF_FAILOVER_NEEDED;
319 fcport->iodesc_idx_sent = IODESC_INVALID_INDEX;
320 atomic_set(&fcport->state, FCS_ONLINE);
321}
322
323
324/**
325 * Mailbox IOCB commands.
326 **/
327
328/**
329 * qla2x00_get_mbx_iocb_entry() - Retrieve an IOCB from the request queue.
330 * @ha: HA context
331 * @handle: handle to io descriptor
332 *
333 * Returns a pointer to the reqest entry, or NULL, if none were available.
334 */
335static inline struct mbx_entry *
336qla2x00_get_mbx_iocb_entry(scsi_qla_host_t *ha, uint32_t handle)
337{
338 uint16_t cnt;
339 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
340 struct mbx_entry *mbxentry;
341
342 mbxentry = NULL;
343
344 if (ha->req_q_cnt < 3) {
345 cnt = qla2x00_debounce_register(ISP_REQ_Q_OUT(ha, reg));
346 if (ha->req_ring_index < cnt)
347 ha->req_q_cnt = cnt - ha->req_ring_index;
348 else
349 ha->req_q_cnt = ha->request_q_length -
350 (ha->req_ring_index - cnt);
351 }
352 if (ha->req_q_cnt >= 3) {
353 mbxentry = (struct mbx_entry *)ha->request_ring_ptr;
354
355 memset(mbxentry, 0, sizeof(struct mbx_entry));
356 mbxentry->entry_type = MBX_IOCB_TYPE;
357 mbxentry->entry_count = 1;
358 mbxentry->sys_define1 = SOURCE_ASYNC_IOCB;
359 mbxentry->handle = handle;
360 }
361 return (mbxentry);
362}
363
364/**
365 * qla2x00_send_abort_iocb() - Issue an abort IOCB to the firmware.
366 * @ha: HA context
367 * @iodesc: io descriptor
368 * @handle_to_abort: firmware handle to abort
369 * @ha_locked: is function called with the hardware lock
370 *
371 * Returns QLA_SUCCESS if the IOCB was issued.
372 */
373static int
374qla2x00_send_abort_iocb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
375 uint32_t handle_to_abort, int ha_locked)
376{
377 unsigned long flags = 0;
378 struct mbx_entry *mbxentry;
379
380 /* Send marker if required. */
381 if (qla2x00_issue_marker(ha, ha_locked) != QLA_SUCCESS)
382 return (QLA_FUNCTION_FAILED);
383
384 if (!ha_locked)
385 spin_lock_irqsave(&ha->hardware_lock, flags);
386
387 /* Build abort mailbox IOCB. */
388 mbxentry = qla2x00_get_mbx_iocb_entry(ha, iodesc->signature);
389 if (mbxentry == NULL) {
390 if (!ha_locked)
391 spin_unlock_irqrestore(&ha->hardware_lock, flags);
392
393 return (QLA_FUNCTION_FAILED);
394 }
395 mbxentry->mb0 = __constant_cpu_to_le16(MBC_ABORT_COMMAND);
396 mbxentry->mb1 = mbxentry->loop_id.extended =
397 cpu_to_le16(iodesc->remote_fcport->loop_id);
398 mbxentry->mb2 = LSW(handle_to_abort);
399 mbxentry->mb3 = MSW(handle_to_abort);
400 wmb();
401
402 qla2x00_add_iodesc_timer(iodesc);
403
404 /* Issue command to ISP. */
405 qla2x00_isp_cmd(ha);
406
407 if (!ha_locked)
408 spin_unlock_irqrestore(&ha->hardware_lock, flags);
409
410 DEBUG14(printk("scsi(%ld): Sending Abort IOCB (%08x) to [%x], aborting "
411 "%08x.\n", ha->host_no, iodesc->signature,
412 iodesc->remote_fcport->loop_id, handle_to_abort));
413
414 return (QLA_SUCCESS);
415}
416
417/**
418 * qla2x00_send_abort_iocb_cb() - Abort IOCB callback.
419 * @ha: HA context
420 * @iodesc: io descriptor
421 * @mbxstat: mailbox status IOCB
422 *
423 * Returns QLA_SUCCESS if @iodesc can be freed by the caller, else, @iodesc
424 * will be used for a retry.
425 */
426static int
427qla2x00_send_abort_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
428 struct mbx_entry *mbxstat)
429{
430 DEBUG14(printk("scsi(%ld): Abort IOCB -- sent to [%x/%02x%02x%02x], "
431 "status=%x mb0=%x.\n", ha->host_no, iodesc->remote_fcport->loop_id,
432 iodesc->d_id.b.domain, iodesc->d_id.b.area, iodesc->d_id.b.al_pa,
433 le16_to_cpu(mbxstat->status), le16_to_cpu(mbxstat->mb0)));
434
435 return (QLA_SUCCESS);
436}
437
438
439/**
440 * qla2x00_send_adisc_iocb() - Issue a Get Port Database IOCB to the firmware.
441 * @ha: HA context
442 * @iodesc: io descriptor
443 * @ha_locked: is function called with the hardware lock
444 *
445 * Returns QLA_SUCCESS if the IOCB was issued.
446 */
447static int
448qla2x00_send_adisc_iocb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
449 int ha_locked)
450{
451 unsigned long flags = 0;
452 struct mbx_entry *mbxentry;
453
454 /* Send marker if required. */
455 if (qla2x00_issue_marker(ha, ha_locked) != QLA_SUCCESS)
456 return (QLA_FUNCTION_FAILED);
457
458 if (!ha_locked)
459 spin_lock_irqsave(&ha->hardware_lock, flags);
460
461 /* Build Get Port Database IOCB. */
462 mbxentry = qla2x00_get_mbx_iocb_entry(ha, iodesc->signature);
463 if (mbxentry == NULL) {
464 if (!ha_locked)
465 spin_unlock_irqrestore(&ha->hardware_lock, flags);
466
467 return (QLA_FUNCTION_FAILED);
468 }
469 mbxentry->mb0 = __constant_cpu_to_le16(MBC_GET_PORT_DATABASE);
470 mbxentry->mb1 = mbxentry->loop_id.extended =
471 cpu_to_le16(iodesc->remote_fcport->loop_id);
472 mbxentry->mb2 = cpu_to_le16(MSW(LSD(ha->iodesc_pd_dma)));
473 mbxentry->mb3 = cpu_to_le16(LSW(LSD(ha->iodesc_pd_dma)));
474 mbxentry->mb6 = cpu_to_le16(MSW(MSD(ha->iodesc_pd_dma)));
475 mbxentry->mb7 = cpu_to_le16(LSW(MSD(ha->iodesc_pd_dma)));
476 mbxentry->mb10 = __constant_cpu_to_le16(BIT_0);
477 wmb();
478
479 qla2x00_add_iodesc_timer(iodesc);
480
481 /* Issue command to ISP. */
482 qla2x00_isp_cmd(ha);
483
484 if (!ha_locked)
485 spin_unlock_irqrestore(&ha->hardware_lock, flags);
486
487 DEBUG14(printk("scsi(%ld): Sending Adisc IOCB (%08x) to [%x].\n",
488 ha->host_no, iodesc->signature, iodesc->remote_fcport->loop_id));
489
490 return (QLA_SUCCESS);
491}
492
493/**
494 * qla2x00_send_adisc_iocb_cb() - Get Port Database IOCB callback.
495 * @ha: HA context
496 * @iodesc: io descriptor
497 * @mbxstat: mailbox status IOCB
498 *
499 * Returns QLA_SUCCESS if @iodesc can be freed by the caller, else, @iodesc
500 * will be used for a retry.
501 */
502static int
503qla2x00_send_adisc_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
504 struct mbx_entry *mbxstat)
505{
506 fc_port_t *remote_fcport;
507
508 remote_fcport = iodesc->remote_fcport;
509
510 /* Ensure the port IDs are consistent. */
511 if (remote_fcport->d_id.b24 != iodesc->d_id.b24) {
512 DEBUG14(printk("scsi(%ld): Adisc IOCB -- ignoring, remote port "
513 "id changed from [%02x%02x%02x] to [%02x%02x%02x].\n",
514 ha->host_no, remote_fcport->d_id.b.domain,
515 remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa,
516 iodesc->d_id.b.domain, iodesc->d_id.b.area,
517 iodesc->d_id.b.al_pa));
518
519 return (QLA_SUCCESS);
520 }
521
522 /* Only process the last command. */
523 if (remote_fcport->iodesc_idx_sent != iodesc->idx) {
524 DEBUG14(printk("scsi(%ld): Adisc IOCB -- ignoring, sent to "
525 "[%02x%02x%02x], expected %x, received %x.\n", ha->host_no,
526 iodesc->d_id.b.domain, iodesc->d_id.b.area,
527 iodesc->d_id.b.al_pa, remote_fcport->iodesc_idx_sent,
528 iodesc->idx));
529
530 return (QLA_SUCCESS);
531 }
532
533 if (le16_to_cpu(mbxstat->status) == CS_COMPLETE) {
534 DEBUG14(printk("scsi(%ld): Adisc IOCB -- marking "
535 "[%x/%02x%02x%02x] online.\n", ha->host_no,
536 remote_fcport->loop_id, remote_fcport->d_id.b.domain,
537 remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa));
538
539 atomic_set(&remote_fcport->state, FCS_ONLINE);
540 } else {
541 DEBUG14(printk("scsi(%ld): Adisc IOCB -- marking "
542 "[%x/%02x%02x%02x] lost, status=%x mb0=%x.\n", ha->host_no,
543 remote_fcport->loop_id, remote_fcport->d_id.b.domain,
544 remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa,
545 le16_to_cpu(mbxstat->status), le16_to_cpu(mbxstat->mb0)));
546
547 if (atomic_read(&remote_fcport->state) != FCS_DEVICE_DEAD)
548 atomic_set(&remote_fcport->state, FCS_DEVICE_LOST);
549 }
550 remote_fcport->iodesc_idx_sent = IODESC_INVALID_INDEX;
551
552 return (QLA_SUCCESS);
553}
554
555
556/**
557 * qla2x00_send_logout_iocb() - Issue a fabric port logout IOCB to the firmware.
558 * @ha: HA context
559 * @iodesc: io descriptor
560 * @ha_locked: is function called with the hardware lock
561 *
562 * Returns QLA_SUCCESS if the IOCB was issued.
563 */
564static int
565qla2x00_send_logout_iocb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
566 int ha_locked)
567{
568 unsigned long flags = 0;
569 struct mbx_entry *mbxentry;
570
571 /* Send marker if required. */
572 if (qla2x00_issue_marker(ha, ha_locked) != QLA_SUCCESS)
573 return (QLA_FUNCTION_FAILED);
574
575 if (!ha_locked)
576 spin_lock_irqsave(&ha->hardware_lock, flags);
577
578 /* Build fabric port logout mailbox IOCB. */
579 mbxentry = qla2x00_get_mbx_iocb_entry(ha, iodesc->signature);
580 if (mbxentry == NULL) {
581 if (!ha_locked)
582 spin_unlock_irqrestore(&ha->hardware_lock, flags);
583
584 return (QLA_FUNCTION_FAILED);
585 }
586 mbxentry->mb0 = __constant_cpu_to_le16(MBC_LOGOUT_FABRIC_PORT);
587 mbxentry->mb1 = mbxentry->loop_id.extended =
588 cpu_to_le16(iodesc->remote_fcport->loop_id);
589 wmb();
590
591 qla2x00_add_iodesc_timer(iodesc);
592
593 /* Issue command to ISP. */
594 qla2x00_isp_cmd(ha);
595
596 if (!ha_locked)
597 spin_unlock_irqrestore(&ha->hardware_lock, flags);
598
599 DEBUG14(printk("scsi(%ld): Sending Logout IOCB (%08x) to [%x].\n",
600 ha->host_no, iodesc->signature, iodesc->remote_fcport->loop_id));
601
602 return (QLA_SUCCESS);
603}
604
605/**
606 * qla2x00_send_logout_iocb_cb() - Fabric port logout IOCB callback.
607 * @ha: HA context
608 * @iodesc: io descriptor
609 * @mbxstat: mailbox status IOCB
610 *
611 * Returns QLA_SUCCESS if @iodesc can be freed by the caller, else, @iodesc
612 * will be used for a retry.
613 */
614static int
615qla2x00_send_logout_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
616 struct mbx_entry *mbxstat)
617{
618 DEBUG14(printk("scsi(%ld): Logout IOCB -- sent to [%x/%02x%02x%02x], "
619 "status=%x mb0=%x mb1=%x.\n", ha->host_no,
620 iodesc->remote_fcport->loop_id,
621 iodesc->remote_fcport->d_id.b.domain,
622 iodesc->remote_fcport->d_id.b.area,
623 iodesc->remote_fcport->d_id.b.al_pa, le16_to_cpu(mbxstat->status),
624 le16_to_cpu(mbxstat->mb0), le16_to_cpu(mbxstat->mb1)));
625
626 return (QLA_SUCCESS);
627}
628
629
630/**
631 * qla2x00_send_login_iocb() - Issue a fabric port login IOCB to the firmware.
632 * @ha: HA context
633 * @iodesc: io descriptor
634 * @d_id: port id for device
635 * @ha_locked: is function called with the hardware lock
636 *
637 * Returns QLA_SUCCESS if the IOCB was issued.
638 */
639static int
640qla2x00_send_login_iocb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
641 port_id_t *d_id, int ha_locked)
642{
643 unsigned long flags = 0;
644 struct mbx_entry *mbxentry;
645
646 /* Send marker if required. */
647 if (qla2x00_issue_marker(ha, ha_locked) != QLA_SUCCESS)
648 return (QLA_FUNCTION_FAILED);
649
650 if (!ha_locked)
651 spin_lock_irqsave(&ha->hardware_lock, flags);
652
653 /* Build fabric port login mailbox IOCB. */
654 mbxentry = qla2x00_get_mbx_iocb_entry(ha, iodesc->signature);
655 if (mbxentry == NULL) {
656 if (!ha_locked)
657 spin_unlock_irqrestore(&ha->hardware_lock, flags);
658
659 return (QLA_FUNCTION_FAILED);
660 }
661 mbxentry->mb0 = __constant_cpu_to_le16(MBC_LOGIN_FABRIC_PORT);
662 mbxentry->mb1 = mbxentry->loop_id.extended =
663 cpu_to_le16(iodesc->remote_fcport->loop_id);
664 mbxentry->mb2 = cpu_to_le16(d_id->b.domain);
665 mbxentry->mb3 = cpu_to_le16(d_id->b.area << 8 | d_id->b.al_pa);
666 mbxentry->mb10 = __constant_cpu_to_le16(BIT_0);
667 wmb();
668
669 qla2x00_add_iodesc_timer(iodesc);
670
671 /* Issue command to ISP. */
672 qla2x00_isp_cmd(ha);
673
674 if (!ha_locked)
675 spin_unlock_irqrestore(&ha->hardware_lock, flags);
676
677 DEBUG14(printk("scsi(%ld): Sending Login IOCB (%08x) to "
678 "[%x/%02x%02x%02x].\n", ha->host_no, iodesc->signature,
679 iodesc->remote_fcport->loop_id, d_id->b.domain, d_id->b.area,
680 d_id->b.al_pa));
681
682 return (QLA_SUCCESS);
683}
684
685/**
686 * qla2x00_send_login_iocb_cb() - Fabric port logout IOCB callback.
687 * @ha: HA context
688 * @iodesc: io descriptor
689 * @mbxstat: mailbox status IOCB
690 *
691 * Returns QLA_SUCCESS if @iodesc can be freed by the caller, else, @iodesc
692 * will be used for a retry.
693 */
694static int
695qla2x00_send_login_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
696 struct mbx_entry *mbxstat)
697{
698 int rval;
699 fc_port_t *fcport, *remote_fcport, *exist_fcport;
700 struct io_descriptor *abort_iodesc, *login_iodesc;
701 uint16_t status, mb[8];
702 uint16_t reuse;
703 uint16_t remote_loopid;
704 port_id_t remote_did, inuse_did;
705
706 remote_fcport = iodesc->remote_fcport;
707
708 /* Only process the last command. */
709 if (remote_fcport->iodesc_idx_sent != iodesc->idx) {
710 DEBUG14(printk("scsi(%ld): Login IOCB -- ignoring, sent to "
711 "[%02x%02x%02x], expected %x, received %x.\n",
712 ha->host_no, iodesc->d_id.b.domain, iodesc->d_id.b.area,
713 iodesc->d_id.b.al_pa, remote_fcport->iodesc_idx_sent,
714 iodesc->idx));
715
716 /* Free RSCN fcport resources. */
717 if (remote_fcport->port_type == FCT_RSCN) {
718 DEBUG14(printk("scsi(%ld): Login IOCB -- Freeing RSCN "
719 "fcport %p [%x/%02x%02x%02x] given ignored Login "
720 "IOCB.\n", ha->host_no, remote_fcport,
721 remote_fcport->loop_id,
722 remote_fcport->d_id.b.domain,
723 remote_fcport->d_id.b.area,
724 remote_fcport->d_id.b.al_pa));
725
726 list_del(&remote_fcport->list);
727 kfree(remote_fcport);
728 }
729 return (QLA_SUCCESS);
730 }
731
732 status = le16_to_cpu(mbxstat->status);
733 mb[0] = le16_to_cpu(mbxstat->mb0);
734 mb[1] = le16_to_cpu(mbxstat->mb1);
735 mb[2] = le16_to_cpu(mbxstat->mb2);
736 mb[6] = le16_to_cpu(mbxstat->mb6);
737 mb[7] = le16_to_cpu(mbxstat->mb7);
738
739 /* Good status? */
740 if ((status == CS_COMPLETE || status == CS_COMPLETE_CHKCOND) &&
741 mb[0] == MBS_COMMAND_COMPLETE) {
742
743 DEBUG14(printk("scsi(%ld): Login IOCB -- status=%x mb1=%x pn="
744 "%02x%02x%02x%02x%02x%02x%02x%02x.\n", ha->host_no, status,
745 mb[1], mbxstat->port_name[0], mbxstat->port_name[1],
746 mbxstat->port_name[2], mbxstat->port_name[3],
747 mbxstat->port_name[4], mbxstat->port_name[5],
748 mbxstat->port_name[6], mbxstat->port_name[7]));
749
750 memcpy(remote_fcport->node_name, mbxstat->node_name, WWN_SIZE);
751 memcpy(remote_fcport->port_name, mbxstat->port_name, WWN_SIZE);
752
753 /* Is the device already in our fcports list? */
754 if (remote_fcport->port_type != FCT_RSCN) {
755 DEBUG14(printk("scsi(%ld): Login IOCB -- marking "
756 "[%x/%02x%02x%02x] online.\n", ha->host_no,
757 remote_fcport->loop_id,
758 remote_fcport->d_id.b.domain,
759 remote_fcport->d_id.b.area,
760 remote_fcport->d_id.b.al_pa));
761
762 qla2x00_update_login_fcport(ha, mbxstat, remote_fcport);
763
764 return (QLA_SUCCESS);
765 }
766
767 /* Does the RSCN portname already exist in our fcports list? */
768 exist_fcport = NULL;
769 list_for_each_entry(fcport, &ha->fcports, list) {
770 if (memcmp(remote_fcport->port_name, fcport->port_name,
771 WWN_SIZE) == 0) {
772 exist_fcport = fcport;
773 break;
774 }
775 }
776 if (exist_fcport != NULL) {
777 DEBUG14(printk("scsi(%ld): Login IOCB -- found RSCN "
778 "fcport in fcports list [%p].\n", ha->host_no,
779 exist_fcport));
780
781 /* Abort any ADISC that could have been sent. */
782 if (exist_fcport->iodesc_idx_sent != iodesc->idx &&
783 exist_fcport->iodesc_idx_sent <
784 MAX_IO_DESCRIPTORS &&
785 ha->io_descriptors[exist_fcport->iodesc_idx_sent].
786 cb_idx == ADISC_PORT_IOCB_CB) {
787
788 abort_iodesc = qla2x00_alloc_iodesc(ha);
789 if (abort_iodesc) {
790 DEBUG14(printk("scsi(%ld): Login IOCB "
791 "-- issuing abort to outstanding "
792 "Adisc [%x/%02x%02x%02x].\n",
793 ha->host_no, remote_fcport->loop_id,
794 exist_fcport->d_id.b.domain,
795 exist_fcport->d_id.b.area,
796 exist_fcport->d_id.b.al_pa));
797
798 abort_iodesc->cb_idx = ABORT_IOCB_CB;
799 abort_iodesc->d_id.b24 =
800 exist_fcport->d_id.b24;
801 abort_iodesc->remote_fcport =
802 exist_fcport;
803 exist_fcport->iodesc_idx_sent =
804 abort_iodesc->idx;
805 qla2x00_send_abort_iocb(ha,
806 abort_iodesc, ha->io_descriptors[
807 exist_fcport->iodesc_idx_sent].
808 signature, 1);
809 } else {
810 DEBUG14(printk("scsi(%ld): Login IOCB "
811 "-- unable to abort outstanding "
812 "Adisc [%x/%02x%02x%02x].\n",
813 ha->host_no, remote_fcport->loop_id,
814 exist_fcport->d_id.b.domain,
815 exist_fcport->d_id.b.area,
816 exist_fcport->d_id.b.al_pa));
817 }
818 }
819
820 /*
821 * If the existing fcport is waiting to send an ADISC
822 * or LOGIN, then reuse remote fcport (RSCN) to
823 * continue waiting.
824 */
825 reuse = 0;
826 remote_loopid = remote_fcport->loop_id;
827 remote_did.b24 = remote_fcport->d_id.b24;
828 if (exist_fcport->iodesc_idx_sent ==
829 IODESC_ADISC_NEEDED ||
830 exist_fcport->iodesc_idx_sent ==
831 IODESC_LOGIN_NEEDED) {
832 DEBUG14(printk("scsi(%ld): Login IOCB -- "
833 "existing fcport [%x/%02x%02x%02x] "
834 "waiting for IO descriptor, reuse RSCN "
835 "fcport.\n", ha->host_no,
836 exist_fcport->loop_id,
837 exist_fcport->d_id.b.domain,
838 exist_fcport->d_id.b.area,
839 exist_fcport->d_id.b.al_pa));
840
841 reuse++;
842 remote_fcport->iodesc_idx_sent =
843 exist_fcport->iodesc_idx_sent;
844 exist_fcport->iodesc_idx_sent =
845 IODESC_INVALID_INDEX;
846 remote_fcport->loop_id = exist_fcport->loop_id;
847 remote_fcport->d_id.b24 =
848 exist_fcport->d_id.b24;
849 }
850
851 /* Logout the old loopid. */
852 if (!reuse &&
853 exist_fcport->loop_id != remote_fcport->loop_id &&
854 exist_fcport->loop_id != FC_NO_LOOP_ID) {
855 login_iodesc = qla2x00_alloc_iodesc(ha);
856 if (login_iodesc) {
857 DEBUG14(printk("scsi(%ld): Login IOCB "
858 "-- issuing logout to free old "
859 "loop id [%x/%02x%02x%02x].\n",
860 ha->host_no, exist_fcport->loop_id,
861 exist_fcport->d_id.b.domain,
862 exist_fcport->d_id.b.area,
863 exist_fcport->d_id.b.al_pa));
864
865 login_iodesc->cb_idx =
866 LOGOUT_PORT_IOCB_CB;
867 login_iodesc->d_id.b24 =
868 exist_fcport->d_id.b24;
869 login_iodesc->remote_fcport =
870 exist_fcport;
871 exist_fcport->iodesc_idx_sent =
872 login_iodesc->idx;
873 qla2x00_send_logout_iocb(ha,
874 login_iodesc, 1);
875 } else {
876 /* Ran out of IO descriptiors. */
877 DEBUG14(printk("scsi(%ld): Login IOCB "
878 "-- unable to logout to free old "
879 "loop id [%x/%02x%02x%02x].\n",
880 ha->host_no, exist_fcport->loop_id,
881 exist_fcport->d_id.b.domain,
882 exist_fcport->d_id.b.area,
883 exist_fcport->d_id.b.al_pa));
884
885 exist_fcport->iodesc_idx_sent =
886 IODESC_INVALID_INDEX;
887 }
888
889 }
890
891 /* Update existing fcport with remote fcport info. */
892 DEBUG14(printk("scsi(%ld): Login IOCB -- marking "
893 "existing fcport [%x/%02x%02x%02x] online.\n",
894 ha->host_no, remote_loopid, remote_did.b.domain,
895 remote_did.b.area, remote_did.b.al_pa));
896
897 memcpy(exist_fcport->node_name,
898 remote_fcport->node_name, WWN_SIZE);
899 exist_fcport->loop_id = remote_loopid;
900 exist_fcport->d_id.b24 = remote_did.b24;
901 qla2x00_update_login_fcport(ha, mbxstat, exist_fcport);
902
903 /* Finally, free the remote (RSCN) fcport. */
904 if (!reuse) {
905 DEBUG14(printk("scsi(%ld): Login IOCB -- "
906 "Freeing RSCN fcport %p "
907 "[%x/%02x%02x%02x].\n", ha->host_no,
908 remote_fcport, remote_fcport->loop_id,
909 remote_fcport->d_id.b.domain,
910 remote_fcport->d_id.b.area,
911 remote_fcport->d_id.b.al_pa));
912
913 list_del(&remote_fcport->list);
914 kfree(remote_fcport);
915 }
916
917 return (QLA_SUCCESS);
918 }
919
920 /*
921 * A new device has been added, move the RSCN fcport to our
922 * fcports list.
923 */
924 DEBUG14(printk("scsi(%ld): Login IOCB -- adding RSCN fcport "
925 "[%x/%02x%02x%02x] to fcports list.\n", ha->host_no,
926 remote_fcport->loop_id, remote_fcport->d_id.b.domain,
927 remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa));
928
929 list_del(&remote_fcport->list);
930 remote_fcport->flags = (FCF_RLC_SUPPORT | FCF_RESCAN_NEEDED);
931 qla2x00_update_login_fcport(ha, mbxstat, remote_fcport);
932 list_add_tail(&remote_fcport->list, &ha->fcports);
933 set_bit(FCPORT_RESCAN_NEEDED, &ha->dpc_flags);
934 } else {
935 /* Handle login failure. */
936 if (remote_fcport->login_retry != 0) {
937 if (mb[0] == MBS_LOOP_ID_USED) {
938 inuse_did.b.domain = LSB(mb[1]);
939 inuse_did.b.area = MSB(mb[2]);
940 inuse_did.b.al_pa = LSB(mb[2]);
941
942 DEBUG14(printk("scsi(%ld): Login IOCB -- loop "
943 "id [%x] used by port id [%02x%02x%02x].\n",
944 ha->host_no, remote_fcport->loop_id,
945 inuse_did.b.domain, inuse_did.b.area,
946 inuse_did.b.al_pa));
947
948 if (remote_fcport->d_id.b24 ==
949 INVALID_PORT_ID) {
950 /*
951 * Invalid port id means we are trying
952 * to login to a remote port with just
953 * a loop id without knowing about the
954 * port id. Copy the port id and try
955 * again.
956 */
957 remote_fcport->d_id.b24 = inuse_did.b24;
958 iodesc->d_id.b24 = inuse_did.b24;
959 } else {
960 remote_fcport->loop_id++;
961 rval = qla2x00_find_new_loop_id(ha,
962 remote_fcport);
963 if (rval == QLA_FUNCTION_FAILED) {
964 /* No more loop ids. */
965 return (QLA_SUCCESS);
966 }
967 }
968 } else if (mb[0] == MBS_PORT_ID_USED) {
969 /*
970 * Device has another loop ID. The firmware
971 * group recommends the driver perform an
972 * implicit login with the specified ID.
973 */
974 DEBUG14(printk("scsi(%ld): Login IOCB -- port "
975 "id [%02x%02x%02x] already assigned to "
976 "loop id [%x].\n", ha->host_no,
977 iodesc->d_id.b.domain, iodesc->d_id.b.area,
978 iodesc->d_id.b.al_pa, mb[1]));
979
980 remote_fcport->loop_id = mb[1];
981
982 } else {
983 /* Unable to perform login, try again. */
984 DEBUG14(printk("scsi(%ld): Login IOCB -- "
985 "failed login [%x/%02x%02x%02x], status=%x "
986 "mb0=%x mb1=%x mb2=%x mb6=%x mb7=%x.\n",
987 ha->host_no, remote_fcport->loop_id,
988 iodesc->d_id.b.domain, iodesc->d_id.b.area,
989 iodesc->d_id.b.al_pa, status, mb[0], mb[1],
990 mb[2], mb[6], mb[7]));
991 }
992
993 /* Reissue Login with the same IO descriptor. */
994 iodesc->signature =
995 qla2x00_iodesc_to_handle(iodesc);
996 iodesc->cb_idx = LOGIN_PORT_IOCB_CB;
997 iodesc->d_id.b24 = remote_fcport->d_id.b24;
998 remote_fcport->iodesc_idx_sent = iodesc->idx;
999 remote_fcport->login_retry--;
1000
1001 DEBUG14(printk("scsi(%ld): Login IOCB -- retrying "
1002 "login to [%x/%02x%02x%02x] (%d).\n", ha->host_no,
1003 remote_fcport->loop_id,
1004 remote_fcport->d_id.b.domain,
1005 remote_fcport->d_id.b.area,
1006 remote_fcport->d_id.b.al_pa,
1007 remote_fcport->login_retry));
1008
1009 qla2x00_send_login_iocb(ha, iodesc,
1010 &remote_fcport->d_id, 1);
1011
1012 return (QLA_FUNCTION_FAILED);
1013 } else {
1014 /* No more logins, mark device dead. */
1015 DEBUG14(printk("scsi(%ld): Login IOCB -- failed "
1016 "login [%x/%02x%02x%02x] after retries, status=%x "
1017 "mb0=%x mb1=%x mb2=%x mb6=%x mb7=%x.\n",
1018 ha->host_no, remote_fcport->loop_id,
1019 iodesc->d_id.b.domain, iodesc->d_id.b.area,
1020 iodesc->d_id.b.al_pa, status, mb[0], mb[1],
1021 mb[2], mb[6], mb[7]));
1022
1023 atomic_set(&remote_fcport->state, FCS_DEVICE_DEAD);
1024 if (remote_fcport->port_type == FCT_RSCN) {
1025 DEBUG14(printk("scsi(%ld): Login IOCB -- "
1026 "Freeing dead RSCN fcport %p "
1027 "[%x/%02x%02x%02x].\n", ha->host_no,
1028 remote_fcport, remote_fcport->loop_id,
1029 remote_fcport->d_id.b.domain,
1030 remote_fcport->d_id.b.area,
1031 remote_fcport->d_id.b.al_pa));
1032
1033 list_del(&remote_fcport->list);
1034 kfree(remote_fcport);
1035 }
1036 }
1037 }
1038
1039 return (QLA_SUCCESS);
1040}
1041
1042
1043/**
1044 * IO descriptor processing routines.
1045 **/
1046
1047/**
1048 * qla2x00_alloc_rscn_fcport() - Allocate an RSCN type fcport.
1049 * @ha: HA context
1050 * @flags: allocation flags
1051 *
1052 * Returns a pointer to the allocated RSCN fcport, or NULL, if none available.
1053 */
1054fc_port_t *
1055qla2x00_alloc_rscn_fcport(scsi_qla_host_t *ha, gfp_t flags)
1056{
1057 fc_port_t *fcport;
1058
1059 fcport = qla2x00_alloc_fcport(ha, flags);
1060 if (fcport == NULL)
1061 return (fcport);
1062
1063 /* Setup RSCN fcport structure. */
1064 fcport->port_type = FCT_RSCN;
1065
1066 return (fcport);
1067}
1068
1069/**
1070 * qla2x00_handle_port_rscn() - Handle port RSCN.
1071 * @ha: HA context
1072 * @rscn_entry: RSCN entry
1073 * @fcport: fcport entry to updated
1074 *
1075 * Returns QLA_SUCCESS if the port RSCN was handled.
1076 */
1077int
1078qla2x00_handle_port_rscn(scsi_qla_host_t *ha, uint32_t rscn_entry,
1079 fc_port_t *known_fcport, int ha_locked)
1080{
1081 int rval;
1082 port_id_t rscn_pid;
1083 fc_port_t *fcport, *remote_fcport, *rscn_fcport;
1084 struct io_descriptor *iodesc;
1085
1086 remote_fcport = NULL;
1087 rscn_fcport = NULL;
1088
1089 /* Prepare port id based on incoming entries. */
1090 if (known_fcport) {
1091 rscn_pid.b24 = known_fcport->d_id.b24;
1092 remote_fcport = known_fcport;
1093
1094 DEBUG14(printk("scsi(%ld): Handle RSCN -- process RSCN for "
1095 "fcport [%02x%02x%02x].\n", ha->host_no,
1096 remote_fcport->d_id.b.domain, remote_fcport->d_id.b.area,
1097 remote_fcport->d_id.b.al_pa));
1098 } else {
1099 rscn_pid.b.domain = LSB(MSW(rscn_entry));
1100 rscn_pid.b.area = MSB(LSW(rscn_entry));
1101 rscn_pid.b.al_pa = LSB(LSW(rscn_entry));
1102
1103 DEBUG14(printk("scsi(%ld): Handle RSCN -- process RSCN for "
1104 "port id [%02x%02x%02x].\n", ha->host_no,
1105 rscn_pid.b.domain, rscn_pid.b.area, rscn_pid.b.al_pa));
1106
1107 /*
1108 * Search fcport lists for a known entry at the specified port
1109 * ID.
1110 */
1111 list_for_each_entry(fcport, &ha->fcports, list) {
1112 if (rscn_pid.b24 == fcport->d_id.b24) {
1113 remote_fcport = fcport;
1114 break;
1115 }
1116 }
1117 list_for_each_entry(fcport, &ha->rscn_fcports, list) {
1118 if (rscn_pid.b24 == fcport->d_id.b24) {
1119 rscn_fcport = fcport;
1120 break;
1121 }
1122 }
1123 if (remote_fcport == NULL)
1124 remote_fcport = rscn_fcport;
1125 }
1126
1127 /*
1128 * If the port is already in our fcport list and online, send an ADISC
1129 * to see if it's still alive. Issue login if a new fcport or the known
1130 * fcport is currently offline.
1131 */
1132 if (remote_fcport) {
1133 /*
1134 * No need to send request if the remote fcport is currently
1135 * waiting for an available io descriptor.
1136 */
1137 if (known_fcport == NULL &&
1138 (remote_fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED ||
1139 remote_fcport->iodesc_idx_sent == IODESC_LOGIN_NEEDED)) {
1140 /*
1141 * If previous waiting io descriptor is an ADISC, then
1142 * the new RSCN may come from a new remote fcport being
1143 * plugged into the same location.
1144 */
1145 if (remote_fcport->port_type == FCT_RSCN) {
1146 remote_fcport->iodesc_idx_sent =
1147 IODESC_LOGIN_NEEDED;
1148 } else if (remote_fcport->iodesc_idx_sent ==
1149 IODESC_ADISC_NEEDED) {
1150 fc_port_t *new_fcport;
1151
1152 remote_fcport->iodesc_idx_sent =
1153 IODESC_INVALID_INDEX;
1154
1155 /* Create new fcport for later login. */
1156 new_fcport = qla2x00_alloc_rscn_fcport(ha,
1157 ha_locked ? GFP_ATOMIC: GFP_KERNEL);
1158 if (new_fcport) {
1159 DEBUG14(printk("scsi(%ld): Handle RSCN "
1160 "-- creating RSCN fcport %p for "
1161 "future login.\n", ha->host_no,
1162 new_fcport));
1163
1164 new_fcport->d_id.b24 =
1165 remote_fcport->d_id.b24;
1166 new_fcport->iodesc_idx_sent =
1167 IODESC_LOGIN_NEEDED;
1168
1169 list_add_tail(&new_fcport->list,
1170 &ha->rscn_fcports);
1171 set_bit(IODESC_PROCESS_NEEDED,
1172 &ha->dpc_flags);
1173 } else {
1174 DEBUG14(printk("scsi(%ld): Handle RSCN "
1175 "-- unable to allocate RSCN fcport "
1176 "for future login.\n",
1177 ha->host_no));
1178 }
1179 }
1180 return (QLA_SUCCESS);
1181 }
1182
1183 /* Send ADISC if the fcport is online */
1184 if (atomic_read(&remote_fcport->state) == FCS_ONLINE ||
1185 remote_fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED) {
1186
1187 atomic_set(&remote_fcport->state, FCS_DEVICE_LOST);
1188
1189 iodesc = qla2x00_alloc_iodesc(ha);
1190 if (iodesc == NULL) {
1191 /* Mark fcport for later adisc processing */
1192 DEBUG14(printk("scsi(%ld): Handle RSCN -- not "
1193 "enough IO descriptors for Adisc, flag "
1194 "for later processing.\n", ha->host_no));
1195
1196 remote_fcport->iodesc_idx_sent =
1197 IODESC_ADISC_NEEDED;
1198 set_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags);
1199
1200 return (QLA_SUCCESS);
1201 }
1202
1203 iodesc->cb_idx = ADISC_PORT_IOCB_CB;
1204 iodesc->d_id.b24 = rscn_pid.b24;
1205 iodesc->remote_fcport = remote_fcport;
1206 remote_fcport->iodesc_idx_sent = iodesc->idx;
1207 qla2x00_send_adisc_iocb(ha, iodesc, ha_locked);
1208
1209 return (QLA_SUCCESS);
1210 } else if (remote_fcport->iodesc_idx_sent <
1211 MAX_IO_DESCRIPTORS &&
1212 ha->io_descriptors[remote_fcport->iodesc_idx_sent].cb_idx ==
1213 ADISC_PORT_IOCB_CB) {
1214 /*
1215 * Receiving another RSCN while an ADISC is pending,
1216 * abort the IOCB. Use the same descriptor for the
1217 * abort.
1218 */
1219 uint32_t handle_to_abort;
1220
1221 iodesc = &ha->io_descriptors[
1222 remote_fcport->iodesc_idx_sent];
1223 qla2x00_remove_iodesc_timer(iodesc);
1224 handle_to_abort = iodesc->signature;
1225 iodesc->signature = qla2x00_iodesc_to_handle(iodesc);
1226 iodesc->cb_idx = ABORT_IOCB_CB;
1227 iodesc->d_id.b24 = remote_fcport->d_id.b24;
1228 iodesc->remote_fcport = remote_fcport;
1229 remote_fcport->iodesc_idx_sent = iodesc->idx;
1230
1231 DEBUG14(printk("scsi(%ld): Handle RSCN -- issuing "
1232 "abort to outstanding Adisc [%x/%02x%02x%02x].\n",
1233 ha->host_no, remote_fcport->loop_id,
1234 iodesc->d_id.b.domain, iodesc->d_id.b.area,
1235 iodesc->d_id.b.al_pa));
1236
1237 qla2x00_send_abort_iocb(ha, iodesc, handle_to_abort,
1238 ha_locked);
1239 }
1240 }
1241
1242 /* We need to login to the remote port, find it. */
1243 if (known_fcport) {
1244 remote_fcport = known_fcport;
1245 } else if (rscn_fcport && rscn_fcport->d_id.b24 != INVALID_PORT_ID &&
1246 rscn_fcport->iodesc_idx_sent < MAX_IO_DESCRIPTORS &&
1247 ha->io_descriptors[rscn_fcport->iodesc_idx_sent].cb_idx ==
1248 LOGIN_PORT_IOCB_CB) {
1249 /*
1250 * Ignore duplicate RSCN on fcport which has already
1251 * initiated a login IOCB.
1252 */
1253 DEBUG14(printk("scsi(%ld): Handle RSCN -- ignoring, login "
1254 "already sent to [%02x%02x%02x].\n", ha->host_no,
1255 rscn_fcport->d_id.b.domain, rscn_fcport->d_id.b.area,
1256 rscn_fcport->d_id.b.al_pa));
1257
1258 return (QLA_SUCCESS);
1259 } else if (rscn_fcport && rscn_fcport->d_id.b24 != INVALID_PORT_ID &&
1260 rscn_fcport != remote_fcport) {
1261 /* Reuse same rscn fcport. */
1262 DEBUG14(printk("scsi(%ld): Handle RSCN -- reusing RSCN fcport "
1263 "[%02x%02x%02x].\n", ha->host_no,
1264 rscn_fcport->d_id.b.domain, rscn_fcport->d_id.b.area,
1265 rscn_fcport->d_id.b.al_pa));
1266
1267 remote_fcport = rscn_fcport;
1268 } else {
1269 /* Create new fcport for later login. */
1270 remote_fcport = qla2x00_alloc_rscn_fcport(ha,
1271 ha_locked ? GFP_ATOMIC: GFP_KERNEL);
1272 list_add_tail(&remote_fcport->list, &ha->rscn_fcports);
1273 }
1274 if (remote_fcport == NULL)
1275 return (QLA_SUCCESS);
1276
1277 /* Prepare fcport for login. */
1278 atomic_set(&remote_fcport->state, FCS_DEVICE_LOST);
1279 remote_fcport->login_retry = 3; /* ha->login_retry_count; */
1280 remote_fcport->d_id.b24 = rscn_pid.b24;
1281
1282 iodesc = qla2x00_alloc_iodesc(ha);
1283 if (iodesc == NULL) {
1284 /* Mark fcport for later adisc processing. */
1285 DEBUG14(printk("scsi(%ld): Handle RSCN -- not enough IO "
1286 "descriptors for Login, flag for later processing.\n",
1287 ha->host_no));
1288
1289 remote_fcport->iodesc_idx_sent = IODESC_LOGIN_NEEDED;
1290 set_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags);
1291
1292 return (QLA_SUCCESS);
1293 }
1294
1295 if (known_fcport == NULL || rscn_pid.b24 != INVALID_PORT_ID) {
1296 remote_fcport->loop_id = ha->min_external_loopid;
1297
1298 rval = qla2x00_find_new_loop_id(ha, remote_fcport);
1299 if (rval == QLA_FUNCTION_FAILED) {
1300 /* No more loop ids, failed. */
1301 DEBUG14(printk("scsi(%ld): Handle RSCN -- no available "
1302 "loop id to perform Login, failed.\n",
1303 ha->host_no));
1304
1305 return (rval);
1306 }
1307 }
1308
1309 iodesc->cb_idx = LOGIN_PORT_IOCB_CB;
1310 iodesc->d_id.b24 = rscn_pid.b24;
1311 iodesc->remote_fcport = remote_fcport;
1312 remote_fcport->iodesc_idx_sent = iodesc->idx;
1313
1314 DEBUG14(printk("scsi(%ld): Handle RSCN -- attempting login to "
1315 "[%x/%02x%02x%02x].\n", ha->host_no, remote_fcport->loop_id,
1316 iodesc->d_id.b.domain, iodesc->d_id.b.area, iodesc->d_id.b.al_pa));
1317
1318 qla2x00_send_login_iocb(ha, iodesc, &rscn_pid, ha_locked);
1319
1320 return (QLA_SUCCESS);
1321}
1322
1323/**
1324 * qla2x00_process_iodesc() - Complete IO descriptor processing.
1325 * @ha: HA context
1326 * @mbxstat: Mailbox IOCB status
1327 */
1328void
1329qla2x00_process_iodesc(scsi_qla_host_t *ha, struct mbx_entry *mbxstat)
1330{
1331 int rval;
1332 uint32_t signature;
1333 fc_port_t *fcport;
1334 struct io_descriptor *iodesc;
1335
1336 signature = mbxstat->handle;
1337
1338 DEBUG14(printk("scsi(%ld): Process IODesc -- processing %08x.\n",
1339 ha->host_no, signature));
1340
1341 /* Retrieve proper IO descriptor. */
1342 iodesc = qla2x00_handle_to_iodesc(ha, signature);
1343 if (iodesc == NULL) {
1344 DEBUG14(printk("scsi(%ld): Process IODesc -- ignoring, "
1345 "incorrect signature %08x.\n", ha->host_no, signature));
1346
1347 return;
1348 }
1349
1350 /* Stop IO descriptor timer. */
1351 qla2x00_remove_iodesc_timer(iodesc);
1352
1353 /* Verify signature match. */
1354 if (iodesc->signature != signature) {
1355 DEBUG14(printk("scsi(%ld): Process IODesc -- ignoring, "
1356 "signature mismatch, sent %08x, received %08x.\n",
1357 ha->host_no, iodesc->signature, signature));
1358
1359 return;
1360 }
1361
1362 /* Go with IOCB callback. */
1363 rval = iocb_function_cb_list[iodesc->cb_idx](ha, iodesc, mbxstat);
1364 if (rval != QLA_SUCCESS) {
1365 /* IO descriptor reused by callback. */
1366 return;
1367 }
1368
1369 qla2x00_free_iodesc(iodesc);
1370
1371 if (test_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags)) {
1372 /* Scan our fcports list for any RSCN requests. */
1373 list_for_each_entry(fcport, &ha->fcports, list) {
1374 if (fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED ||
1375 fcport->iodesc_idx_sent == IODESC_LOGIN_NEEDED) {
1376 qla2x00_handle_port_rscn(ha, 0, fcport, 1);
1377 return;
1378 }
1379 }
1380
1381 /* Scan our RSCN fcports list for any RSCN requests. */
1382 list_for_each_entry(fcport, &ha->rscn_fcports, list) {
1383 if (fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED ||
1384 fcport->iodesc_idx_sent == IODESC_LOGIN_NEEDED) {
1385 qla2x00_handle_port_rscn(ha, 0, fcport, 1);
1386 return;
1387 }
1388 }
1389 }
1390 clear_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags);
1391}
1392
1393/**
1394 * qla2x00_cancel_io_descriptors() - Cancel all outstanding io descriptors.
1395 * @ha: HA context
1396 *
1397 * This routine will also delete any RSCN entries related to the outstanding
1398 * IO descriptors.
1399 */
1400void
1401qla2x00_cancel_io_descriptors(scsi_qla_host_t *ha)
1402{
1403 fc_port_t *fcport, *fcptemp;
1404
1405 clear_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags);
1406
1407 /* Abort all IO descriptors. */
1408 qla2x00_init_io_descriptors(ha);
1409
1410 /* Reset all pending IO descriptors in fcports list. */
1411 list_for_each_entry(fcport, &ha->fcports, list) {
1412 fcport->iodesc_idx_sent = IODESC_INVALID_INDEX;
1413 }
1414
1415 /* Reset all pending IO descriptors in rscn fcports list. */
1416 list_for_each_entry_safe(fcport, fcptemp, &ha->rscn_fcports, list) {
1417 DEBUG14(printk("scsi(%ld): Cancel IOs -- Freeing RSCN fcport "
1418 "%p [%x/%02x%02x%02x].\n", ha->host_no, fcport,
1419 fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area,
1420 fcport->d_id.b.al_pa));
1421
1422 list_del(&fcport->list);
1423 kfree(fcport);
1424 }
1425}