aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/bfa
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-02 22:01:32 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-02 22:01:32 -0400
commit3151367f8778a1789d6f6e6f6c642681b6cd6d64 (patch)
tree1869d5429a25abd994ae94079808b8db060ec6f3 /drivers/scsi/bfa
parent16642a2e7be23bbda013fc32d8f6c68982eab603 (diff)
parentfe709ed827d370e6b0c0a9f9456da1c22bdcd118 (diff)
Merge tag 'scsi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull first round of SCSI updates from James Bottomley: "This is a large set of updates, mostly for drivers (qla2xxx [including support for new 83xx based card], qla4xxx, mpt2sas, bfa, zfcp, hpsa, be2iscsi, isci, lpfc, ipr, ibmvfc, ibmvscsi, megaraid_sas). There's also a rework for tape adding virtually unlimited numbers of tape drives plus a set of dif fixes for sd and a fix for a live lock on hot remove of SCSI devices. This round includes a signed tag pull of isci-for-3.6 Signed-off-by: James Bottomley <JBottomley@Parallels.com>" Fix up trivial conflict in drivers/scsi/qla2xxx/qla_nx.c due to new PCI helper function use in a function that was removed by this pull. * tag 'scsi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (198 commits) [SCSI] st: remove st_mutex [SCSI] sd: Ensure we correctly disable devices with unknown protection type [SCSI] hpsa: gen8plus Smart Array IDs [SCSI] qla4xxx: Update driver version to 5.03.00-k1 [SCSI] qla4xxx: Disable generating pause frames for ISP83XX [SCSI] qla4xxx: Fix double clearing of risc_intr for ISP83XX [SCSI] qla4xxx: IDC implementation for Loopback [SCSI] qla4xxx: update copyrights in LICENSE.qla4xxx [SCSI] qla4xxx: Fix panic while rmmod [SCSI] qla4xxx: Fail probe_adapter if IRQ allocation fails [SCSI] qla4xxx: Prevent MSI/MSI-X falling back to INTx for ISP82XX [SCSI] qla4xxx: Update idc reg in case of PCI AER [SCSI] qla4xxx: Fix double IDC locking in qla4_8xxx_error_recovery [SCSI] qla4xxx: Clear interrupt while unloading driver for ISP83XX [SCSI] qla4xxx: Print correct IDC version [SCSI] qla4xxx: Added new mbox cmd to pass driver version to FW [SCSI] scsi_dh_alua: Enable STPG for unavailable ports [SCSI] scsi_remove_target: fix softlockup regression on hot remove [SCSI] ibmvscsi: Fix host config length field overflow [SCSI] ibmvscsi: Remove backend abstraction ...
Diffstat (limited to 'drivers/scsi/bfa')
-rw-r--r--drivers/scsi/bfa/bfa_core.c21
-rw-r--r--drivers/scsi/bfa/bfa_cs.h4
-rw-r--r--drivers/scsi/bfa/bfa_defs_fcs.h18
-rw-r--r--drivers/scsi/bfa/bfa_fc.h10
-rw-r--r--drivers/scsi/bfa/bfa_fcbuild.c21
-rw-r--r--drivers/scsi/bfa/bfa_fcbuild.h2
-rw-r--r--drivers/scsi/bfa/bfa_fcpim.c12
-rw-r--r--drivers/scsi/bfa/bfa_fcs.c182
-rw-r--r--drivers/scsi/bfa/bfa_fcs.h66
-rw-r--r--drivers/scsi/bfa/bfa_fcs_fcpim.c129
-rw-r--r--drivers/scsi/bfa/bfa_fcs_lport.c632
-rw-r--r--drivers/scsi/bfa/bfa_fcs_rport.c466
-rw-r--r--drivers/scsi/bfa/bfa_ioc.c24
-rw-r--r--drivers/scsi/bfa/bfa_ioc.h2
-rw-r--r--drivers/scsi/bfa/bfa_modules.h1
-rw-r--r--drivers/scsi/bfa/bfa_svc.c95
-rw-r--r--drivers/scsi/bfa/bfa_svc.h23
-rw-r--r--drivers/scsi/bfa/bfad.c236
-rw-r--r--drivers/scsi/bfa/bfad_attr.c46
-rw-r--r--drivers/scsi/bfa/bfad_bsg.c39
-rw-r--r--drivers/scsi/bfa/bfad_bsg.h2
-rw-r--r--drivers/scsi/bfa/bfad_drv.h5
-rw-r--r--drivers/scsi/bfa/bfad_im.c9
23 files changed, 1736 insertions, 309 deletions
diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c
index 456e5762977..b7c326f7a6d 100644
--- a/drivers/scsi/bfa/bfa_core.c
+++ b/drivers/scsi/bfa/bfa_core.c
@@ -775,7 +775,8 @@ bfa_intx(struct bfa_s *bfa)
775 if (!intr) 775 if (!intr)
776 return BFA_TRUE; 776 return BFA_TRUE;
777 777
778 bfa_msix_lpu_err(bfa, intr); 778 if (bfa->intr_enabled)
779 bfa_msix_lpu_err(bfa, intr);
779 780
780 return BFA_TRUE; 781 return BFA_TRUE;
781} 782}
@@ -803,11 +804,17 @@ bfa_isr_enable(struct bfa_s *bfa)
803 writel(~umsk, bfa->iocfc.bfa_regs.intr_mask); 804 writel(~umsk, bfa->iocfc.bfa_regs.intr_mask);
804 bfa->iocfc.intr_mask = ~umsk; 805 bfa->iocfc.intr_mask = ~umsk;
805 bfa_isr_mode_set(bfa, bfa->msix.nvecs != 0); 806 bfa_isr_mode_set(bfa, bfa->msix.nvecs != 0);
807
808 /*
809 * Set the flag indicating successful enabling of interrupts
810 */
811 bfa->intr_enabled = BFA_TRUE;
806} 812}
807 813
808void 814void
809bfa_isr_disable(struct bfa_s *bfa) 815bfa_isr_disable(struct bfa_s *bfa)
810{ 816{
817 bfa->intr_enabled = BFA_FALSE;
811 bfa_isr_mode_set(bfa, BFA_FALSE); 818 bfa_isr_mode_set(bfa, BFA_FALSE);
812 writel(-1L, bfa->iocfc.bfa_regs.intr_mask); 819 writel(-1L, bfa->iocfc.bfa_regs.intr_mask);
813 bfa_msix_uninstall(bfa); 820 bfa_msix_uninstall(bfa);
@@ -1022,7 +1029,7 @@ bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg)
1022{ 1029{
1023 u8 *dm_kva = NULL; 1030 u8 *dm_kva = NULL;
1024 u64 dm_pa = 0; 1031 u64 dm_pa = 0;
1025 int i, per_reqq_sz, per_rspq_sz, dbgsz; 1032 int i, per_reqq_sz, per_rspq_sz;
1026 struct bfa_iocfc_s *iocfc = &bfa->iocfc; 1033 struct bfa_iocfc_s *iocfc = &bfa->iocfc;
1027 struct bfa_mem_dma_s *ioc_dma = BFA_MEM_IOC_DMA(bfa); 1034 struct bfa_mem_dma_s *ioc_dma = BFA_MEM_IOC_DMA(bfa);
1028 struct bfa_mem_dma_s *iocfc_dma = BFA_MEM_IOCFC_DMA(bfa); 1035 struct bfa_mem_dma_s *iocfc_dma = BFA_MEM_IOCFC_DMA(bfa);
@@ -1083,11 +1090,8 @@ bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg)
1083 BFA_CACHELINE_SZ); 1090 BFA_CACHELINE_SZ);
1084 1091
1085 /* Claim IOCFC kva memory */ 1092 /* Claim IOCFC kva memory */
1086 dbgsz = (bfa_auto_recover) ? BFA_DBG_FWTRC_LEN : 0; 1093 bfa_ioc_debug_memclaim(&bfa->ioc, bfa_mem_kva_curp(iocfc));
1087 if (dbgsz > 0) { 1094 bfa_mem_kva_curp(iocfc) += BFA_DBG_FWTRC_LEN;
1088 bfa_ioc_debug_memclaim(&bfa->ioc, bfa_mem_kva_curp(iocfc));
1089 bfa_mem_kva_curp(iocfc) += dbgsz;
1090 }
1091} 1095}
1092 1096
1093/* 1097/*
@@ -1429,8 +1433,7 @@ bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
1429 bfa_mem_dma_setup(meminfo, iocfc_dma, dm_len); 1433 bfa_mem_dma_setup(meminfo, iocfc_dma, dm_len);
1430 1434
1431 /* kva memory setup for IOCFC */ 1435 /* kva memory setup for IOCFC */
1432 bfa_mem_kva_setup(meminfo, iocfc_kva, 1436 bfa_mem_kva_setup(meminfo, iocfc_kva, BFA_DBG_FWTRC_LEN);
1433 ((bfa_auto_recover) ? BFA_DBG_FWTRC_LEN : 0));
1434} 1437}
1435 1438
1436/* 1439/*
diff --git a/drivers/scsi/bfa/bfa_cs.h b/drivers/scsi/bfa/bfa_cs.h
index 12bfeed268e..91a8aa394db 100644
--- a/drivers/scsi/bfa/bfa_cs.h
+++ b/drivers/scsi/bfa/bfa_cs.h
@@ -168,7 +168,7 @@ __bfa_trc32(struct bfa_trc_mod_s *trcm, int fileno, int line, u32 data)
168/* 168/*
169 * bfa_q_deq - dequeue an element from head of the queue 169 * bfa_q_deq - dequeue an element from head of the queue
170 */ 170 */
171#define bfa_q_deq(_q, _qe) { \ 171#define bfa_q_deq(_q, _qe) do { \
172 if (!list_empty(_q)) { \ 172 if (!list_empty(_q)) { \
173 (*((struct list_head **) (_qe))) = bfa_q_next(_q); \ 173 (*((struct list_head **) (_qe))) = bfa_q_next(_q); \
174 bfa_q_prev(bfa_q_next(*((struct list_head **) _qe))) = \ 174 bfa_q_prev(bfa_q_next(*((struct list_head **) _qe))) = \
@@ -177,7 +177,7 @@ __bfa_trc32(struct bfa_trc_mod_s *trcm, int fileno, int line, u32 data)
177 } else { \ 177 } else { \
178 *((struct list_head **) (_qe)) = (struct list_head *) NULL;\ 178 *((struct list_head **) (_qe)) = (struct list_head *) NULL;\
179 } \ 179 } \
180} 180} while (0)
181 181
182/* 182/*
183 * bfa_q_deq_tail - dequeue an element from tail of the queue 183 * bfa_q_deq_tail - dequeue an element from tail of the queue
diff --git a/drivers/scsi/bfa/bfa_defs_fcs.h b/drivers/scsi/bfa/bfa_defs_fcs.h
index 3bbc583f65c..06f0a163ca3 100644
--- a/drivers/scsi/bfa/bfa_defs_fcs.h
+++ b/drivers/scsi/bfa/bfa_defs_fcs.h
@@ -93,6 +93,7 @@ struct bfa_lport_cfg_s {
93 wwn_t pwwn; /* port wwn */ 93 wwn_t pwwn; /* port wwn */
94 wwn_t nwwn; /* node wwn */ 94 wwn_t nwwn; /* node wwn */
95 struct bfa_lport_symname_s sym_name; /* vm port symbolic name */ 95 struct bfa_lport_symname_s sym_name; /* vm port symbolic name */
96 struct bfa_lport_symname_s node_sym_name; /* Node symbolic name */
96 enum bfa_lport_role roles; /* FCS port roles */ 97 enum bfa_lport_role roles; /* FCS port roles */
97 u32 rsvd; 98 u32 rsvd;
98 bfa_boolean_t preboot_vp; /* vport created from PBC */ 99 bfa_boolean_t preboot_vp; /* vport created from PBC */
@@ -192,6 +193,18 @@ struct bfa_lport_stats_s {
192 u32 ns_gidft_unknown_rsp; 193 u32 ns_gidft_unknown_rsp;
193 u32 ns_gidft_alloc_wait; 194 u32 ns_gidft_alloc_wait;
194 195
196 u32 ns_rnnid_sent;
197 u32 ns_rnnid_accepts;
198 u32 ns_rnnid_rsp_err;
199 u32 ns_rnnid_rejects;
200 u32 ns_rnnid_alloc_wait;
201
202 u32 ns_rsnn_nn_sent;
203 u32 ns_rsnn_nn_accepts;
204 u32 ns_rsnn_nn_rsp_err;
205 u32 ns_rsnn_nn_rejects;
206 u32 ns_rsnn_nn_alloc_wait;
207
195 /* 208 /*
196 * Mgmt Server stats 209 * Mgmt Server stats
197 */ 210 */
@@ -410,6 +423,11 @@ struct bfa_rport_remote_link_stats_s {
410 u32 icc; /* Invalid CRC Count */ 423 u32 icc; /* Invalid CRC Count */
411}; 424};
412 425
426struct bfa_rport_qualifier_s {
427 wwn_t pwwn; /* Port WWN */
428 u32 pid; /* port ID */
429 u32 rsvd;
430};
413 431
414#define BFA_MAX_IO_INDEX 7 432#define BFA_MAX_IO_INDEX 7
415#define BFA_NO_IO_INDEX 9 433#define BFA_NO_IO_INDEX 9
diff --git a/drivers/scsi/bfa/bfa_fc.h b/drivers/scsi/bfa/bfa_fc.h
index 8d0b88f67a3..e0beb4d7e26 100644
--- a/drivers/scsi/bfa/bfa_fc.h
+++ b/drivers/scsi/bfa/bfa_fc.h
@@ -1279,6 +1279,7 @@ enum {
1279 GS_GSPN_ID = 0x0118, /* Get symbolic PN on ID */ 1279 GS_GSPN_ID = 0x0118, /* Get symbolic PN on ID */
1280 GS_RFT_ID = 0x0217, /* Register fc4type on ID */ 1280 GS_RFT_ID = 0x0217, /* Register fc4type on ID */
1281 GS_RSPN_ID = 0x0218, /* Register symbolic PN on ID */ 1281 GS_RSPN_ID = 0x0218, /* Register symbolic PN on ID */
1282 GS_RSNN_NN = 0x0239, /* Register symbolic NN on NN */
1282 GS_RPN_ID = 0x0212, /* Register port name */ 1283 GS_RPN_ID = 0x0212, /* Register port name */
1283 GS_RNN_ID = 0x0213, /* Register node name */ 1284 GS_RNN_ID = 0x0213, /* Register node name */
1284 GS_RCS_ID = 0x0214, /* Register class of service */ 1285 GS_RCS_ID = 0x0214, /* Register class of service */
@@ -1357,6 +1358,15 @@ struct fcgs_rspnid_req_s {
1357}; 1358};
1358 1359
1359/* 1360/*
1361 * RSNN_NN
1362 */
1363struct fcgs_rsnn_nn_req_s {
1364 wwn_t node_name; /* Node name */
1365 u8 snn_len; /* symbolic node name length */
1366 u8 snn[256]; /* symbolic node name */
1367};
1368
1369/*
1360 * RPN_ID 1370 * RPN_ID
1361 */ 1371 */
1362struct fcgs_rpnid_req_s { 1372struct fcgs_rpnid_req_s {
diff --git a/drivers/scsi/bfa/bfa_fcbuild.c b/drivers/scsi/bfa/bfa_fcbuild.c
index 17b59b8b564..273cee90b3b 100644
--- a/drivers/scsi/bfa/bfa_fcbuild.c
+++ b/drivers/scsi/bfa/bfa_fcbuild.c
@@ -1252,6 +1252,27 @@ fc_rspnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
1252} 1252}
1253 1253
1254u16 1254u16
1255fc_rsnn_nn_build(struct fchs_s *fchs, void *pyld, u32 s_id,
1256 wwn_t node_name, u8 *name)
1257{
1258 struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
1259 struct fcgs_rsnn_nn_req_s *rsnn_nn =
1260 (struct fcgs_rsnn_nn_req_s *) (cthdr + 1);
1261 u32 d_id = bfa_hton3b(FC_NAME_SERVER);
1262
1263 fc_gs_fchdr_build(fchs, d_id, s_id, 0);
1264 fc_gs_cthdr_build(cthdr, s_id, GS_RSNN_NN);
1265
1266 memset(rsnn_nn, 0, sizeof(struct fcgs_rsnn_nn_req_s));
1267
1268 rsnn_nn->node_name = node_name;
1269 rsnn_nn->snn_len = (u8) strlen((char *)name);
1270 strncpy((char *)rsnn_nn->snn, (char *)name, rsnn_nn->snn_len);
1271
1272 return sizeof(struct fcgs_rsnn_nn_req_s) + sizeof(struct ct_hdr_s);
1273}
1274
1275u16
1255fc_gid_ft_build(struct fchs_s *fchs, void *pyld, u32 s_id, u8 fc4_type) 1276fc_gid_ft_build(struct fchs_s *fchs, void *pyld, u32 s_id, u8 fc4_type)
1256{ 1277{
1257 1278
diff --git a/drivers/scsi/bfa/bfa_fcbuild.h b/drivers/scsi/bfa/bfa_fcbuild.h
index 42cd9d4da69..03c753d1e54 100644
--- a/drivers/scsi/bfa/bfa_fcbuild.h
+++ b/drivers/scsi/bfa/bfa_fcbuild.h
@@ -166,6 +166,8 @@ enum fc_parse_status fc_rrq_rsp_parse(struct fchs_s *buf, int len);
166 166
167u16 fc_rspnid_build(struct fchs_s *fchs, void *pld, u32 s_id, 167u16 fc_rspnid_build(struct fchs_s *fchs, void *pld, u32 s_id,
168 u16 ox_id, u8 *name); 168 u16 ox_id, u8 *name);
169u16 fc_rsnn_nn_build(struct fchs_s *fchs, void *pld, u32 s_id,
170 wwn_t node_name, u8 *name);
169 171
170u16 fc_rftid_build(struct fchs_s *fchs, void *pld, u32 s_id, 172u16 fc_rftid_build(struct fchs_s *fchs, void *pld, u32 s_id,
171 u16 ox_id, enum bfa_lport_role role); 173 u16 ox_id, enum bfa_lport_role role);
diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c
index f0f80e282e3..1633963c66c 100644
--- a/drivers/scsi/bfa/bfa_fcpim.c
+++ b/drivers/scsi/bfa/bfa_fcpim.c
@@ -1466,7 +1466,13 @@ bfa_status_t
1466bfa_itnim_get_ioprofile(struct bfa_itnim_s *itnim, 1466bfa_itnim_get_ioprofile(struct bfa_itnim_s *itnim,
1467 struct bfa_itnim_ioprofile_s *ioprofile) 1467 struct bfa_itnim_ioprofile_s *ioprofile)
1468{ 1468{
1469 struct bfa_fcpim_s *fcpim = BFA_FCPIM(itnim->bfa); 1469 struct bfa_fcpim_s *fcpim;
1470
1471 if (!itnim)
1472 return BFA_STATUS_NO_FCPIM_NEXUS;
1473
1474 fcpim = BFA_FCPIM(itnim->bfa);
1475
1470 if (!fcpim->io_profile) 1476 if (!fcpim->io_profile)
1471 return BFA_STATUS_IOPROFILE_OFF; 1477 return BFA_STATUS_IOPROFILE_OFF;
1472 1478
@@ -1484,6 +1490,10 @@ void
1484bfa_itnim_clear_stats(struct bfa_itnim_s *itnim) 1490bfa_itnim_clear_stats(struct bfa_itnim_s *itnim)
1485{ 1491{
1486 int j; 1492 int j;
1493
1494 if (!itnim)
1495 return;
1496
1487 memset(&itnim->stats, 0, sizeof(itnim->stats)); 1497 memset(&itnim->stats, 0, sizeof(itnim->stats));
1488 memset(&itnim->ioprofile, 0, sizeof(itnim->ioprofile)); 1498 memset(&itnim->ioprofile, 0, sizeof(itnim->ioprofile));
1489 for (j = 0; j < BFA_IOBUCKET_MAX; j++) 1499 for (j = 0; j < BFA_IOBUCKET_MAX; j++)
diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c
index eaac57e1dde..fd3e84d32bd 100644
--- a/drivers/scsi/bfa/bfa_fcs.c
+++ b/drivers/scsi/bfa/bfa_fcs.c
@@ -76,6 +76,7 @@ bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad,
76 fcs->bfa = bfa; 76 fcs->bfa = bfa;
77 fcs->bfad = bfad; 77 fcs->bfad = bfad;
78 fcs->min_cfg = min_cfg; 78 fcs->min_cfg = min_cfg;
79 fcs->num_rport_logins = 0;
79 80
80 bfa->fcs = BFA_TRUE; 81 bfa->fcs = BFA_TRUE;
81 fcbuild_init(); 82 fcbuild_init();
@@ -119,6 +120,18 @@ bfa_fcs_update_cfg(struct bfa_fcs_s *fcs)
119} 120}
120 121
121/* 122/*
123 * Stop FCS operations.
124 */
125void
126bfa_fcs_stop(struct bfa_fcs_s *fcs)
127{
128 bfa_wc_init(&fcs->wc, bfa_fcs_exit_comp, fcs);
129 bfa_wc_up(&fcs->wc);
130 bfa_fcs_fabric_modstop(fcs);
131 bfa_wc_wait(&fcs->wc);
132}
133
134/*
122 * fcs pbc vport initialization 135 * fcs pbc vport initialization
123 */ 136 */
124void 137void
@@ -153,6 +166,7 @@ bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs,
153 fcs->driver_info = *driver_info; 166 fcs->driver_info = *driver_info;
154 167
155 bfa_fcs_fabric_psymb_init(&fcs->fabric); 168 bfa_fcs_fabric_psymb_init(&fcs->fabric);
169 bfa_fcs_fabric_nsymb_init(&fcs->fabric);
156} 170}
157 171
158/* 172/*
@@ -213,6 +227,8 @@ static void bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric);
213static void bfa_fcs_fabric_delay(void *cbarg); 227static void bfa_fcs_fabric_delay(void *cbarg);
214static void bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric); 228static void bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric);
215static void bfa_fcs_fabric_delete_comp(void *cbarg); 229static void bfa_fcs_fabric_delete_comp(void *cbarg);
230static void bfa_fcs_fabric_stop(struct bfa_fcs_fabric_s *fabric);
231static void bfa_fcs_fabric_stop_comp(void *cbarg);
216static void bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric, 232static void bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric,
217 struct fchs_s *fchs, u16 len); 233 struct fchs_s *fchs, u16 len);
218static void bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric, 234static void bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,
@@ -250,6 +266,10 @@ static void bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric,
250 enum bfa_fcs_fabric_event event); 266 enum bfa_fcs_fabric_event event);
251static void bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric, 267static void bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,
252 enum bfa_fcs_fabric_event event); 268 enum bfa_fcs_fabric_event event);
269static void bfa_fcs_fabric_sm_stopping(struct bfa_fcs_fabric_s *fabric,
270 enum bfa_fcs_fabric_event event);
271static void bfa_fcs_fabric_sm_cleanup(struct bfa_fcs_fabric_s *fabric,
272 enum bfa_fcs_fabric_event event);
253/* 273/*
254 * Beginning state before fabric creation. 274 * Beginning state before fabric creation.
255 */ 275 */
@@ -334,6 +354,11 @@ bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,
334 bfa_fcs_fabric_delete(fabric); 354 bfa_fcs_fabric_delete(fabric);
335 break; 355 break;
336 356
357 case BFA_FCS_FABRIC_SM_STOP:
358 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_cleanup);
359 bfa_fcs_fabric_stop(fabric);
360 break;
361
337 default: 362 default:
338 bfa_sm_fault(fabric->fcs, event); 363 bfa_sm_fault(fabric->fcs, event);
339 } 364 }
@@ -585,6 +610,11 @@ bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
585 bfa_fcs_fabric_delete(fabric); 610 bfa_fcs_fabric_delete(fabric);
586 break; 611 break;
587 612
613 case BFA_FCS_FABRIC_SM_STOP:
614 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_stopping);
615 bfa_fcs_fabric_stop(fabric);
616 break;
617
588 case BFA_FCS_FABRIC_SM_AUTH_FAILED: 618 case BFA_FCS_FABRIC_SM_AUTH_FAILED:
589 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed); 619 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);
590 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE); 620 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
@@ -682,7 +712,62 @@ bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,
682 } 712 }
683} 713}
684 714
715/*
716 * Fabric is being stopped, awaiting vport stop completions.
717 */
718static void
719bfa_fcs_fabric_sm_stopping(struct bfa_fcs_fabric_s *fabric,
720 enum bfa_fcs_fabric_event event)
721{
722 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
723 bfa_trc(fabric->fcs, event);
724
725 switch (event) {
726 case BFA_FCS_FABRIC_SM_STOPCOMP:
727 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_cleanup);
728 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_LOGOUT);
729 break;
730
731 case BFA_FCS_FABRIC_SM_LINK_UP:
732 break;
733
734 case BFA_FCS_FABRIC_SM_LINK_DOWN:
735 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_cleanup);
736 break;
737
738 default:
739 bfa_sm_fault(fabric->fcs, event);
740 }
741}
742
743/*
744 * Fabric is being stopped, cleanup without FLOGO
745 */
746static void
747bfa_fcs_fabric_sm_cleanup(struct bfa_fcs_fabric_s *fabric,
748 enum bfa_fcs_fabric_event event)
749{
750 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
751 bfa_trc(fabric->fcs, event);
685 752
753 switch (event) {
754 case BFA_FCS_FABRIC_SM_STOPCOMP:
755 case BFA_FCS_FABRIC_SM_LOGOCOMP:
756 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created);
757 bfa_wc_down(&(fabric->fcs)->wc);
758 break;
759
760 case BFA_FCS_FABRIC_SM_LINK_DOWN:
761 /*
762 * Ignore - can get this event if we get notified about IOC down
763 * before the fabric completion callbk is done.
764 */
765 break;
766
767 default:
768 bfa_sm_fault(fabric->fcs, event);
769 }
770}
686 771
687/* 772/*
688 * fcs_fabric_private fabric private functions 773 * fcs_fabric_private fabric private functions
@@ -760,6 +845,44 @@ bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric)
760} 845}
761 846
762/* 847/*
848 * Node Symbolic Name Creation for base port and all vports
849 */
850void
851bfa_fcs_fabric_nsymb_init(struct bfa_fcs_fabric_s *fabric)
852{
853 struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg;
854 char model[BFA_ADAPTER_MODEL_NAME_LEN] = {0};
855 struct bfa_fcs_driver_info_s *driver_info = &fabric->fcs->driver_info;
856
857 bfa_ioc_get_adapter_model(&fabric->fcs->bfa->ioc, model);
858
859 /* Model name/number */
860 strncpy((char *)&port_cfg->node_sym_name, model,
861 BFA_FCS_PORT_SYMBNAME_MODEL_SZ);
862 strncat((char *)&port_cfg->node_sym_name,
863 BFA_FCS_PORT_SYMBNAME_SEPARATOR,
864 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
865
866 /* Driver Version */
867 strncat((char *)&port_cfg->node_sym_name, (char *)driver_info->version,
868 BFA_FCS_PORT_SYMBNAME_VERSION_SZ);
869 strncat((char *)&port_cfg->node_sym_name,
870 BFA_FCS_PORT_SYMBNAME_SEPARATOR,
871 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
872
873 /* Host machine name */
874 strncat((char *)&port_cfg->node_sym_name,
875 (char *)driver_info->host_machine_name,
876 BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ);
877 strncat((char *)&port_cfg->node_sym_name,
878 BFA_FCS_PORT_SYMBNAME_SEPARATOR,
879 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
880
881 /* null terminate */
882 port_cfg->node_sym_name.symname[BFA_SYMNAME_MAXLEN - 1] = 0;
883}
884
885/*
763 * bfa lps login completion callback 886 * bfa lps login completion callback
764 */ 887 */
765void 888void
@@ -919,6 +1042,28 @@ bfa_fcs_fabric_delay(void *cbarg)
919} 1042}
920 1043
921/* 1044/*
1045 * Stop all vports and wait for vport stop completions.
1046 */
1047static void
1048bfa_fcs_fabric_stop(struct bfa_fcs_fabric_s *fabric)
1049{
1050 struct bfa_fcs_vport_s *vport;
1051 struct list_head *qe, *qen;
1052
1053 bfa_wc_init(&fabric->stop_wc, bfa_fcs_fabric_stop_comp, fabric);
1054
1055 list_for_each_safe(qe, qen, &fabric->vport_q) {
1056 vport = (struct bfa_fcs_vport_s *) qe;
1057 bfa_wc_up(&fabric->stop_wc);
1058 bfa_fcs_vport_fcs_stop(vport);
1059 }
1060
1061 bfa_wc_up(&fabric->stop_wc);
1062 bfa_fcs_lport_stop(&fabric->bport);
1063 bfa_wc_wait(&fabric->stop_wc);
1064}
1065
1066/*
922 * Computes operating BB_SCN value 1067 * Computes operating BB_SCN value
923 */ 1068 */
924static u8 1069static u8
@@ -978,6 +1123,14 @@ bfa_fcs_fabric_delete_comp(void *cbarg)
978 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELCOMP); 1123 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELCOMP);
979} 1124}
980 1125
1126static void
1127bfa_fcs_fabric_stop_comp(void *cbarg)
1128{
1129 struct bfa_fcs_fabric_s *fabric = cbarg;
1130
1131 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_STOPCOMP);
1132}
1133
981/* 1134/*
982 * fcs_fabric_public fabric public functions 1135 * fcs_fabric_public fabric public functions
983 */ 1136 */
@@ -1039,6 +1192,19 @@ bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs)
1039} 1192}
1040 1193
1041/* 1194/*
1195 * Fabric module stop -- stop FCS actions
1196 */
1197void
1198bfa_fcs_fabric_modstop(struct bfa_fcs_s *fcs)
1199{
1200 struct bfa_fcs_fabric_s *fabric;
1201
1202 bfa_trc(fcs, 0);
1203 fabric = &fcs->fabric;
1204 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_STOP);
1205}
1206
1207/*
1042 * Fabric module start -- kick starts FCS actions 1208 * Fabric module start -- kick starts FCS actions
1043 */ 1209 */
1044void 1210void
@@ -1219,8 +1385,11 @@ bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,
1219 return; 1385 return;
1220 } 1386 }
1221 } 1387 }
1222 bfa_trc(fabric->fcs, els_cmd->els_code); 1388
1223 bfa_fcs_lport_uf_recv(&fabric->bport, fchs, len); 1389 if (!bfa_fcs_fabric_is_switched(fabric))
1390 bfa_fcs_lport_uf_recv(&fabric->bport, fchs, len);
1391
1392 bfa_trc(fabric->fcs, fchs->type);
1224} 1393}
1225 1394
1226/* 1395/*
@@ -1294,7 +1463,7 @@ bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric)
1294 u16 reqlen; 1463 u16 reqlen;
1295 struct fchs_s fchs; 1464 struct fchs_s fchs;
1296 1465
1297 fcxp = bfa_fcs_fcxp_alloc(fabric->fcs); 1466 fcxp = bfa_fcs_fcxp_alloc(fabric->fcs, BFA_FALSE);
1298 /* 1467 /*
1299 * Do not expect this failure -- expect remote node to retry 1468 * Do not expect this failure -- expect remote node to retry
1300 */ 1469 */
@@ -1387,6 +1556,13 @@ bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,
1387 } 1556 }
1388} 1557}
1389 1558
1559void
1560bfa_cb_lps_flogo_comp(void *bfad, void *uarg)
1561{
1562 struct bfa_fcs_fabric_s *fabric = uarg;
1563 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LOGOCOMP);
1564}
1565
1390/* 1566/*
1391 * Returns FCS vf structure for a given vf_id. 1567 * Returns FCS vf structure for a given vf_id.
1392 * 1568 *
diff --git a/drivers/scsi/bfa/bfa_fcs.h b/drivers/scsi/bfa/bfa_fcs.h
index 51c9e134571..6c4377cb287 100644
--- a/drivers/scsi/bfa/bfa_fcs.h
+++ b/drivers/scsi/bfa/bfa_fcs.h
@@ -62,9 +62,9 @@ struct bfa_fcs_s;
62#define N2N_LOCAL_PID 0x010000 62#define N2N_LOCAL_PID 0x010000
63#define N2N_REMOTE_PID 0x020000 63#define N2N_REMOTE_PID 0x020000
64#define BFA_FCS_RETRY_TIMEOUT 2000 64#define BFA_FCS_RETRY_TIMEOUT 2000
65#define BFA_FCS_MAX_NS_RETRIES 5
65#define BFA_FCS_PID_IS_WKA(pid) ((bfa_ntoh3b(pid) > 0xFFF000) ? 1 : 0) 66#define BFA_FCS_PID_IS_WKA(pid) ((bfa_ntoh3b(pid) > 0xFFF000) ? 1 : 0)
66 67#define BFA_FCS_MAX_RPORT_LOGINS 1024
67
68 68
69struct bfa_fcs_lport_ns_s { 69struct bfa_fcs_lport_ns_s {
70 bfa_sm_t sm; /* state machine */ 70 bfa_sm_t sm; /* state machine */
@@ -72,6 +72,8 @@ struct bfa_fcs_lport_ns_s {
72 struct bfa_fcs_lport_s *port; /* parent port */ 72 struct bfa_fcs_lport_s *port; /* parent port */
73 struct bfa_fcxp_s *fcxp; 73 struct bfa_fcxp_s *fcxp;
74 struct bfa_fcxp_wqe_s fcxp_wqe; 74 struct bfa_fcxp_wqe_s fcxp_wqe;
75 u8 num_rnnid_retries;
76 u8 num_rsnn_nn_retries;
75}; 77};
76 78
77 79
@@ -205,6 +207,7 @@ struct bfa_fcs_fabric_s {
205 struct bfa_lps_s *lps; /* lport login services */ 207 struct bfa_lps_s *lps; /* lport login services */
206 u8 fabric_ip_addr[BFA_FCS_FABRIC_IPADDR_SZ]; 208 u8 fabric_ip_addr[BFA_FCS_FABRIC_IPADDR_SZ];
207 /* attached fabric's ip addr */ 209 /* attached fabric's ip addr */
210 struct bfa_wc_s stop_wc; /* wait counter for stop */
208}; 211};
209 212
210#define bfa_fcs_fabric_npiv_capable(__f) ((__f)->is_npiv) 213#define bfa_fcs_fabric_npiv_capable(__f) ((__f)->is_npiv)
@@ -264,6 +267,7 @@ struct bfa_fcs_fabric_s;
264#define bfa_fcs_lport_get_pwwn(_lport) ((_lport)->port_cfg.pwwn) 267#define bfa_fcs_lport_get_pwwn(_lport) ((_lport)->port_cfg.pwwn)
265#define bfa_fcs_lport_get_nwwn(_lport) ((_lport)->port_cfg.nwwn) 268#define bfa_fcs_lport_get_nwwn(_lport) ((_lport)->port_cfg.nwwn)
266#define bfa_fcs_lport_get_psym_name(_lport) ((_lport)->port_cfg.sym_name) 269#define bfa_fcs_lport_get_psym_name(_lport) ((_lport)->port_cfg.sym_name)
270#define bfa_fcs_lport_get_nsym_name(_lport) ((_lport)->port_cfg.node_sym_name)
267#define bfa_fcs_lport_is_initiator(_lport) \ 271#define bfa_fcs_lport_is_initiator(_lport) \
268 ((_lport)->port_cfg.roles & BFA_LPORT_ROLE_FCP_IM) 272 ((_lport)->port_cfg.roles & BFA_LPORT_ROLE_FCP_IM)
269#define bfa_fcs_lport_get_nrports(_lport) \ 273#define bfa_fcs_lport_get_nrports(_lport) \
@@ -286,9 +290,8 @@ bfa_fcs_lport_get_drvport(struct bfa_fcs_lport_s *port)
286 290
287bfa_boolean_t bfa_fcs_lport_is_online(struct bfa_fcs_lport_s *port); 291bfa_boolean_t bfa_fcs_lport_is_online(struct bfa_fcs_lport_s *port);
288struct bfa_fcs_lport_s *bfa_fcs_get_base_port(struct bfa_fcs_s *fcs); 292struct bfa_fcs_lport_s *bfa_fcs_get_base_port(struct bfa_fcs_s *fcs);
289void bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port, 293void bfa_fcs_lport_get_rport_quals(struct bfa_fcs_lport_s *port,
290 wwn_t rport_wwns[], int *nrports); 294 struct bfa_rport_qualifier_s rport[], int *nrports);
291
292wwn_t bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn, 295wwn_t bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn,
293 int index, int nrports, bfa_boolean_t bwwn); 296 int index, int nrports, bfa_boolean_t bwwn);
294 297
@@ -324,12 +327,17 @@ void bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport,
324void bfa_fcs_lport_online(struct bfa_fcs_lport_s *port); 327void bfa_fcs_lport_online(struct bfa_fcs_lport_s *port);
325void bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port); 328void bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port);
326void bfa_fcs_lport_delete(struct bfa_fcs_lport_s *port); 329void bfa_fcs_lport_delete(struct bfa_fcs_lport_s *port);
330void bfa_fcs_lport_stop(struct bfa_fcs_lport_s *port);
327struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_pid( 331struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_pid(
328 struct bfa_fcs_lport_s *port, u32 pid); 332 struct bfa_fcs_lport_s *port, u32 pid);
333struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_old_pid(
334 struct bfa_fcs_lport_s *port, u32 pid);
329struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_pwwn( 335struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_pwwn(
330 struct bfa_fcs_lport_s *port, wwn_t pwwn); 336 struct bfa_fcs_lport_s *port, wwn_t pwwn);
331struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_nwwn( 337struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_nwwn(
332 struct bfa_fcs_lport_s *port, wwn_t nwwn); 338 struct bfa_fcs_lport_s *port, wwn_t nwwn);
339struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_qualifier(
340 struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 pid);
333void bfa_fcs_lport_add_rport(struct bfa_fcs_lport_s *port, 341void bfa_fcs_lport_add_rport(struct bfa_fcs_lport_s *port,
334 struct bfa_fcs_rport_s *rport); 342 struct bfa_fcs_rport_s *rport);
335void bfa_fcs_lport_del_rport(struct bfa_fcs_lport_s *port, 343void bfa_fcs_lport_del_rport(struct bfa_fcs_lport_s *port,
@@ -338,6 +346,8 @@ void bfa_fcs_lport_ns_init(struct bfa_fcs_lport_s *vport);
338void bfa_fcs_lport_ns_offline(struct bfa_fcs_lport_s *vport); 346void bfa_fcs_lport_ns_offline(struct bfa_fcs_lport_s *vport);
339void bfa_fcs_lport_ns_online(struct bfa_fcs_lport_s *vport); 347void bfa_fcs_lport_ns_online(struct bfa_fcs_lport_s *vport);
340void bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s *port); 348void bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s *port);
349void bfa_fcs_lport_ns_util_send_rspn_id(void *cbarg,
350 struct bfa_fcxp_s *fcxp_alloced);
341void bfa_fcs_lport_scn_init(struct bfa_fcs_lport_s *vport); 351void bfa_fcs_lport_scn_init(struct bfa_fcs_lport_s *vport);
342void bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *vport); 352void bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *vport);
343void bfa_fcs_lport_scn_online(struct bfa_fcs_lport_s *vport); 353void bfa_fcs_lport_scn_online(struct bfa_fcs_lport_s *vport);
@@ -382,6 +392,7 @@ void bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport);
382void bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport); 392void bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport);
383void bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport); 393void bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport);
384void bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport); 394void bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport);
395void bfa_fcs_vport_fcs_stop(struct bfa_fcs_vport_s *vport);
385void bfa_fcs_vport_stop_comp(struct bfa_fcs_vport_s *vport); 396void bfa_fcs_vport_stop_comp(struct bfa_fcs_vport_s *vport);
386 397
387#define BFA_FCS_RPORT_DEF_DEL_TIMEOUT 90 /* in secs */ 398#define BFA_FCS_RPORT_DEF_DEL_TIMEOUT 90 /* in secs */
@@ -419,6 +430,7 @@ struct bfa_fcs_rport_s {
419 struct bfa_fcs_s *fcs; /* fcs instance */ 430 struct bfa_fcs_s *fcs; /* fcs instance */
420 struct bfad_rport_s *rp_drv; /* driver peer instance */ 431 struct bfad_rport_s *rp_drv; /* driver peer instance */
421 u32 pid; /* port ID of rport */ 432 u32 pid; /* port ID of rport */
433 u32 old_pid; /* PID before rport goes offline */
422 u16 maxfrsize; /* maximum frame size */ 434 u16 maxfrsize; /* maximum frame size */
423 __be16 reply_oxid; /* OX_ID of inbound requests */ 435 __be16 reply_oxid; /* OX_ID of inbound requests */
424 enum fc_cos fc_cos; /* FC classes of service supp */ 436 enum fc_cos fc_cos; /* FC classes of service supp */
@@ -459,7 +471,7 @@ struct bfa_fcs_rport_s *bfa_fcs_rport_lookup(struct bfa_fcs_lport_s *port,
459struct bfa_fcs_rport_s *bfa_fcs_rport_lookup_by_nwwn( 471struct bfa_fcs_rport_s *bfa_fcs_rport_lookup_by_nwwn(
460 struct bfa_fcs_lport_s *port, wwn_t rnwwn); 472 struct bfa_fcs_lport_s *port, wwn_t rnwwn);
461void bfa_fcs_rport_set_del_timeout(u8 rport_tmo); 473void bfa_fcs_rport_set_del_timeout(u8 rport_tmo);
462 474void bfa_fcs_rport_set_max_logins(u32 max_logins);
463void bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport, 475void bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport,
464 struct fchs_s *fchs, u16 len); 476 struct fchs_s *fchs, u16 len);
465void bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport); 477void bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport);
@@ -505,12 +517,13 @@ struct bfa_fcs_itnim_s {
505 struct bfa_fcxp_s *fcxp; /* FCXP in use */ 517 struct bfa_fcxp_s *fcxp; /* FCXP in use */
506 struct bfa_itnim_stats_s stats; /* itn statistics */ 518 struct bfa_itnim_stats_s stats; /* itn statistics */
507}; 519};
508#define bfa_fcs_fcxp_alloc(__fcs) \ 520#define bfa_fcs_fcxp_alloc(__fcs, __req) \
509 bfa_fcxp_alloc(NULL, (__fcs)->bfa, 0, 0, NULL, NULL, NULL, NULL) 521 bfa_fcxp_req_rsp_alloc(NULL, (__fcs)->bfa, 0, 0, \
510 522 NULL, NULL, NULL, NULL, __req)
511#define bfa_fcs_fcxp_alloc_wait(__bfa, __wqe, __alloc_cbfn, __alloc_cbarg) \ 523#define bfa_fcs_fcxp_alloc_wait(__bfa, __wqe, __alloc_cbfn, \
512 bfa_fcxp_alloc_wait(__bfa, __wqe, __alloc_cbfn, __alloc_cbarg, \ 524 __alloc_cbarg, __req) \
513 NULL, 0, 0, NULL, NULL, NULL, NULL) 525 bfa_fcxp_req_rsp_alloc_wait(__bfa, __wqe, __alloc_cbfn, \
526 __alloc_cbarg, NULL, 0, 0, NULL, NULL, NULL, NULL, __req)
514 527
515static inline struct bfad_port_s * 528static inline struct bfad_port_s *
516bfa_fcs_itnim_get_drvport(struct bfa_fcs_itnim_s *itnim) 529bfa_fcs_itnim_get_drvport(struct bfa_fcs_itnim_s *itnim)
@@ -592,7 +605,7 @@ bfa_status_t bfa_fcs_itnim_stats_clear(struct bfa_fcs_lport_s *port,
592struct bfa_fcs_itnim_s *bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport); 605struct bfa_fcs_itnim_s *bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport);
593void bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s *itnim); 606void bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s *itnim);
594void bfa_fcs_itnim_rport_offline(struct bfa_fcs_itnim_s *itnim); 607void bfa_fcs_itnim_rport_offline(struct bfa_fcs_itnim_s *itnim);
595void bfa_fcs_itnim_rport_online(struct bfa_fcs_itnim_s *itnim); 608void bfa_fcs_itnim_brp_online(struct bfa_fcs_itnim_s *itnim);
596bfa_status_t bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s *itnim); 609bfa_status_t bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s *itnim);
597void bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s *itnim); 610void bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s *itnim);
598void bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim, 611void bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim,
@@ -676,6 +689,7 @@ struct bfa_fcs_s {
676 struct bfa_fcs_stats_s stats; /* FCS statistics */ 689 struct bfa_fcs_stats_s stats; /* FCS statistics */
677 struct bfa_wc_s wc; /* waiting counter */ 690 struct bfa_wc_s wc; /* waiting counter */
678 int fcs_aen_seq; 691 int fcs_aen_seq;
692 u32 num_rport_logins;
679}; 693};
680 694
681/* 695/*
@@ -702,6 +716,9 @@ enum bfa_fcs_fabric_event {
702 BFA_FCS_FABRIC_SM_DELCOMP = 14, /* all vports deleted event */ 716 BFA_FCS_FABRIC_SM_DELCOMP = 14, /* all vports deleted event */
703 BFA_FCS_FABRIC_SM_LOOPBACK = 15, /* Received our own FLOGI */ 717 BFA_FCS_FABRIC_SM_LOOPBACK = 15, /* Received our own FLOGI */
704 BFA_FCS_FABRIC_SM_START = 16, /* from driver */ 718 BFA_FCS_FABRIC_SM_START = 16, /* from driver */
719 BFA_FCS_FABRIC_SM_STOP = 17, /* Stop from driver */
720 BFA_FCS_FABRIC_SM_STOPCOMP = 18, /* Stop completion */
721 BFA_FCS_FABRIC_SM_LOGOCOMP = 19, /* FLOGO completion */
705}; 722};
706 723
707/* 724/*
@@ -727,6 +744,26 @@ enum rport_event {
727 RPSM_EVENT_ADDRESS_DISC = 16, /* Need to Discover rport's PID */ 744 RPSM_EVENT_ADDRESS_DISC = 16, /* Need to Discover rport's PID */
728 RPSM_EVENT_PRLO_RCVD = 17, /* PRLO from remote device */ 745 RPSM_EVENT_PRLO_RCVD = 17, /* PRLO from remote device */
729 RPSM_EVENT_PLOGI_RETRY = 18, /* Retry PLOGI continuously */ 746 RPSM_EVENT_PLOGI_RETRY = 18, /* Retry PLOGI continuously */
747 RPSM_EVENT_FC4_FCS_ONLINE = 19, /*!< FC-4 FCS online complete */
748};
749
750/*
751 * fcs_itnim_sm FCS itnim state machine events
752 */
753enum bfa_fcs_itnim_event {
754 BFA_FCS_ITNIM_SM_FCS_ONLINE = 1, /* rport online event */
755 BFA_FCS_ITNIM_SM_OFFLINE = 2, /* rport offline */
756 BFA_FCS_ITNIM_SM_FRMSENT = 3, /* prli frame is sent */
757 BFA_FCS_ITNIM_SM_RSP_OK = 4, /* good response */
758 BFA_FCS_ITNIM_SM_RSP_ERROR = 5, /* error response */
759 BFA_FCS_ITNIM_SM_TIMEOUT = 6, /* delay timeout */
760 BFA_FCS_ITNIM_SM_HCB_OFFLINE = 7, /* BFA online callback */
761 BFA_FCS_ITNIM_SM_HCB_ONLINE = 8, /* BFA offline callback */
762 BFA_FCS_ITNIM_SM_INITIATOR = 9, /* rport is initiator */
763 BFA_FCS_ITNIM_SM_DELETE = 10, /* delete event from rport */
764 BFA_FCS_ITNIM_SM_PRLO = 11, /* delete event from rport */
765 BFA_FCS_ITNIM_SM_RSP_NOT_SUPP = 12, /* cmd not supported rsp */
766 BFA_FCS_ITNIM_SM_HAL_ONLINE = 13, /*!< bfa rport online event */
730}; 767};
731 768
732/* 769/*
@@ -741,6 +778,7 @@ void bfa_fcs_update_cfg(struct bfa_fcs_s *fcs);
741void bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs, 778void bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs,
742 struct bfa_fcs_driver_info_s *driver_info); 779 struct bfa_fcs_driver_info_s *driver_info);
743void bfa_fcs_exit(struct bfa_fcs_s *fcs); 780void bfa_fcs_exit(struct bfa_fcs_s *fcs);
781void bfa_fcs_stop(struct bfa_fcs_s *fcs);
744 782
745/* 783/*
746 * bfa fcs vf public functions 784 * bfa fcs vf public functions
@@ -766,11 +804,13 @@ void bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs);
766void bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric, 804void bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric,
767 struct fchs_s *fchs, u16 len); 805 struct fchs_s *fchs, u16 len);
768void bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric); 806void bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric);
807void bfa_fcs_fabric_nsymb_init(struct bfa_fcs_fabric_s *fabric);
769void bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric, 808void bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,
770 wwn_t fabric_name); 809 wwn_t fabric_name);
771u16 bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric); 810u16 bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric);
772void bfa_fcs_uf_attach(struct bfa_fcs_s *fcs); 811void bfa_fcs_uf_attach(struct bfa_fcs_s *fcs);
773void bfa_fcs_port_attach(struct bfa_fcs_s *fcs); 812void bfa_fcs_port_attach(struct bfa_fcs_s *fcs);
813void bfa_fcs_fabric_modstop(struct bfa_fcs_s *fcs);
774void bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric, 814void bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
775 enum bfa_fcs_fabric_event event); 815 enum bfa_fcs_fabric_event event);
776void bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric, 816void bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric,
diff --git a/drivers/scsi/bfa/bfa_fcs_fcpim.c b/drivers/scsi/bfa/bfa_fcs_fcpim.c
index 9272840a240..6dc7926a3ed 100644
--- a/drivers/scsi/bfa/bfa_fcs_fcpim.c
+++ b/drivers/scsi/bfa/bfa_fcs_fcpim.c
@@ -40,25 +40,6 @@ static void bfa_fcs_itnim_prli_response(void *fcsarg,
40static void bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s *itnim, 40static void bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s *itnim,
41 enum bfa_itnim_aen_event event); 41 enum bfa_itnim_aen_event event);
42 42
43/*
44 * fcs_itnim_sm FCS itnim state machine events
45 */
46
47enum bfa_fcs_itnim_event {
48 BFA_FCS_ITNIM_SM_ONLINE = 1, /* rport online event */
49 BFA_FCS_ITNIM_SM_OFFLINE = 2, /* rport offline */
50 BFA_FCS_ITNIM_SM_FRMSENT = 3, /* prli frame is sent */
51 BFA_FCS_ITNIM_SM_RSP_OK = 4, /* good response */
52 BFA_FCS_ITNIM_SM_RSP_ERROR = 5, /* error response */
53 BFA_FCS_ITNIM_SM_TIMEOUT = 6, /* delay timeout */
54 BFA_FCS_ITNIM_SM_HCB_OFFLINE = 7, /* BFA online callback */
55 BFA_FCS_ITNIM_SM_HCB_ONLINE = 8, /* BFA offline callback */
56 BFA_FCS_ITNIM_SM_INITIATOR = 9, /* rport is initiator */
57 BFA_FCS_ITNIM_SM_DELETE = 10, /* delete event from rport */
58 BFA_FCS_ITNIM_SM_PRLO = 11, /* delete event from rport */
59 BFA_FCS_ITNIM_SM_RSP_NOT_SUPP = 12, /* cmd not supported rsp */
60};
61
62static void bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim, 43static void bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
63 enum bfa_fcs_itnim_event event); 44 enum bfa_fcs_itnim_event event);
64static void bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim, 45static void bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,
@@ -69,6 +50,8 @@ static void bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,
69 enum bfa_fcs_itnim_event event); 50 enum bfa_fcs_itnim_event event);
70static void bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim, 51static void bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
71 enum bfa_fcs_itnim_event event); 52 enum bfa_fcs_itnim_event event);
53static void bfa_fcs_itnim_sm_hal_rport_online(struct bfa_fcs_itnim_s *itnim,
54 enum bfa_fcs_itnim_event event);
72static void bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim, 55static void bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,
73 enum bfa_fcs_itnim_event event); 56 enum bfa_fcs_itnim_event event);
74static void bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim, 57static void bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim,
@@ -99,7 +82,7 @@ bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
99 bfa_trc(itnim->fcs, event); 82 bfa_trc(itnim->fcs, event);
100 83
101 switch (event) { 84 switch (event) {
102 case BFA_FCS_ITNIM_SM_ONLINE: 85 case BFA_FCS_ITNIM_SM_FCS_ONLINE:
103 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_send); 86 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_send);
104 itnim->prli_retries = 0; 87 itnim->prli_retries = 0;
105 bfa_fcs_itnim_send_prli(itnim, NULL); 88 bfa_fcs_itnim_send_prli(itnim, NULL);
@@ -138,6 +121,7 @@ bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,
138 case BFA_FCS_ITNIM_SM_INITIATOR: 121 case BFA_FCS_ITNIM_SM_INITIATOR:
139 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator); 122 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
140 bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe); 123 bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
124 bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);
141 break; 125 break;
142 126
143 case BFA_FCS_ITNIM_SM_OFFLINE: 127 case BFA_FCS_ITNIM_SM_OFFLINE:
@@ -166,12 +150,13 @@ bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
166 150
167 switch (event) { 151 switch (event) {
168 case BFA_FCS_ITNIM_SM_RSP_OK: 152 case BFA_FCS_ITNIM_SM_RSP_OK:
169 if (itnim->rport->scsi_function == BFA_RPORT_INITIATOR) { 153 if (itnim->rport->scsi_function == BFA_RPORT_INITIATOR)
170 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator); 154 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
171 } else { 155 else
172 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_online); 156 bfa_sm_set_state(itnim,
173 bfa_itnim_online(itnim->bfa_itnim, itnim->seq_rec); 157 bfa_fcs_itnim_sm_hal_rport_online);
174 } 158
159 bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);
175 break; 160 break;
176 161
177 case BFA_FCS_ITNIM_SM_RSP_ERROR: 162 case BFA_FCS_ITNIM_SM_RSP_ERROR:
@@ -194,6 +179,7 @@ bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
194 case BFA_FCS_ITNIM_SM_INITIATOR: 179 case BFA_FCS_ITNIM_SM_INITIATOR:
195 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator); 180 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
196 bfa_fcxp_discard(itnim->fcxp); 181 bfa_fcxp_discard(itnim->fcxp);
182 bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);
197 break; 183 break;
198 184
199 case BFA_FCS_ITNIM_SM_DELETE: 185 case BFA_FCS_ITNIM_SM_DELETE:
@@ -208,6 +194,44 @@ bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
208} 194}
209 195
210static void 196static void
197bfa_fcs_itnim_sm_hal_rport_online(struct bfa_fcs_itnim_s *itnim,
198 enum bfa_fcs_itnim_event event)
199{
200 bfa_trc(itnim->fcs, itnim->rport->pwwn);
201 bfa_trc(itnim->fcs, event);
202
203 switch (event) {
204 case BFA_FCS_ITNIM_SM_HAL_ONLINE:
205 if (!itnim->bfa_itnim)
206 itnim->bfa_itnim = bfa_itnim_create(itnim->fcs->bfa,
207 itnim->rport->bfa_rport, itnim);
208
209 if (itnim->bfa_itnim) {
210 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_online);
211 bfa_itnim_online(itnim->bfa_itnim, itnim->seq_rec);
212 } else {
213 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
214 bfa_sm_send_event(itnim->rport, RPSM_EVENT_DELETE);
215 }
216
217 break;
218
219 case BFA_FCS_ITNIM_SM_OFFLINE:
220 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
221 bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
222 break;
223
224 case BFA_FCS_ITNIM_SM_DELETE:
225 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
226 bfa_fcs_itnim_free(itnim);
227 break;
228
229 default:
230 bfa_sm_fault(itnim->fcs, event);
231 }
232}
233
234static void
211bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim, 235bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,
212 enum bfa_fcs_itnim_event event) 236 enum bfa_fcs_itnim_event event)
213{ 237{
@@ -238,6 +262,7 @@ bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,
238 case BFA_FCS_ITNIM_SM_INITIATOR: 262 case BFA_FCS_ITNIM_SM_INITIATOR:
239 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator); 263 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
240 bfa_timer_stop(&itnim->timer); 264 bfa_timer_stop(&itnim->timer);
265 bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);
241 break; 266 break;
242 267
243 case BFA_FCS_ITNIM_SM_DELETE: 268 case BFA_FCS_ITNIM_SM_DELETE:
@@ -275,9 +300,8 @@ bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
275 break; 300 break;
276 301
277 case BFA_FCS_ITNIM_SM_OFFLINE: 302 case BFA_FCS_ITNIM_SM_OFFLINE:
278 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); 303 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_offline);
279 bfa_itnim_offline(itnim->bfa_itnim); 304 bfa_itnim_offline(itnim->bfa_itnim);
280 bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
281 break; 305 break;
282 306
283 case BFA_FCS_ITNIM_SM_DELETE: 307 case BFA_FCS_ITNIM_SM_DELETE:
@@ -372,8 +396,14 @@ bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,
372 bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE); 396 bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
373 break; 397 break;
374 398
399 /*
400 * fcs_online is expected here for well known initiator ports
401 */
402 case BFA_FCS_ITNIM_SM_FCS_ONLINE:
403 bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);
404 break;
405
375 case BFA_FCS_ITNIM_SM_RSP_ERROR: 406 case BFA_FCS_ITNIM_SM_RSP_ERROR:
376 case BFA_FCS_ITNIM_SM_ONLINE:
377 case BFA_FCS_ITNIM_SM_INITIATOR: 407 case BFA_FCS_ITNIM_SM_INITIATOR:
378 break; 408 break;
379 409
@@ -426,11 +456,12 @@ bfa_fcs_itnim_send_prli(void *itnim_cbarg, struct bfa_fcxp_s *fcxp_alloced)
426 456
427 bfa_trc(itnim->fcs, itnim->rport->pwwn); 457 bfa_trc(itnim->fcs, itnim->rport->pwwn);
428 458
429 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 459 fcxp = fcxp_alloced ? fcxp_alloced :
460 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
430 if (!fcxp) { 461 if (!fcxp) {
431 itnim->stats.fcxp_alloc_wait++; 462 itnim->stats.fcxp_alloc_wait++;
432 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &itnim->fcxp_wqe, 463 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &itnim->fcxp_wqe,
433 bfa_fcs_itnim_send_prli, itnim); 464 bfa_fcs_itnim_send_prli, itnim, BFA_TRUE);
434 return; 465 return;
435 } 466 }
436 itnim->fcxp = fcxp; 467 itnim->fcxp = fcxp;
@@ -483,7 +514,7 @@ bfa_fcs_itnim_prli_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
483 if (prli_resp->parampage.servparams.initiator) { 514 if (prli_resp->parampage.servparams.initiator) {
484 bfa_trc(itnim->fcs, prli_resp->parampage.type); 515 bfa_trc(itnim->fcs, prli_resp->parampage.type);
485 itnim->rport->scsi_function = 516 itnim->rport->scsi_function =
486 BFA_RPORT_INITIATOR; 517 BFA_RPORT_INITIATOR;
487 itnim->stats.prli_rsp_acc++; 518 itnim->stats.prli_rsp_acc++;
488 itnim->stats.initiator++; 519 itnim->stats.initiator++;
489 bfa_sm_send_event(itnim, 520 bfa_sm_send_event(itnim,
@@ -531,7 +562,11 @@ bfa_fcs_itnim_timeout(void *arg)
531static void 562static void
532bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim) 563bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim)
533{ 564{
534 bfa_itnim_delete(itnim->bfa_itnim); 565 if (itnim->bfa_itnim) {
566 bfa_itnim_delete(itnim->bfa_itnim);
567 itnim->bfa_itnim = NULL;
568 }
569
535 bfa_fcb_itnim_free(itnim->fcs->bfad, itnim->itnim_drv); 570 bfa_fcb_itnim_free(itnim->fcs->bfad, itnim->itnim_drv);
536} 571}
537 572
@@ -552,7 +587,6 @@ bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport)
552 struct bfa_fcs_lport_s *port = rport->port; 587 struct bfa_fcs_lport_s *port = rport->port;
553 struct bfa_fcs_itnim_s *itnim; 588 struct bfa_fcs_itnim_s *itnim;
554 struct bfad_itnim_s *itnim_drv; 589 struct bfad_itnim_s *itnim_drv;
555 struct bfa_itnim_s *bfa_itnim;
556 590
557 /* 591 /*
558 * call bfad to allocate the itnim 592 * call bfad to allocate the itnim
@@ -570,20 +604,7 @@ bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport)
570 itnim->fcs = rport->fcs; 604 itnim->fcs = rport->fcs;
571 itnim->itnim_drv = itnim_drv; 605 itnim->itnim_drv = itnim_drv;
572 606
573 /* 607 itnim->bfa_itnim = NULL;
574 * call BFA to create the itnim
575 */
576 bfa_itnim =
577 bfa_itnim_create(port->fcs->bfa, rport->bfa_rport, itnim);
578
579 if (bfa_itnim == NULL) {
580 bfa_trc(port->fcs, rport->pwwn);
581 bfa_fcb_itnim_free(port->fcs->bfad, itnim_drv);
582 WARN_ON(1);
583 return NULL;
584 }
585
586 itnim->bfa_itnim = bfa_itnim;
587 itnim->seq_rec = BFA_FALSE; 608 itnim->seq_rec = BFA_FALSE;
588 itnim->rec_support = BFA_FALSE; 609 itnim->rec_support = BFA_FALSE;
589 itnim->conf_comp = BFA_FALSE; 610 itnim->conf_comp = BFA_FALSE;
@@ -613,20 +634,12 @@ bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s *itnim)
613 * Notification from rport that PLOGI is complete to initiate FC-4 session. 634 * Notification from rport that PLOGI is complete to initiate FC-4 session.
614 */ 635 */
615void 636void
616bfa_fcs_itnim_rport_online(struct bfa_fcs_itnim_s *itnim) 637bfa_fcs_itnim_brp_online(struct bfa_fcs_itnim_s *itnim)
617{ 638{
618 itnim->stats.onlines++; 639 itnim->stats.onlines++;
619 640
620 if (!BFA_FCS_PID_IS_WKA(itnim->rport->pid)) { 641 if (!BFA_FCS_PID_IS_WKA(itnim->rport->pid))
621 bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_ONLINE); 642 bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HAL_ONLINE);
622 } else {
623 /*
624 * For well known addresses, we set the itnim to initiator
625 * state
626 */
627 itnim->stats.initiator++;
628 bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_INITIATOR);
629 }
630} 643}
631 644
632/* 645/*
diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c
index bcc4966e8ba..3b75f6fb2de 100644
--- a/drivers/scsi/bfa/bfa_fcs_lport.c
+++ b/drivers/scsi/bfa/bfa_fcs_lport.c
@@ -131,6 +131,8 @@ bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
131 /* If vport - send completion call back */ 131 /* If vport - send completion call back */
132 if (port->vport) 132 if (port->vport)
133 bfa_fcs_vport_stop_comp(port->vport); 133 bfa_fcs_vport_stop_comp(port->vport);
134 else
135 bfa_wc_down(&(port->fabric->stop_wc));
134 break; 136 break;
135 137
136 case BFA_FCS_PORT_SM_OFFLINE: 138 case BFA_FCS_PORT_SM_OFFLINE:
@@ -166,6 +168,8 @@ bfa_fcs_lport_sm_online(
166 /* If vport - send completion call back */ 168 /* If vport - send completion call back */
167 if (port->vport) 169 if (port->vport)
168 bfa_fcs_vport_stop_comp(port->vport); 170 bfa_fcs_vport_stop_comp(port->vport);
171 else
172 bfa_wc_down(&(port->fabric->stop_wc));
169 } else { 173 } else {
170 bfa_sm_set_state(port, bfa_fcs_lport_sm_stopping); 174 bfa_sm_set_state(port, bfa_fcs_lport_sm_stopping);
171 list_for_each_safe(qe, qen, &port->rport_q) { 175 list_for_each_safe(qe, qen, &port->rport_q) {
@@ -222,6 +226,8 @@ bfa_fcs_lport_sm_offline(
222 /* If vport - send completion call back */ 226 /* If vport - send completion call back */
223 if (port->vport) 227 if (port->vport)
224 bfa_fcs_vport_stop_comp(port->vport); 228 bfa_fcs_vport_stop_comp(port->vport);
229 else
230 bfa_wc_down(&(port->fabric->stop_wc));
225 } else { 231 } else {
226 bfa_sm_set_state(port, bfa_fcs_lport_sm_stopping); 232 bfa_sm_set_state(port, bfa_fcs_lport_sm_stopping);
227 list_for_each_safe(qe, qen, &port->rport_q) { 233 list_for_each_safe(qe, qen, &port->rport_q) {
@@ -267,6 +273,8 @@ bfa_fcs_lport_sm_stopping(struct bfa_fcs_lport_s *port,
267 /* If vport - send completion call back */ 273 /* If vport - send completion call back */
268 if (port->vport) 274 if (port->vport)
269 bfa_fcs_vport_stop_comp(port->vport); 275 bfa_fcs_vport_stop_comp(port->vport);
276 else
277 bfa_wc_down(&(port->fabric->stop_wc));
270 } 278 }
271 break; 279 break;
272 280
@@ -340,7 +348,7 @@ bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
340 bfa_trc(port->fcs, rx_fchs->d_id); 348 bfa_trc(port->fcs, rx_fchs->d_id);
341 bfa_trc(port->fcs, rx_fchs->s_id); 349 bfa_trc(port->fcs, rx_fchs->s_id);
342 350
343 fcxp = bfa_fcs_fcxp_alloc(port->fcs); 351 fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
344 if (!fcxp) 352 if (!fcxp)
345 return; 353 return;
346 354
@@ -370,7 +378,7 @@ bfa_fcs_lport_send_fcgs_rjt(struct bfa_fcs_lport_s *port,
370 bfa_trc(port->fcs, rx_fchs->d_id); 378 bfa_trc(port->fcs, rx_fchs->d_id);
371 bfa_trc(port->fcs, rx_fchs->s_id); 379 bfa_trc(port->fcs, rx_fchs->s_id);
372 380
373 fcxp = bfa_fcs_fcxp_alloc(port->fcs); 381 fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
374 if (!fcxp) 382 if (!fcxp)
375 return; 383 return;
376 384
@@ -507,7 +515,7 @@ bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
507 bfa_trc(port->fcs, rx_fchs->s_id); 515 bfa_trc(port->fcs, rx_fchs->s_id);
508 bfa_trc(port->fcs, rx_fchs->d_id); 516 bfa_trc(port->fcs, rx_fchs->d_id);
509 517
510 fcxp = bfa_fcs_fcxp_alloc(port->fcs); 518 fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
511 if (!fcxp) 519 if (!fcxp)
512 return; 520 return;
513 521
@@ -552,7 +560,7 @@ bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
552 bfa_trc(port->fcs, rx_fchs->d_id); 560 bfa_trc(port->fcs, rx_fchs->d_id);
553 bfa_trc(port->fcs, rx_len); 561 bfa_trc(port->fcs, rx_len);
554 562
555 fcxp = bfa_fcs_fcxp_alloc(port->fcs); 563 fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
556 if (!fcxp) 564 if (!fcxp)
557 return; 565 return;
558 566
@@ -684,7 +692,7 @@ bfa_fcs_lport_abts_acc(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs)
684 bfa_trc(port->fcs, rx_fchs->d_id); 692 bfa_trc(port->fcs, rx_fchs->d_id);
685 bfa_trc(port->fcs, rx_fchs->s_id); 693 bfa_trc(port->fcs, rx_fchs->s_id);
686 694
687 fcxp = bfa_fcs_fcxp_alloc(port->fcs); 695 fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
688 if (!fcxp) 696 if (!fcxp)
689 return; 697 return;
690 698
@@ -854,6 +862,25 @@ bfa_fcs_lport_get_rport_by_pid(struct bfa_fcs_lport_s *port, u32 pid)
854} 862}
855 863
856/* 864/*
865 * OLD_PID based Lookup for a R-Port in the Port R-Port Queue
866 */
867struct bfa_fcs_rport_s *
868bfa_fcs_lport_get_rport_by_old_pid(struct bfa_fcs_lport_s *port, u32 pid)
869{
870 struct bfa_fcs_rport_s *rport;
871 struct list_head *qe;
872
873 list_for_each(qe, &port->rport_q) {
874 rport = (struct bfa_fcs_rport_s *) qe;
875 if (rport->old_pid == pid)
876 return rport;
877 }
878
879 bfa_trc(port->fcs, pid);
880 return NULL;
881}
882
883/*
857 * PWWN based Lookup for a R-Port in the Port R-Port Queue 884 * PWWN based Lookup for a R-Port in the Port R-Port Queue
858 */ 885 */
859struct bfa_fcs_rport_s * 886struct bfa_fcs_rport_s *
@@ -892,6 +919,26 @@ bfa_fcs_lport_get_rport_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t nwwn)
892} 919}
893 920
894/* 921/*
922 * PWWN & PID based Lookup for a R-Port in the Port R-Port Queue
923 */
924struct bfa_fcs_rport_s *
925bfa_fcs_lport_get_rport_by_qualifier(struct bfa_fcs_lport_s *port,
926 wwn_t pwwn, u32 pid)
927{
928 struct bfa_fcs_rport_s *rport;
929 struct list_head *qe;
930
931 list_for_each(qe, &port->rport_q) {
932 rport = (struct bfa_fcs_rport_s *) qe;
933 if (wwn_is_equal(rport->pwwn, pwwn) && rport->pid == pid)
934 return rport;
935 }
936
937 bfa_trc(port->fcs, pwwn);
938 return NULL;
939}
940
941/*
895 * Called by rport module when new rports are discovered. 942 * Called by rport module when new rports are discovered.
896 */ 943 */
897void 944void
@@ -939,6 +986,16 @@ bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port)
939} 986}
940 987
941/* 988/*
989 * Called by fabric for base port and by vport for virtual ports
990 * when target mode driver is unloaded.
991 */
992void
993bfa_fcs_lport_stop(struct bfa_fcs_lport_s *port)
994{
995 bfa_sm_send_event(port, BFA_FCS_PORT_SM_STOP);
996}
997
998/*
942 * Called by fabric to delete base lport and associated resources. 999 * Called by fabric to delete base lport and associated resources.
943 * 1000 *
944 * Called by vport to delete lport and associated resources. Should call 1001 * Called by vport to delete lport and associated resources. Should call
@@ -1657,10 +1714,11 @@ bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1657 1714
1658 bfa_trc(port->fcs, port->port_cfg.pwwn); 1715 bfa_trc(port->fcs, port->port_cfg.pwwn);
1659 1716
1660 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 1717 fcxp = fcxp_alloced ? fcxp_alloced :
1718 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
1661 if (!fcxp) { 1719 if (!fcxp) {
1662 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe, 1720 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
1663 bfa_fcs_lport_fdmi_send_rhba, fdmi); 1721 bfa_fcs_lport_fdmi_send_rhba, fdmi, BFA_TRUE);
1664 return; 1722 return;
1665 } 1723 }
1666 fdmi->fcxp = fcxp; 1724 fdmi->fcxp = fcxp;
@@ -1931,10 +1989,11 @@ bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1931 1989
1932 bfa_trc(port->fcs, port->port_cfg.pwwn); 1990 bfa_trc(port->fcs, port->port_cfg.pwwn);
1933 1991
1934 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 1992 fcxp = fcxp_alloced ? fcxp_alloced :
1993 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
1935 if (!fcxp) { 1994 if (!fcxp) {
1936 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe, 1995 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
1937 bfa_fcs_lport_fdmi_send_rprt, fdmi); 1996 bfa_fcs_lport_fdmi_send_rprt, fdmi, BFA_TRUE);
1938 return; 1997 return;
1939 } 1998 }
1940 fdmi->fcxp = fcxp; 1999 fdmi->fcxp = fcxp;
@@ -2146,10 +2205,11 @@ bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2146 2205
2147 bfa_trc(port->fcs, port->port_cfg.pwwn); 2206 bfa_trc(port->fcs, port->port_cfg.pwwn);
2148 2207
2149 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 2208 fcxp = fcxp_alloced ? fcxp_alloced :
2209 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
2150 if (!fcxp) { 2210 if (!fcxp) {
2151 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe, 2211 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
2152 bfa_fcs_lport_fdmi_send_rpa, fdmi); 2212 bfa_fcs_lport_fdmi_send_rpa, fdmi, BFA_TRUE);
2153 return; 2213 return;
2154 } 2214 }
2155 fdmi->fcxp = fcxp; 2215 fdmi->fcxp = fcxp;
@@ -2736,10 +2796,11 @@ bfa_fcs_lport_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2736 2796
2737 bfa_trc(port->fcs, port->pid); 2797 bfa_trc(port->fcs, port->pid);
2738 2798
2739 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 2799 fcxp = fcxp_alloced ? fcxp_alloced :
2800 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
2740 if (!fcxp) { 2801 if (!fcxp) {
2741 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe, 2802 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
2742 bfa_fcs_lport_ms_send_gmal, ms); 2803 bfa_fcs_lport_ms_send_gmal, ms, BFA_TRUE);
2743 return; 2804 return;
2744 } 2805 }
2745 ms->fcxp = fcxp; 2806 ms->fcxp = fcxp;
@@ -2936,10 +2997,11 @@ bfa_fcs_lport_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2936 2997
2937 bfa_trc(port->fcs, port->pid); 2998 bfa_trc(port->fcs, port->pid);
2938 2999
2939 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 3000 fcxp = fcxp_alloced ? fcxp_alloced :
3001 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
2940 if (!fcxp) { 3002 if (!fcxp) {
2941 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe, 3003 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
2942 bfa_fcs_lport_ms_send_gfn, ms); 3004 bfa_fcs_lport_ms_send_gfn, ms, BFA_TRUE);
2943 return; 3005 return;
2944 } 3006 }
2945 ms->fcxp = fcxp; 3007 ms->fcxp = fcxp;
@@ -3012,11 +3074,12 @@ bfa_fcs_lport_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3012 3074
3013 bfa_trc(port->fcs, port->pid); 3075 bfa_trc(port->fcs, port->pid);
3014 3076
3015 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 3077 fcxp = fcxp_alloced ? fcxp_alloced :
3078 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
3016 if (!fcxp) { 3079 if (!fcxp) {
3017 port->stats.ms_plogi_alloc_wait++; 3080 port->stats.ms_plogi_alloc_wait++;
3018 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe, 3081 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
3019 bfa_fcs_lport_ms_send_plogi, ms); 3082 bfa_fcs_lport_ms_send_plogi, ms, BFA_TRUE);
3020 return; 3083 return;
3021 } 3084 }
3022 ms->fcxp = fcxp; 3085 ms->fcxp = fcxp;
@@ -3166,6 +3229,10 @@ static void bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg,
3166 struct bfa_fcxp_s *fcxp_alloced); 3229 struct bfa_fcxp_s *fcxp_alloced);
3167static void bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg, 3230static void bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg,
3168 struct bfa_fcxp_s *fcxp_alloced); 3231 struct bfa_fcxp_s *fcxp_alloced);
3232static void bfa_fcs_lport_ns_send_rnn_id(void *ns_cbarg,
3233 struct bfa_fcxp_s *fcxp_alloced);
3234static void bfa_fcs_lport_ns_send_rsnn_nn(void *ns_cbarg,
3235 struct bfa_fcxp_s *fcxp_alloced);
3169static void bfa_fcs_lport_ns_timeout(void *arg); 3236static void bfa_fcs_lport_ns_timeout(void *arg);
3170static void bfa_fcs_lport_ns_plogi_response(void *fcsarg, 3237static void bfa_fcs_lport_ns_plogi_response(void *fcsarg,
3171 struct bfa_fcxp_s *fcxp, 3238 struct bfa_fcxp_s *fcxp,
@@ -3202,6 +3269,20 @@ static void bfa_fcs_lport_ns_gid_ft_response(void *fcsarg,
3202 u32 rsp_len, 3269 u32 rsp_len,
3203 u32 resid_len, 3270 u32 resid_len,
3204 struct fchs_s *rsp_fchs); 3271 struct fchs_s *rsp_fchs);
3272static void bfa_fcs_lport_ns_rnn_id_response(void *fcsarg,
3273 struct bfa_fcxp_s *fcxp,
3274 void *cbarg,
3275 bfa_status_t req_status,
3276 u32 rsp_len,
3277 u32 resid_len,
3278 struct fchs_s *rsp_fchs);
3279static void bfa_fcs_lport_ns_rsnn_nn_response(void *fcsarg,
3280 struct bfa_fcxp_s *fcxp,
3281 void *cbarg,
3282 bfa_status_t req_status,
3283 u32 rsp_len,
3284 u32 resid_len,
3285 struct fchs_s *rsp_fchs);
3205static void bfa_fcs_lport_ns_process_gidft_pids( 3286static void bfa_fcs_lport_ns_process_gidft_pids(
3206 struct bfa_fcs_lport_s *port, 3287 struct bfa_fcs_lport_s *port,
3207 u32 *pid_buf, u32 n_pids); 3288 u32 *pid_buf, u32 n_pids);
@@ -3226,6 +3307,8 @@ enum vport_ns_event {
3226 NSSM_EVENT_RFTID_SENT = 9, 3307 NSSM_EVENT_RFTID_SENT = 9,
3227 NSSM_EVENT_RFFID_SENT = 10, 3308 NSSM_EVENT_RFFID_SENT = 10,
3228 NSSM_EVENT_GIDFT_SENT = 11, 3309 NSSM_EVENT_GIDFT_SENT = 11,
3310 NSSM_EVENT_RNNID_SENT = 12,
3311 NSSM_EVENT_RSNN_NN_SENT = 13,
3229}; 3312};
3230 3313
3231static void bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns, 3314static void bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
@@ -3266,6 +3349,21 @@ static void bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
3266 enum vport_ns_event event); 3349 enum vport_ns_event event);
3267static void bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns, 3350static void bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
3268 enum vport_ns_event event); 3351 enum vport_ns_event event);
3352static void bfa_fcs_lport_ns_sm_sending_rnn_id(
3353 struct bfa_fcs_lport_ns_s *ns,
3354 enum vport_ns_event event);
3355static void bfa_fcs_lport_ns_sm_rnn_id(struct bfa_fcs_lport_ns_s *ns,
3356 enum vport_ns_event event);
3357static void bfa_fcs_lport_ns_sm_rnn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3358 enum vport_ns_event event);
3359static void bfa_fcs_lport_ns_sm_sending_rsnn_nn(
3360 struct bfa_fcs_lport_ns_s *ns,
3361 enum vport_ns_event event);
3362static void bfa_fcs_lport_ns_sm_rsnn_nn(struct bfa_fcs_lport_ns_s *ns,
3363 enum vport_ns_event event);
3364static void bfa_fcs_lport_ns_sm_rsnn_nn_retry(
3365 struct bfa_fcs_lport_ns_s *ns,
3366 enum vport_ns_event event);
3269/* 3367/*
3270 * Start in offline state - awaiting linkup 3368 * Start in offline state - awaiting linkup
3271 */ 3369 */
@@ -3333,8 +3431,9 @@ bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
3333 break; 3431 break;
3334 3432
3335 case NSSM_EVENT_RSP_OK: 3433 case NSSM_EVENT_RSP_OK:
3336 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id); 3434 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rnn_id);
3337 bfa_fcs_lport_ns_send_rspn_id(ns, NULL); 3435 ns->num_rnnid_retries = 0;
3436 bfa_fcs_lport_ns_send_rnn_id(ns, NULL);
3338 break; 3437 break;
3339 3438
3340 case NSSM_EVENT_PORT_OFFLINE: 3439 case NSSM_EVENT_PORT_OFFLINE:
@@ -3374,6 +3473,176 @@ bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
3374} 3473}
3375 3474
3376static void 3475static void
3476bfa_fcs_lport_ns_sm_sending_rnn_id(struct bfa_fcs_lport_ns_s *ns,
3477 enum vport_ns_event event)
3478{
3479 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3480 bfa_trc(ns->port->fcs, event);
3481
3482 switch (event) {
3483 case NSSM_EVENT_RNNID_SENT:
3484 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rnn_id);
3485 break;
3486
3487 case NSSM_EVENT_PORT_OFFLINE:
3488 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3489 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3490 &ns->fcxp_wqe);
3491 break;
3492 default:
3493 bfa_sm_fault(ns->port->fcs, event);
3494 }
3495}
3496
3497static void
3498bfa_fcs_lport_ns_sm_rnn_id(struct bfa_fcs_lport_ns_s *ns,
3499 enum vport_ns_event event)
3500{
3501 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3502 bfa_trc(ns->port->fcs, event);
3503
3504 switch (event) {
3505 case NSSM_EVENT_RSP_OK:
3506 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rsnn_nn);
3507 ns->num_rnnid_retries = 0;
3508 ns->num_rsnn_nn_retries = 0;
3509 bfa_fcs_lport_ns_send_rsnn_nn(ns, NULL);
3510 break;
3511
3512 case NSSM_EVENT_RSP_ERROR:
3513 if (ns->num_rnnid_retries < BFA_FCS_MAX_NS_RETRIES) {
3514 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rnn_id_retry);
3515 ns->port->stats.ns_retries++;
3516 ns->num_rnnid_retries++;
3517 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3518 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3519 BFA_FCS_RETRY_TIMEOUT);
3520 } else {
3521 bfa_sm_set_state(ns,
3522 bfa_fcs_lport_ns_sm_sending_rspn_id);
3523 bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
3524 }
3525 break;
3526
3527 case NSSM_EVENT_PORT_OFFLINE:
3528 bfa_fcxp_discard(ns->fcxp);
3529 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3530 break;
3531
3532 default:
3533 bfa_sm_fault(ns->port->fcs, event);
3534 }
3535}
3536
3537static void
3538bfa_fcs_lport_ns_sm_rnn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3539 enum vport_ns_event event)
3540{
3541 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3542 bfa_trc(ns->port->fcs, event);
3543
3544 switch (event) {
3545 case NSSM_EVENT_TIMEOUT:
3546 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rnn_id);
3547 bfa_fcs_lport_ns_send_rnn_id(ns, NULL);
3548 break;
3549
3550 case NSSM_EVENT_PORT_OFFLINE:
3551 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3552 bfa_timer_stop(&ns->timer);
3553 break;
3554
3555 default:
3556 bfa_sm_fault(ns->port->fcs, event);
3557 }
3558}
3559
3560static void
3561bfa_fcs_lport_ns_sm_sending_rsnn_nn(struct bfa_fcs_lport_ns_s *ns,
3562 enum vport_ns_event event)
3563{
3564 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3565 bfa_trc(ns->port->fcs, event);
3566
3567 switch (event) {
3568 case NSSM_EVENT_RSNN_NN_SENT:
3569 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rsnn_nn);
3570 break;
3571
3572 case NSSM_EVENT_PORT_OFFLINE:
3573 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3574 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3575 &ns->fcxp_wqe);
3576 break;
3577
3578 default:
3579 bfa_sm_fault(ns->port->fcs, event);
3580 }
3581}
3582
3583static void
3584bfa_fcs_lport_ns_sm_rsnn_nn(struct bfa_fcs_lport_ns_s *ns,
3585 enum vport_ns_event event)
3586{
3587 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3588 bfa_trc(ns->port->fcs, event);
3589
3590 switch (event) {
3591 case NSSM_EVENT_RSP_OK:
3592 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
3593 ns->num_rsnn_nn_retries = 0;
3594 bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
3595 break;
3596
3597 case NSSM_EVENT_RSP_ERROR:
3598 if (ns->num_rsnn_nn_retries < BFA_FCS_MAX_NS_RETRIES) {
3599 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rsnn_nn_retry);
3600 ns->port->stats.ns_retries++;
3601 ns->num_rsnn_nn_retries++;
3602 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3603 &ns->timer, bfa_fcs_lport_ns_timeout,
3604 ns, BFA_FCS_RETRY_TIMEOUT);
3605 } else {
3606 bfa_sm_set_state(ns,
3607 bfa_fcs_lport_ns_sm_sending_rspn_id);
3608 bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
3609 }
3610 break;
3611
3612 case NSSM_EVENT_PORT_OFFLINE:
3613 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3614 bfa_fcxp_discard(ns->fcxp);
3615 break;
3616
3617 default:
3618 bfa_sm_fault(ns->port->fcs, event);
3619 }
3620}
3621
3622static void
3623bfa_fcs_lport_ns_sm_rsnn_nn_retry(struct bfa_fcs_lport_ns_s *ns,
3624 enum vport_ns_event event)
3625{
3626 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3627 bfa_trc(ns->port->fcs, event);
3628
3629 switch (event) {
3630 case NSSM_EVENT_TIMEOUT:
3631 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rsnn_nn);
3632 bfa_fcs_lport_ns_send_rsnn_nn(ns, NULL);
3633 break;
3634
3635 case NSSM_EVENT_PORT_OFFLINE:
3636 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3637 bfa_timer_stop(&ns->timer);
3638 break;
3639
3640 default:
3641 bfa_sm_fault(ns->port->fcs, event);
3642 }
3643}
3644
3645static void
3377bfa_fcs_lport_ns_sm_sending_rspn_id(struct bfa_fcs_lport_ns_s *ns, 3646bfa_fcs_lport_ns_sm_sending_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3378 enum vport_ns_event event) 3647 enum vport_ns_event event)
3379{ 3648{
@@ -3770,11 +4039,12 @@ bfa_fcs_lport_ns_send_plogi(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3770 4039
3771 bfa_trc(port->fcs, port->pid); 4040 bfa_trc(port->fcs, port->pid);
3772 4041
3773 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 4042 fcxp = fcxp_alloced ? fcxp_alloced :
4043 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
3774 if (!fcxp) { 4044 if (!fcxp) {
3775 port->stats.ns_plogi_alloc_wait++; 4045 port->stats.ns_plogi_alloc_wait++;
3776 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, 4046 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3777 bfa_fcs_lport_ns_send_plogi, ns); 4047 bfa_fcs_lport_ns_send_plogi, ns, BFA_TRUE);
3778 return; 4048 return;
3779 } 4049 }
3780 ns->fcxp = fcxp; 4050 ns->fcxp = fcxp;
@@ -3853,6 +4123,162 @@ bfa_fcs_lport_ns_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3853} 4123}
3854 4124
3855/* 4125/*
4126 * Register node name for port_id
4127 */
4128static void
4129bfa_fcs_lport_ns_send_rnn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4130{
4131 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
4132 struct bfa_fcs_lport_s *port = ns->port;
4133 struct fchs_s fchs;
4134 int len;
4135 struct bfa_fcxp_s *fcxp;
4136
4137 bfa_trc(port->fcs, port->port_cfg.pwwn);
4138
4139 fcxp = fcxp_alloced ? fcxp_alloced :
4140 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4141 if (!fcxp) {
4142 port->stats.ns_rnnid_alloc_wait++;
4143 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4144 bfa_fcs_lport_ns_send_rnn_id, ns, BFA_TRUE);
4145 return;
4146 }
4147
4148 ns->fcxp = fcxp;
4149
4150 len = fc_rnnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4151 bfa_fcs_lport_get_fcid(port),
4152 bfa_fcs_lport_get_fcid(port),
4153 bfa_fcs_lport_get_nwwn(port));
4154
4155 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4156 FC_CLASS_3, len, &fchs,
4157 bfa_fcs_lport_ns_rnn_id_response, (void *)ns,
4158 FC_MAX_PDUSZ, FC_FCCT_TOV);
4159
4160 port->stats.ns_rnnid_sent++;
4161 bfa_sm_send_event(ns, NSSM_EVENT_RNNID_SENT);
4162}
4163
4164static void
4165bfa_fcs_lport_ns_rnn_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4166 void *cbarg, bfa_status_t req_status,
4167 u32 rsp_len, u32 resid_len,
4168 struct fchs_s *rsp_fchs)
4169
4170{
4171 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4172 struct bfa_fcs_lport_s *port = ns->port;
4173 struct ct_hdr_s *cthdr = NULL;
4174
4175 bfa_trc(port->fcs, port->port_cfg.pwwn);
4176
4177 /*
4178 * Sanity Checks
4179 */
4180 if (req_status != BFA_STATUS_OK) {
4181 bfa_trc(port->fcs, req_status);
4182 port->stats.ns_rnnid_rsp_err++;
4183 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4184 return;
4185 }
4186
4187 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
4188 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
4189
4190 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
4191 port->stats.ns_rnnid_accepts++;
4192 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4193 return;
4194 }
4195
4196 port->stats.ns_rnnid_rejects++;
4197 bfa_trc(port->fcs, cthdr->reason_code);
4198 bfa_trc(port->fcs, cthdr->exp_code);
4199 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4200}
4201
4202/*
4203 * Register the symbolic node name for a given node name.
4204 */
4205static void
4206bfa_fcs_lport_ns_send_rsnn_nn(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4207{
4208 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
4209 struct bfa_fcs_lport_s *port = ns->port;
4210 struct fchs_s fchs;
4211 int len;
4212 struct bfa_fcxp_s *fcxp;
4213 u8 *nsymbl;
4214
4215 bfa_trc(port->fcs, port->port_cfg.pwwn);
4216
4217 fcxp = fcxp_alloced ? fcxp_alloced :
4218 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4219 if (!fcxp) {
4220 port->stats.ns_rsnn_nn_alloc_wait++;
4221 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4222 bfa_fcs_lport_ns_send_rsnn_nn, ns, BFA_TRUE);
4223 return;
4224 }
4225 ns->fcxp = fcxp;
4226
4227 nsymbl = (u8 *) &(bfa_fcs_lport_get_nsym_name(
4228 bfa_fcs_get_base_port(port->fcs)));
4229
4230 len = fc_rsnn_nn_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4231 bfa_fcs_lport_get_fcid(port),
4232 bfa_fcs_lport_get_nwwn(port), nsymbl);
4233
4234 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4235 FC_CLASS_3, len, &fchs,
4236 bfa_fcs_lport_ns_rsnn_nn_response, (void *)ns,
4237 FC_MAX_PDUSZ, FC_FCCT_TOV);
4238
4239 port->stats.ns_rsnn_nn_sent++;
4240
4241 bfa_sm_send_event(ns, NSSM_EVENT_RSNN_NN_SENT);
4242}
4243
4244static void
4245bfa_fcs_lport_ns_rsnn_nn_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4246 void *cbarg, bfa_status_t req_status,
4247 u32 rsp_len, u32 resid_len,
4248 struct fchs_s *rsp_fchs)
4249{
4250 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4251 struct bfa_fcs_lport_s *port = ns->port;
4252 struct ct_hdr_s *cthdr = NULL;
4253
4254 bfa_trc(port->fcs, port->port_cfg.pwwn);
4255
4256 /*
4257 * Sanity Checks
4258 */
4259 if (req_status != BFA_STATUS_OK) {
4260 bfa_trc(port->fcs, req_status);
4261 port->stats.ns_rsnn_nn_rsp_err++;
4262 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4263 return;
4264 }
4265
4266 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
4267 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
4268
4269 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
4270 port->stats.ns_rsnn_nn_accepts++;
4271 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4272 return;
4273 }
4274
4275 port->stats.ns_rsnn_nn_rejects++;
4276 bfa_trc(port->fcs, cthdr->reason_code);
4277 bfa_trc(port->fcs, cthdr->exp_code);
4278 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4279}
4280
4281/*
3856 * Register the symbolic port name. 4282 * Register the symbolic port name.
3857 */ 4283 */
3858static void 4284static void
@@ -3870,11 +4296,12 @@ bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3870 4296
3871 bfa_trc(port->fcs, port->port_cfg.pwwn); 4297 bfa_trc(port->fcs, port->port_cfg.pwwn);
3872 4298
3873 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 4299 fcxp = fcxp_alloced ? fcxp_alloced :
4300 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
3874 if (!fcxp) { 4301 if (!fcxp) {
3875 port->stats.ns_rspnid_alloc_wait++; 4302 port->stats.ns_rspnid_alloc_wait++;
3876 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, 4303 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3877 bfa_fcs_lport_ns_send_rspn_id, ns); 4304 bfa_fcs_lport_ns_send_rspn_id, ns, BFA_TRUE);
3878 return; 4305 return;
3879 } 4306 }
3880 ns->fcxp = fcxp; 4307 ns->fcxp = fcxp;
@@ -3971,11 +4398,12 @@ bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3971 4398
3972 bfa_trc(port->fcs, port->port_cfg.pwwn); 4399 bfa_trc(port->fcs, port->port_cfg.pwwn);
3973 4400
3974 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 4401 fcxp = fcxp_alloced ? fcxp_alloced :
4402 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
3975 if (!fcxp) { 4403 if (!fcxp) {
3976 port->stats.ns_rftid_alloc_wait++; 4404 port->stats.ns_rftid_alloc_wait++;
3977 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, 4405 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3978 bfa_fcs_lport_ns_send_rft_id, ns); 4406 bfa_fcs_lport_ns_send_rft_id, ns, BFA_TRUE);
3979 return; 4407 return;
3980 } 4408 }
3981 ns->fcxp = fcxp; 4409 ns->fcxp = fcxp;
@@ -4044,11 +4472,12 @@ bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4044 4472
4045 bfa_trc(port->fcs, port->port_cfg.pwwn); 4473 bfa_trc(port->fcs, port->port_cfg.pwwn);
4046 4474
4047 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 4475 fcxp = fcxp_alloced ? fcxp_alloced :
4476 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4048 if (!fcxp) { 4477 if (!fcxp) {
4049 port->stats.ns_rffid_alloc_wait++; 4478 port->stats.ns_rffid_alloc_wait++;
4050 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, 4479 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4051 bfa_fcs_lport_ns_send_rff_id, ns); 4480 bfa_fcs_lport_ns_send_rff_id, ns, BFA_TRUE);
4052 return; 4481 return;
4053 } 4482 }
4054 ns->fcxp = fcxp; 4483 ns->fcxp = fcxp;
@@ -4127,11 +4556,12 @@ bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4127 4556
4128 bfa_trc(port->fcs, port->pid); 4557 bfa_trc(port->fcs, port->pid);
4129 4558
4130 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 4559 fcxp = fcxp_alloced ? fcxp_alloced :
4560 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4131 if (!fcxp) { 4561 if (!fcxp) {
4132 port->stats.ns_gidft_alloc_wait++; 4562 port->stats.ns_gidft_alloc_wait++;
4133 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, 4563 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4134 bfa_fcs_lport_ns_send_gid_ft, ns); 4564 bfa_fcs_lport_ns_send_gid_ft, ns, BFA_TRUE);
4135 return; 4565 return;
4136 } 4566 }
4137 ns->fcxp = fcxp; 4567 ns->fcxp = fcxp;
@@ -4261,6 +4691,10 @@ bfa_fcs_lport_ns_process_gidft_pids(struct bfa_fcs_lport_s *port, u32 *pid_buf,
4261 struct fcgs_gidft_resp_s *gidft_entry; 4691 struct fcgs_gidft_resp_s *gidft_entry;
4262 struct bfa_fcs_rport_s *rport; 4692 struct bfa_fcs_rport_s *rport;
4263 u32 ii; 4693 u32 ii;
4694 struct bfa_fcs_fabric_s *fabric = port->fabric;
4695 struct bfa_fcs_vport_s *vport;
4696 struct list_head *qe;
4697 u8 found = 0;
4264 4698
4265 for (ii = 0; ii < n_pids; ii++) { 4699 for (ii = 0; ii < n_pids; ii++) {
4266 gidft_entry = (struct fcgs_gidft_resp_s *) &pid_buf[ii]; 4700 gidft_entry = (struct fcgs_gidft_resp_s *) &pid_buf[ii];
@@ -4269,6 +4703,29 @@ bfa_fcs_lport_ns_process_gidft_pids(struct bfa_fcs_lport_s *port, u32 *pid_buf,
4269 continue; 4703 continue;
4270 4704
4271 /* 4705 /*
4706 * Ignore PID if it is of base port
4707 * (Avoid vports discovering base port as remote port)
4708 */
4709 if (gidft_entry->pid == fabric->bport.pid)
4710 continue;
4711
4712 /*
4713 * Ignore PID if it is of vport created on the same base port
4714 * (Avoid vport discovering every other vport created on the
4715 * same port as remote port)
4716 */
4717 list_for_each(qe, &fabric->vport_q) {
4718 vport = (struct bfa_fcs_vport_s *) qe;
4719 if (vport->lport.pid == gidft_entry->pid)
4720 found = 1;
4721 }
4722
4723 if (found) {
4724 found = 0;
4725 continue;
4726 }
4727
4728 /*
4272 * Check if this rport already exists 4729 * Check if this rport already exists
4273 */ 4730 */
4274 rport = bfa_fcs_lport_get_rport_by_pid(port, gidft_entry->pid); 4731 rport = bfa_fcs_lport_get_rport_by_pid(port, gidft_entry->pid);
@@ -4335,7 +4792,8 @@ bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s *port)
4335 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port); 4792 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4336 4793
4337 bfa_trc(port->fcs, port->pid); 4794 bfa_trc(port->fcs, port->pid);
4338 bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY); 4795 if (bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_online))
4796 bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY);
4339} 4797}
4340 4798
4341static void 4799static void
@@ -4355,6 +4813,70 @@ bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port)
4355 } 4813 }
4356} 4814}
4357 4815
4816void
4817bfa_fcs_lport_ns_util_send_rspn_id(void *cbarg, struct bfa_fcxp_s *fcxp_alloced)
4818{
4819 struct bfa_fcs_lport_ns_s *ns = cbarg;
4820 struct bfa_fcs_lport_s *port = ns->port;
4821 struct fchs_s fchs;
4822 struct bfa_fcxp_s *fcxp;
4823 u8 symbl[256];
4824 u8 *psymbl = &symbl[0];
4825 int len;
4826
4827 if (!bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online))
4828 return;
4829
4830 /* Avoid sending RSPN in the following states. */
4831 if (bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_offline) ||
4832 bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi_sending) ||
4833 bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi) ||
4834 bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi_retry) ||
4835 bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_rspn_id_retry))
4836 return;
4837
4838 memset(symbl, 0, sizeof(symbl));
4839 bfa_trc(port->fcs, port->port_cfg.pwwn);
4840
4841 fcxp = fcxp_alloced ? fcxp_alloced :
4842 bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
4843 if (!fcxp) {
4844 port->stats.ns_rspnid_alloc_wait++;
4845 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4846 bfa_fcs_lport_ns_util_send_rspn_id, ns, BFA_FALSE);
4847 return;
4848 }
4849
4850 ns->fcxp = fcxp;
4851
4852 if (port->vport) {
4853 /*
4854 * For Vports, we append the vport's port symbolic name
4855 * to that of the base port.
4856 */
4857 strncpy((char *)psymbl, (char *)&(bfa_fcs_lport_get_psym_name
4858 (bfa_fcs_get_base_port(port->fcs))),
4859 strlen((char *)&bfa_fcs_lport_get_psym_name(
4860 bfa_fcs_get_base_port(port->fcs))));
4861
4862 /* Ensure we have a null terminating string. */
4863 ((char *)psymbl)[strlen((char *)&bfa_fcs_lport_get_psym_name(
4864 bfa_fcs_get_base_port(port->fcs)))] = 0;
4865
4866 strncat((char *)psymbl,
4867 (char *)&(bfa_fcs_lport_get_psym_name(port)),
4868 strlen((char *)&bfa_fcs_lport_get_psym_name(port)));
4869 }
4870
4871 len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4872 bfa_fcs_lport_get_fcid(port), 0, psymbl);
4873
4874 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4875 FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
4876
4877 port->stats.ns_rspnid_sent++;
4878}
4879
4358/* 4880/*
4359 * FCS SCN 4881 * FCS SCN
4360 */ 4882 */
@@ -4529,10 +5051,11 @@ bfa_fcs_lport_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4529 bfa_trc(port->fcs, port->pid); 5051 bfa_trc(port->fcs, port->pid);
4530 bfa_trc(port->fcs, port->port_cfg.pwwn); 5052 bfa_trc(port->fcs, port->port_cfg.pwwn);
4531 5053
4532 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 5054 fcxp = fcxp_alloced ? fcxp_alloced :
5055 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4533 if (!fcxp) { 5056 if (!fcxp) {
4534 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &scn->fcxp_wqe, 5057 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &scn->fcxp_wqe,
4535 bfa_fcs_lport_scn_send_scr, scn); 5058 bfa_fcs_lport_scn_send_scr, scn, BFA_TRUE);
4536 return; 5059 return;
4537 } 5060 }
4538 scn->fcxp = fcxp; 5061 scn->fcxp = fcxp;
@@ -4614,7 +5137,7 @@ bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
4614 5137
4615 bfa_trc(port->fcs, rx_fchs->s_id); 5138 bfa_trc(port->fcs, rx_fchs->s_id);
4616 5139
4617 fcxp = bfa_fcs_fcxp_alloc(port->fcs); 5140 fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
4618 if (!fcxp) 5141 if (!fcxp)
4619 return; 5142 return;
4620 5143
@@ -4688,14 +5211,33 @@ static void
4688bfa_fcs_lport_scn_portid_rscn(struct bfa_fcs_lport_s *port, u32 rpid) 5211bfa_fcs_lport_scn_portid_rscn(struct bfa_fcs_lport_s *port, u32 rpid)
4689{ 5212{
4690 struct bfa_fcs_rport_s *rport; 5213 struct bfa_fcs_rport_s *rport;
5214 struct bfa_fcs_fabric_s *fabric = port->fabric;
5215 struct bfa_fcs_vport_s *vport;
5216 struct list_head *qe;
4691 5217
4692 bfa_trc(port->fcs, rpid); 5218 bfa_trc(port->fcs, rpid);
4693 5219
4694 /* 5220 /*
5221 * Ignore PID if it is of base port or of vports created on the
5222 * same base port. It is to avoid vports discovering base port or
5223 * other vports created on same base port as remote port
5224 */
5225 if (rpid == fabric->bport.pid)
5226 return;
5227
5228 list_for_each(qe, &fabric->vport_q) {
5229 vport = (struct bfa_fcs_vport_s *) qe;
5230 if (vport->lport.pid == rpid)
5231 return;
5232 }
5233 /*
4695 * If this is an unknown device, then it just came online. 5234 * If this is an unknown device, then it just came online.
4696 * Otherwise let rport handle the RSCN event. 5235 * Otherwise let rport handle the RSCN event.
4697 */ 5236 */
4698 rport = bfa_fcs_lport_get_rport_by_pid(port, rpid); 5237 rport = bfa_fcs_lport_get_rport_by_pid(port, rpid);
5238 if (!rport)
5239 rport = bfa_fcs_lport_get_rport_by_old_pid(port, rpid);
5240
4699 if (rport == NULL) { 5241 if (rport == NULL) {
4700 /* 5242 /*
4701 * If min cfg mode is enabled, we donot need to 5243 * If min cfg mode is enabled, we donot need to
@@ -4888,15 +5430,15 @@ bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn, int index,
4888} 5430}
4889 5431
4890void 5432void
4891bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port, 5433bfa_fcs_lport_get_rport_quals(struct bfa_fcs_lport_s *port,
4892 wwn_t rport_wwns[], int *nrports) 5434 struct bfa_rport_qualifier_s rports[], int *nrports)
4893{ 5435{
4894 struct list_head *qh, *qe; 5436 struct list_head *qh, *qe;
4895 struct bfa_fcs_rport_s *rport = NULL; 5437 struct bfa_fcs_rport_s *rport = NULL;
4896 int i; 5438 int i;
4897 struct bfa_fcs_s *fcs; 5439 struct bfa_fcs_s *fcs;
4898 5440
4899 if (port == NULL || rport_wwns == NULL || *nrports == 0) 5441 if (port == NULL || rports == NULL || *nrports == 0)
4900 return; 5442 return;
4901 5443
4902 fcs = port->fcs; 5444 fcs = port->fcs;
@@ -4916,7 +5458,13 @@ bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port,
4916 continue; 5458 continue;
4917 } 5459 }
4918 5460
4919 rport_wwns[i] = rport->pwwn; 5461 if (!rport->pwwn && !rport->pid) {
5462 qe = bfa_q_next(qe);
5463 continue;
5464 }
5465
5466 rports[i].pwwn = rport->pwwn;
5467 rports[i].pid = rport->pid;
4920 5468
4921 i++; 5469 i++;
4922 qe = bfa_q_next(qe); 5470 qe = bfa_q_next(qe);
@@ -5760,6 +6308,16 @@ bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport)
5760{ 6308{
5761 vport->vport_stats.fab_cleanup++; 6309 vport->vport_stats.fab_cleanup++;
5762} 6310}
6311
6312/*
6313 * Stop notification from fabric SM. To be invoked from within FCS.
6314 */
6315void
6316bfa_fcs_vport_fcs_stop(struct bfa_fcs_vport_s *vport)
6317{
6318 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP);
6319}
6320
5763/* 6321/*
5764 * delete notification from fabric SM. To be invoked from within FCS. 6322 * delete notification from fabric SM. To be invoked from within FCS.
5765 */ 6323 */
diff --git a/drivers/scsi/bfa/bfa_fcs_rport.c b/drivers/scsi/bfa/bfa_fcs_rport.c
index fe0463a1db0..cc43b2a58ce 100644
--- a/drivers/scsi/bfa/bfa_fcs_rport.c
+++ b/drivers/scsi/bfa/bfa_fcs_rport.c
@@ -30,14 +30,22 @@ static u32
30bfa_fcs_rport_del_timeout = BFA_FCS_RPORT_DEF_DEL_TIMEOUT * 1000; 30bfa_fcs_rport_del_timeout = BFA_FCS_RPORT_DEF_DEL_TIMEOUT * 1000;
31 /* In millisecs */ 31 /* In millisecs */
32/* 32/*
33 * bfa_fcs_rport_max_logins is max count of bfa_fcs_rports
34 * whereas DEF_CFG_NUM_RPORTS is max count of bfa_rports
35 */
36static u32 bfa_fcs_rport_max_logins = BFA_FCS_MAX_RPORT_LOGINS;
37
38/*
33 * forward declarations 39 * forward declarations
34 */ 40 */
35static struct bfa_fcs_rport_s *bfa_fcs_rport_alloc( 41static struct bfa_fcs_rport_s *bfa_fcs_rport_alloc(
36 struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid); 42 struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid);
37static void bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport); 43static void bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport);
38static void bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport); 44static void bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport);
39static void bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport); 45static void bfa_fcs_rport_fcs_online_action(struct bfa_fcs_rport_s *rport);
40static void bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport); 46static void bfa_fcs_rport_hal_online_action(struct bfa_fcs_rport_s *rport);
47static void bfa_fcs_rport_fcs_offline_action(struct bfa_fcs_rport_s *rport);
48static void bfa_fcs_rport_hal_offline_action(struct bfa_fcs_rport_s *rport);
41static void bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, 49static void bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport,
42 struct fc_logi_s *plogi); 50 struct fc_logi_s *plogi);
43static void bfa_fcs_rport_timeout(void *arg); 51static void bfa_fcs_rport_timeout(void *arg);
@@ -76,6 +84,7 @@ static void bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport,
76static void bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport, 84static void bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
77 struct fchs_s *rx_fchs, u16 len); 85 struct fchs_s *rx_fchs, u16 len);
78static void bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport); 86static void bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport);
87static void bfa_fcs_rport_hal_offline(struct bfa_fcs_rport_s *rport);
79 88
80static void bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport, 89static void bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport,
81 enum rport_event event); 90 enum rport_event event);
@@ -87,6 +96,8 @@ static void bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
87 enum rport_event event); 96 enum rport_event event);
88static void bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, 97static void bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport,
89 enum rport_event event); 98 enum rport_event event);
99static void bfa_fcs_rport_sm_fc4_fcs_online(struct bfa_fcs_rport_s *rport,
100 enum rport_event event);
90static void bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport, 101static void bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
91 enum rport_event event); 102 enum rport_event event);
92static void bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, 103static void bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport,
@@ -123,6 +134,10 @@ static void bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
123 enum rport_event event); 134 enum rport_event event);
124static void bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport, 135static void bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
125 enum rport_event event); 136 enum rport_event event);
137static void bfa_fcs_rport_sm_fc4_off_delete(struct bfa_fcs_rport_s *rport,
138 enum rport_event event);
139static void bfa_fcs_rport_sm_delete_pending(struct bfa_fcs_rport_s *rport,
140 enum rport_event event);
126 141
127static struct bfa_sm_table_s rport_sm_table[] = { 142static struct bfa_sm_table_s rport_sm_table[] = {
128 {BFA_SM(bfa_fcs_rport_sm_uninit), BFA_RPORT_UNINIT}, 143 {BFA_SM(bfa_fcs_rport_sm_uninit), BFA_RPORT_UNINIT},
@@ -130,6 +145,7 @@ static struct bfa_sm_table_s rport_sm_table[] = {
130 {BFA_SM(bfa_fcs_rport_sm_plogiacc_sending), BFA_RPORT_ONLINE}, 145 {BFA_SM(bfa_fcs_rport_sm_plogiacc_sending), BFA_RPORT_ONLINE},
131 {BFA_SM(bfa_fcs_rport_sm_plogi_retry), BFA_RPORT_PLOGI_RETRY}, 146 {BFA_SM(bfa_fcs_rport_sm_plogi_retry), BFA_RPORT_PLOGI_RETRY},
132 {BFA_SM(bfa_fcs_rport_sm_plogi), BFA_RPORT_PLOGI}, 147 {BFA_SM(bfa_fcs_rport_sm_plogi), BFA_RPORT_PLOGI},
148 {BFA_SM(bfa_fcs_rport_sm_fc4_fcs_online), BFA_RPORT_ONLINE},
133 {BFA_SM(bfa_fcs_rport_sm_hal_online), BFA_RPORT_ONLINE}, 149 {BFA_SM(bfa_fcs_rport_sm_hal_online), BFA_RPORT_ONLINE},
134 {BFA_SM(bfa_fcs_rport_sm_online), BFA_RPORT_ONLINE}, 150 {BFA_SM(bfa_fcs_rport_sm_online), BFA_RPORT_ONLINE},
135 {BFA_SM(bfa_fcs_rport_sm_nsquery_sending), BFA_RPORT_NSQUERY}, 151 {BFA_SM(bfa_fcs_rport_sm_nsquery_sending), BFA_RPORT_NSQUERY},
@@ -167,8 +183,8 @@ bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport, enum rport_event event)
167 break; 183 break;
168 184
169 case RPSM_EVENT_PLOGI_RCVD: 185 case RPSM_EVENT_PLOGI_RCVD:
170 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending); 186 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
171 bfa_fcs_rport_send_plogiacc(rport, NULL); 187 bfa_fcs_rport_fcs_online_action(rport);
172 break; 188 break;
173 189
174 case RPSM_EVENT_PLOGI_COMP: 190 case RPSM_EVENT_PLOGI_COMP:
@@ -252,8 +268,8 @@ bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
252 268
253 switch (event) { 269 switch (event) {
254 case RPSM_EVENT_FCXP_SENT: 270 case RPSM_EVENT_FCXP_SENT:
255 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); 271 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
256 bfa_fcs_rport_hal_online(rport); 272 bfa_fcs_rport_fcs_online_action(rport);
257 break; 273 break;
258 274
259 case RPSM_EVENT_DELETE: 275 case RPSM_EVENT_DELETE:
@@ -348,9 +364,9 @@ bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
348 break; 364 break;
349 365
350 case RPSM_EVENT_PLOGI_COMP: 366 case RPSM_EVENT_PLOGI_COMP:
351 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); 367 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
352 bfa_timer_stop(&rport->timer); 368 bfa_timer_stop(&rport->timer);
353 bfa_fcs_rport_hal_online(rport); 369 bfa_fcs_rport_fcs_online_action(rport);
354 break; 370 break;
355 371
356 default: 372 default:
@@ -370,9 +386,9 @@ bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
370 386
371 switch (event) { 387 switch (event) {
372 case RPSM_EVENT_ACCEPTED: 388 case RPSM_EVENT_ACCEPTED:
373 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); 389 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
374 rport->plogi_retries = 0; 390 rport->plogi_retries = 0;
375 bfa_fcs_rport_hal_online(rport); 391 bfa_fcs_rport_fcs_online_action(rport);
376 break; 392 break;
377 393
378 case RPSM_EVENT_LOGO_RCVD: 394 case RPSM_EVENT_LOGO_RCVD:
@@ -397,6 +413,7 @@ bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
397 BFA_FCS_RETRY_TIMEOUT); 413 BFA_FCS_RETRY_TIMEOUT);
398 } else { 414 } else {
399 bfa_stats(rport->port, rport_del_max_plogi_retry); 415 bfa_stats(rport->port, rport_del_max_plogi_retry);
416 rport->old_pid = rport->pid;
400 rport->pid = 0; 417 rport->pid = 0;
401 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); 418 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
402 bfa_timer_start(rport->fcs->bfa, &rport->timer, 419 bfa_timer_start(rport->fcs->bfa, &rport->timer,
@@ -443,13 +460,77 @@ bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
443 break; 460 break;
444 461
445 case RPSM_EVENT_PLOGI_COMP: 462 case RPSM_EVENT_PLOGI_COMP:
446 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); 463 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
447 bfa_fcxp_discard(rport->fcxp); 464 bfa_fcxp_discard(rport->fcxp);
448 bfa_fcs_rport_hal_online(rport); 465 bfa_fcs_rport_fcs_online_action(rport);
466 break;
467
468 default:
469 bfa_sm_fault(rport->fcs, event);
470 }
471}
472
473/*
474 * PLOGI is done. Await bfa_fcs_itnim to ascertain the scsi function
475 */
476static void
477bfa_fcs_rport_sm_fc4_fcs_online(struct bfa_fcs_rport_s *rport,
478 enum rport_event event)
479{
480 bfa_trc(rport->fcs, rport->pwwn);
481 bfa_trc(rport->fcs, rport->pid);
482 bfa_trc(rport->fcs, event);
483
484 switch (event) {
485 case RPSM_EVENT_FC4_FCS_ONLINE:
486 if (rport->scsi_function == BFA_RPORT_INITIATOR) {
487 if (!BFA_FCS_PID_IS_WKA(rport->pid))
488 bfa_fcs_rpf_rport_online(rport);
489 bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
490 break;
491 }
492
493 if (!rport->bfa_rport)
494 rport->bfa_rport =
495 bfa_rport_create(rport->fcs->bfa, rport);
496
497 if (rport->bfa_rport) {
498 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
499 bfa_fcs_rport_hal_online(rport);
500 } else {
501 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
502 bfa_fcs_rport_fcs_offline_action(rport);
503 }
504 break;
505
506 case RPSM_EVENT_PLOGI_RCVD:
507 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
508 rport->plogi_pending = BFA_TRUE;
509 bfa_fcs_rport_fcs_offline_action(rport);
510 break;
511
512 case RPSM_EVENT_PLOGI_COMP:
513 case RPSM_EVENT_LOGO_IMP:
514 case RPSM_EVENT_ADDRESS_CHANGE:
515 case RPSM_EVENT_SCN:
516 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
517 bfa_fcs_rport_fcs_offline_action(rport);
518 break;
519
520 case RPSM_EVENT_LOGO_RCVD:
521 case RPSM_EVENT_PRLO_RCVD:
522 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
523 bfa_fcs_rport_fcs_offline_action(rport);
524 break;
525
526 case RPSM_EVENT_DELETE:
527 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
528 bfa_fcs_rport_fcs_offline_action(rport);
449 break; 529 break;
450 530
451 default: 531 default:
452 bfa_sm_fault(rport->fcs, event); 532 bfa_sm_fault(rport->fcs, event);
533 break;
453 } 534 }
454} 535}
455 536
@@ -468,41 +549,34 @@ bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
468 switch (event) { 549 switch (event) {
469 case RPSM_EVENT_HCB_ONLINE: 550 case RPSM_EVENT_HCB_ONLINE:
470 bfa_sm_set_state(rport, bfa_fcs_rport_sm_online); 551 bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
471 bfa_fcs_rport_online_action(rport); 552 bfa_fcs_rport_hal_online_action(rport);
472 break; 553 break;
473 554
474 case RPSM_EVENT_PRLO_RCVD:
475 case RPSM_EVENT_PLOGI_COMP: 555 case RPSM_EVENT_PLOGI_COMP:
476 break; 556 break;
477 557
558 case RPSM_EVENT_PRLO_RCVD:
478 case RPSM_EVENT_LOGO_RCVD: 559 case RPSM_EVENT_LOGO_RCVD:
479 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv); 560 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
480 bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE); 561 bfa_fcs_rport_fcs_offline_action(rport);
481 break; 562 break;
482 563
564 case RPSM_EVENT_SCN:
483 case RPSM_EVENT_LOGO_IMP: 565 case RPSM_EVENT_LOGO_IMP:
484 case RPSM_EVENT_ADDRESS_CHANGE: 566 case RPSM_EVENT_ADDRESS_CHANGE:
485 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline); 567 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
486 bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE); 568 bfa_fcs_rport_fcs_offline_action(rport);
487 break; 569 break;
488 570
489 case RPSM_EVENT_PLOGI_RCVD: 571 case RPSM_EVENT_PLOGI_RCVD:
490 rport->plogi_pending = BFA_TRUE; 572 rport->plogi_pending = BFA_TRUE;
491 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline); 573 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
492 bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE); 574 bfa_fcs_rport_fcs_offline_action(rport);
493 break; 575 break;
494 576
495 case RPSM_EVENT_DELETE: 577 case RPSM_EVENT_DELETE:
496 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend); 578 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
497 bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE); 579 bfa_fcs_rport_fcs_offline_action(rport);
498 break;
499
500 case RPSM_EVENT_SCN:
501 /*
502 * @todo
503 * Ignore SCN - PLOGI just completed, FC-4 login should detect
504 * device failures.
505 */
506 break; 580 break;
507 581
508 default: 582 default:
@@ -537,18 +611,18 @@ bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)
537 case RPSM_EVENT_LOGO_IMP: 611 case RPSM_EVENT_LOGO_IMP:
538 case RPSM_EVENT_ADDRESS_CHANGE: 612 case RPSM_EVENT_ADDRESS_CHANGE:
539 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline); 613 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
540 bfa_fcs_rport_offline_action(rport); 614 bfa_fcs_rport_hal_offline_action(rport);
541 break; 615 break;
542 616
543 case RPSM_EVENT_DELETE: 617 case RPSM_EVENT_DELETE:
544 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend); 618 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
545 bfa_fcs_rport_offline_action(rport); 619 bfa_fcs_rport_hal_offline_action(rport);
546 break; 620 break;
547 621
548 case RPSM_EVENT_LOGO_RCVD: 622 case RPSM_EVENT_LOGO_RCVD:
549 case RPSM_EVENT_PRLO_RCVD: 623 case RPSM_EVENT_PRLO_RCVD:
550 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv); 624 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
551 bfa_fcs_rport_offline_action(rport); 625 bfa_fcs_rport_hal_offline_action(rport);
552 break; 626 break;
553 627
554 case RPSM_EVENT_PLOGI_COMP: 628 case RPSM_EVENT_PLOGI_COMP:
@@ -579,7 +653,7 @@ bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
579 case RPSM_EVENT_DELETE: 653 case RPSM_EVENT_DELETE:
580 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend); 654 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
581 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); 655 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
582 bfa_fcs_rport_offline_action(rport); 656 bfa_fcs_rport_hal_offline_action(rport);
583 break; 657 break;
584 658
585 case RPSM_EVENT_SCN: 659 case RPSM_EVENT_SCN:
@@ -592,24 +666,16 @@ bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
592 case RPSM_EVENT_PRLO_RCVD: 666 case RPSM_EVENT_PRLO_RCVD:
593 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv); 667 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
594 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); 668 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
595 bfa_fcs_rport_offline_action(rport); 669 bfa_fcs_rport_hal_offline_action(rport);
596 break; 670 break;
597 671
598 case RPSM_EVENT_LOGO_IMP: 672 case RPSM_EVENT_LOGO_IMP:
599 rport->pid = 0;
600 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
601 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
602 bfa_timer_start(rport->fcs->bfa, &rport->timer,
603 bfa_fcs_rport_timeout, rport,
604 bfa_fcs_rport_del_timeout);
605 break;
606
607 case RPSM_EVENT_PLOGI_RCVD: 673 case RPSM_EVENT_PLOGI_RCVD:
608 case RPSM_EVENT_ADDRESS_CHANGE: 674 case RPSM_EVENT_ADDRESS_CHANGE:
609 case RPSM_EVENT_PLOGI_COMP: 675 case RPSM_EVENT_PLOGI_COMP:
610 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline); 676 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
611 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); 677 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
612 bfa_fcs_rport_offline_action(rport); 678 bfa_fcs_rport_hal_offline_action(rport);
613 break; 679 break;
614 680
615 default: 681 default:
@@ -642,14 +708,14 @@ bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
642 bfa_fcs_rport_send_nsdisc(rport, NULL); 708 bfa_fcs_rport_send_nsdisc(rport, NULL);
643 } else { 709 } else {
644 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline); 710 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
645 bfa_fcs_rport_offline_action(rport); 711 bfa_fcs_rport_hal_offline_action(rport);
646 } 712 }
647 break; 713 break;
648 714
649 case RPSM_EVENT_DELETE: 715 case RPSM_EVENT_DELETE:
650 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend); 716 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
651 bfa_fcxp_discard(rport->fcxp); 717 bfa_fcxp_discard(rport->fcxp);
652 bfa_fcs_rport_offline_action(rport); 718 bfa_fcs_rport_hal_offline_action(rport);
653 break; 719 break;
654 720
655 case RPSM_EVENT_SCN: 721 case RPSM_EVENT_SCN:
@@ -659,7 +725,7 @@ bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
659 case RPSM_EVENT_PRLO_RCVD: 725 case RPSM_EVENT_PRLO_RCVD:
660 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv); 726 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
661 bfa_fcxp_discard(rport->fcxp); 727 bfa_fcxp_discard(rport->fcxp);
662 bfa_fcs_rport_offline_action(rport); 728 bfa_fcs_rport_hal_offline_action(rport);
663 break; 729 break;
664 730
665 case RPSM_EVENT_PLOGI_COMP: 731 case RPSM_EVENT_PLOGI_COMP:
@@ -668,7 +734,7 @@ bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
668 case RPSM_EVENT_LOGO_IMP: 734 case RPSM_EVENT_LOGO_IMP:
669 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline); 735 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
670 bfa_fcxp_discard(rport->fcxp); 736 bfa_fcxp_discard(rport->fcxp);
671 bfa_fcs_rport_offline_action(rport); 737 bfa_fcs_rport_hal_offline_action(rport);
672 break; 738 break;
673 739
674 default: 740 default:
@@ -696,21 +762,21 @@ bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
696 case RPSM_EVENT_DELETE: 762 case RPSM_EVENT_DELETE:
697 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend); 763 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
698 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); 764 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
699 bfa_fcs_rport_offline_action(rport); 765 bfa_fcs_rport_hal_offline_action(rport);
700 break; 766 break;
701 767
702 case RPSM_EVENT_LOGO_IMP: 768 case RPSM_EVENT_LOGO_IMP:
703 case RPSM_EVENT_ADDRESS_CHANGE: 769 case RPSM_EVENT_ADDRESS_CHANGE:
704 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline); 770 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
705 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); 771 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
706 bfa_fcs_rport_offline_action(rport); 772 bfa_fcs_rport_hal_offline_action(rport);
707 break; 773 break;
708 774
709 case RPSM_EVENT_LOGO_RCVD: 775 case RPSM_EVENT_LOGO_RCVD:
710 case RPSM_EVENT_PRLO_RCVD: 776 case RPSM_EVENT_PRLO_RCVD:
711 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv); 777 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
712 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); 778 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
713 bfa_fcs_rport_offline_action(rport); 779 bfa_fcs_rport_hal_offline_action(rport);
714 break; 780 break;
715 781
716 case RPSM_EVENT_SCN: 782 case RPSM_EVENT_SCN:
@@ -719,7 +785,7 @@ bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
719 case RPSM_EVENT_PLOGI_RCVD: 785 case RPSM_EVENT_PLOGI_RCVD:
720 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline); 786 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
721 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); 787 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
722 bfa_fcs_rport_offline_action(rport); 788 bfa_fcs_rport_hal_offline_action(rport);
723 break; 789 break;
724 790
725 default: 791 default:
@@ -756,13 +822,13 @@ bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event)
756 case RPSM_EVENT_FAILED: 822 case RPSM_EVENT_FAILED:
757 case RPSM_EVENT_ADDRESS_CHANGE: 823 case RPSM_EVENT_ADDRESS_CHANGE:
758 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline); 824 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
759 bfa_fcs_rport_offline_action(rport); 825 bfa_fcs_rport_hal_offline_action(rport);
760 break; 826 break;
761 827
762 case RPSM_EVENT_DELETE: 828 case RPSM_EVENT_DELETE:
763 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend); 829 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
764 bfa_fcxp_discard(rport->fcxp); 830 bfa_fcxp_discard(rport->fcxp);
765 bfa_fcs_rport_offline_action(rport); 831 bfa_fcs_rport_hal_offline_action(rport);
766 break; 832 break;
767 833
768 case RPSM_EVENT_SCN: 834 case RPSM_EVENT_SCN:
@@ -774,14 +840,14 @@ bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event)
774 case RPSM_EVENT_LOGO_IMP: 840 case RPSM_EVENT_LOGO_IMP:
775 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline); 841 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
776 bfa_fcxp_discard(rport->fcxp); 842 bfa_fcxp_discard(rport->fcxp);
777 bfa_fcs_rport_offline_action(rport); 843 bfa_fcs_rport_hal_offline_action(rport);
778 break; 844 break;
779 845
780 case RPSM_EVENT_LOGO_RCVD: 846 case RPSM_EVENT_LOGO_RCVD:
781 case RPSM_EVENT_PRLO_RCVD: 847 case RPSM_EVENT_PRLO_RCVD:
782 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv); 848 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
783 bfa_fcxp_discard(rport->fcxp); 849 bfa_fcxp_discard(rport->fcxp);
784 bfa_fcs_rport_offline_action(rport); 850 bfa_fcs_rport_hal_offline_action(rport);
785 break; 851 break;
786 852
787 default: 853 default:
@@ -803,13 +869,19 @@ bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
803 switch (event) { 869 switch (event) {
804 case RPSM_EVENT_FC4_OFFLINE: 870 case RPSM_EVENT_FC4_OFFLINE:
805 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv); 871 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);
806 bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE); 872 bfa_fcs_rport_hal_offline(rport);
807 break; 873 break;
808 874
809 case RPSM_EVENT_DELETE: 875 case RPSM_EVENT_DELETE:
810 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend); 876 if (rport->pid && (rport->prlo == BFA_TRUE))
877 bfa_fcs_rport_send_prlo_acc(rport);
878 if (rport->pid && (rport->prlo == BFA_FALSE))
879 bfa_fcs_rport_send_logo_acc(rport);
880
881 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_off_delete);
811 break; 882 break;
812 883
884 case RPSM_EVENT_HCB_ONLINE:
813 case RPSM_EVENT_LOGO_RCVD: 885 case RPSM_EVENT_LOGO_RCVD:
814 case RPSM_EVENT_PRLO_RCVD: 886 case RPSM_EVENT_PRLO_RCVD:
815 case RPSM_EVENT_ADDRESS_CHANGE: 887 case RPSM_EVENT_ADDRESS_CHANGE:
@@ -835,7 +907,20 @@ bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,
835 switch (event) { 907 switch (event) {
836 case RPSM_EVENT_FC4_OFFLINE: 908 case RPSM_EVENT_FC4_OFFLINE:
837 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend); 909 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
838 bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE); 910 bfa_fcs_rport_hal_offline(rport);
911 break;
912
913 case RPSM_EVENT_LOGO_RCVD:
914 bfa_fcs_rport_send_logo_acc(rport);
915 case RPSM_EVENT_PRLO_RCVD:
916 if (rport->prlo == BFA_TRUE)
917 bfa_fcs_rport_send_prlo_acc(rport);
918 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_off_delete);
919 break;
920
921 case RPSM_EVENT_HCB_ONLINE:
922 case RPSM_EVENT_DELETE:
923 /* Rport is being deleted */
839 break; 924 break;
840 925
841 default: 926 default:
@@ -857,13 +942,23 @@ bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
857 switch (event) { 942 switch (event) {
858 case RPSM_EVENT_FC4_OFFLINE: 943 case RPSM_EVENT_FC4_OFFLINE:
859 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline); 944 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
860 bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE); 945 bfa_fcs_rport_hal_offline(rport);
861 break; 946 break;
862 947
863 case RPSM_EVENT_SCN:
864 case RPSM_EVENT_LOGO_IMP:
865 case RPSM_EVENT_LOGO_RCVD: 948 case RPSM_EVENT_LOGO_RCVD:
949 /*
950 * Rport is going offline. Just ack the logo
951 */
952 bfa_fcs_rport_send_logo_acc(rport);
953 break;
954
866 case RPSM_EVENT_PRLO_RCVD: 955 case RPSM_EVENT_PRLO_RCVD:
956 bfa_fcs_rport_send_prlo_acc(rport);
957 break;
958
959 case RPSM_EVENT_HCB_ONLINE:
960 case RPSM_EVENT_SCN:
961 case RPSM_EVENT_LOGO_IMP:
867 case RPSM_EVENT_ADDRESS_CHANGE: 962 case RPSM_EVENT_ADDRESS_CHANGE:
868 /* 963 /*
869 * rport is already going offline. 964 * rport is already going offline.
@@ -907,24 +1002,23 @@ bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
907 */ 1002 */
908 1003
909 case RPSM_EVENT_ADDRESS_CHANGE: 1004 case RPSM_EVENT_ADDRESS_CHANGE:
910 if (bfa_fcs_lport_is_online(rport->port)) { 1005 if (!bfa_fcs_lport_is_online(rport->port)) {
911 if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
912 bfa_sm_set_state(rport,
913 bfa_fcs_rport_sm_nsdisc_sending);
914 rport->ns_retries = 0;
915 bfa_fcs_rport_send_nsdisc(rport, NULL);
916 } else {
917 bfa_sm_set_state(rport,
918 bfa_fcs_rport_sm_plogi_sending);
919 rport->plogi_retries = 0;
920 bfa_fcs_rport_send_plogi(rport, NULL);
921 }
922 } else {
923 rport->pid = 0; 1006 rport->pid = 0;
924 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); 1007 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
925 bfa_timer_start(rport->fcs->bfa, &rport->timer, 1008 bfa_timer_start(rport->fcs->bfa, &rport->timer,
926 bfa_fcs_rport_timeout, rport, 1009 bfa_fcs_rport_timeout, rport,
927 bfa_fcs_rport_del_timeout); 1010 bfa_fcs_rport_del_timeout);
1011 break;
1012 }
1013 if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
1014 bfa_sm_set_state(rport,
1015 bfa_fcs_rport_sm_nsdisc_sending);
1016 rport->ns_retries = 0;
1017 bfa_fcs_rport_send_nsdisc(rport, NULL);
1018 } else {
1019 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
1020 rport->plogi_retries = 0;
1021 bfa_fcs_rport_send_plogi(rport, NULL);
928 } 1022 }
929 break; 1023 break;
930 1024
@@ -1001,7 +1095,11 @@ bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
1001 break; 1095 break;
1002 1096
1003 case RPSM_EVENT_DELETE: 1097 case RPSM_EVENT_DELETE:
1004 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend); 1098 bfa_sm_set_state(rport, bfa_fcs_rport_sm_delete_pending);
1099 if (rport->pid && (rport->prlo == BFA_TRUE))
1100 bfa_fcs_rport_send_prlo_acc(rport);
1101 if (rport->pid && (rport->prlo == BFA_FALSE))
1102 bfa_fcs_rport_send_logo_acc(rport);
1005 break; 1103 break;
1006 1104
1007 case RPSM_EVENT_LOGO_IMP: 1105 case RPSM_EVENT_LOGO_IMP:
@@ -1040,7 +1138,14 @@ bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
1040 break; 1138 break;
1041 1139
1042 case RPSM_EVENT_LOGO_RCVD: 1140 case RPSM_EVENT_LOGO_RCVD:
1141 bfa_fcs_rport_send_logo_acc(rport);
1043 case RPSM_EVENT_PRLO_RCVD: 1142 case RPSM_EVENT_PRLO_RCVD:
1143 if (rport->prlo == BFA_TRUE)
1144 bfa_fcs_rport_send_prlo_acc(rport);
1145
1146 bfa_sm_set_state(rport, bfa_fcs_rport_sm_delete_pending);
1147 break;
1148
1044 case RPSM_EVENT_ADDRESS_CHANGE: 1149 case RPSM_EVENT_ADDRESS_CHANGE:
1045 break; 1150 break;
1046 1151
@@ -1072,7 +1177,11 @@ bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
1072 break; 1177 break;
1073 1178
1074 case RPSM_EVENT_LOGO_RCVD: 1179 case RPSM_EVENT_LOGO_RCVD:
1180 bfa_fcs_rport_send_logo_acc(rport);
1075 case RPSM_EVENT_PRLO_RCVD: 1181 case RPSM_EVENT_PRLO_RCVD:
1182 if (rport->prlo == BFA_TRUE)
1183 bfa_fcs_rport_send_prlo_acc(rport);
1184
1076 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); 1185 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1077 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); 1186 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1078 bfa_fcs_rport_free(rport); 1187 bfa_fcs_rport_free(rport);
@@ -1126,9 +1235,9 @@ bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)
1126 break; 1235 break;
1127 1236
1128 case RPSM_EVENT_PLOGI_COMP: 1237 case RPSM_EVENT_PLOGI_COMP:
1129 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); 1238 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
1130 bfa_timer_stop(&rport->timer); 1239 bfa_timer_stop(&rport->timer);
1131 bfa_fcs_rport_hal_online(rport); 1240 bfa_fcs_rport_fcs_online_action(rport);
1132 break; 1241 break;
1133 1242
1134 case RPSM_EVENT_PLOGI_SEND: 1243 case RPSM_EVENT_PLOGI_SEND:
@@ -1190,9 +1299,9 @@ bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
1190 break; 1299 break;
1191 1300
1192 case RPSM_EVENT_PLOGI_COMP: 1301 case RPSM_EVENT_PLOGI_COMP:
1193 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); 1302 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
1194 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); 1303 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1195 bfa_fcs_rport_hal_online(rport); 1304 bfa_fcs_rport_fcs_online_action(rport);
1196 break; 1305 break;
1197 1306
1198 default: 1307 default:
@@ -1254,9 +1363,9 @@ bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
1254 break; 1363 break;
1255 1364
1256 case RPSM_EVENT_PLOGI_COMP: 1365 case RPSM_EVENT_PLOGI_COMP:
1257 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); 1366 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
1258 bfa_timer_stop(&rport->timer); 1367 bfa_timer_stop(&rport->timer);
1259 bfa_fcs_rport_hal_online(rport); 1368 bfa_fcs_rport_fcs_online_action(rport);
1260 break; 1369 break;
1261 1370
1262 default: 1371 default:
@@ -1296,6 +1405,7 @@ bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
1296 bfa_fcs_rport_sm_nsdisc_sending); 1405 bfa_fcs_rport_sm_nsdisc_sending);
1297 bfa_fcs_rport_send_nsdisc(rport, NULL); 1406 bfa_fcs_rport_send_nsdisc(rport, NULL);
1298 } else { 1407 } else {
1408 rport->old_pid = rport->pid;
1299 rport->pid = 0; 1409 rport->pid = 0;
1300 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); 1410 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1301 bfa_timer_start(rport->fcs->bfa, &rport->timer, 1411 bfa_timer_start(rport->fcs->bfa, &rport->timer,
@@ -1343,9 +1453,9 @@ bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
1343 break; 1453 break;
1344 1454
1345 case RPSM_EVENT_PLOGI_COMP: 1455 case RPSM_EVENT_PLOGI_COMP:
1346 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); 1456 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
1347 bfa_fcxp_discard(rport->fcxp); 1457 bfa_fcxp_discard(rport->fcxp);
1348 bfa_fcs_rport_hal_online(rport); 1458 bfa_fcs_rport_fcs_online_action(rport);
1349 break; 1459 break;
1350 1460
1351 default: 1461 default:
@@ -1353,7 +1463,63 @@ bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
1353 } 1463 }
1354} 1464}
1355 1465
1466/*
1467 * Rport needs to be deleted
1468 * waiting for ITNIM clean up to finish
1469 */
1470static void
1471bfa_fcs_rport_sm_fc4_off_delete(struct bfa_fcs_rport_s *rport,
1472 enum rport_event event)
1473{
1474 bfa_trc(rport->fcs, rport->pwwn);
1475 bfa_trc(rport->fcs, rport->pid);
1476 bfa_trc(rport->fcs, event);
1356 1477
1478 switch (event) {
1479 case RPSM_EVENT_FC4_OFFLINE:
1480 bfa_sm_set_state(rport, bfa_fcs_rport_sm_delete_pending);
1481 bfa_fcs_rport_hal_offline(rport);
1482 break;
1483
1484 case RPSM_EVENT_DELETE:
1485 case RPSM_EVENT_PLOGI_RCVD:
1486 /* Ignore these events */
1487 break;
1488
1489 default:
1490 bfa_sm_fault(rport->fcs, event);
1491 break;
1492 }
1493}
1494
1495/*
1496 * RPort needs to be deleted
1497 * waiting for BFA/FW to finish current processing
1498 */
1499static void
1500bfa_fcs_rport_sm_delete_pending(struct bfa_fcs_rport_s *rport,
1501 enum rport_event event)
1502{
1503 bfa_trc(rport->fcs, rport->pwwn);
1504 bfa_trc(rport->fcs, rport->pid);
1505 bfa_trc(rport->fcs, event);
1506
1507 switch (event) {
1508 case RPSM_EVENT_HCB_OFFLINE:
1509 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1510 bfa_fcs_rport_free(rport);
1511 break;
1512
1513 case RPSM_EVENT_DELETE:
1514 case RPSM_EVENT_LOGO_IMP:
1515 case RPSM_EVENT_PLOGI_RCVD:
1516 /* Ignore these events */
1517 break;
1518
1519 default:
1520 bfa_sm_fault(rport->fcs, event);
1521 }
1522}
1357 1523
1358/* 1524/*
1359 * fcs_rport_private FCS RPORT provate functions 1525 * fcs_rport_private FCS RPORT provate functions
@@ -1370,10 +1536,11 @@ bfa_fcs_rport_send_plogi(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1370 1536
1371 bfa_trc(rport->fcs, rport->pwwn); 1537 bfa_trc(rport->fcs, rport->pwwn);
1372 1538
1373 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 1539 fcxp = fcxp_alloced ? fcxp_alloced :
1540 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
1374 if (!fcxp) { 1541 if (!fcxp) {
1375 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe, 1542 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1376 bfa_fcs_rport_send_plogi, rport); 1543 bfa_fcs_rport_send_plogi, rport, BFA_TRUE);
1377 return; 1544 return;
1378 } 1545 }
1379 rport->fcxp = fcxp; 1546 rport->fcxp = fcxp;
@@ -1490,10 +1657,11 @@ bfa_fcs_rport_send_plogiacc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1490 bfa_trc(rport->fcs, rport->pwwn); 1657 bfa_trc(rport->fcs, rport->pwwn);
1491 bfa_trc(rport->fcs, rport->reply_oxid); 1658 bfa_trc(rport->fcs, rport->reply_oxid);
1492 1659
1493 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 1660 fcxp = fcxp_alloced ? fcxp_alloced :
1661 bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
1494 if (!fcxp) { 1662 if (!fcxp) {
1495 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe, 1663 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1496 bfa_fcs_rport_send_plogiacc, rport); 1664 bfa_fcs_rport_send_plogiacc, rport, BFA_FALSE);
1497 return; 1665 return;
1498 } 1666 }
1499 rport->fcxp = fcxp; 1667 rport->fcxp = fcxp;
@@ -1522,10 +1690,11 @@ bfa_fcs_rport_send_adisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1522 1690
1523 bfa_trc(rport->fcs, rport->pwwn); 1691 bfa_trc(rport->fcs, rport->pwwn);
1524 1692
1525 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 1693 fcxp = fcxp_alloced ? fcxp_alloced :
1694 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
1526 if (!fcxp) { 1695 if (!fcxp) {
1527 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe, 1696 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1528 bfa_fcs_rport_send_adisc, rport); 1697 bfa_fcs_rport_send_adisc, rport, BFA_TRUE);
1529 return; 1698 return;
1530 } 1699 }
1531 rport->fcxp = fcxp; 1700 rport->fcxp = fcxp;
@@ -1585,10 +1754,11 @@ bfa_fcs_rport_send_nsdisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1585 1754
1586 bfa_trc(rport->fcs, rport->pid); 1755 bfa_trc(rport->fcs, rport->pid);
1587 1756
1588 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 1757 fcxp = fcxp_alloced ? fcxp_alloced :
1758 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
1589 if (!fcxp) { 1759 if (!fcxp) {
1590 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe, 1760 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1591 bfa_fcs_rport_send_nsdisc, rport); 1761 bfa_fcs_rport_send_nsdisc, rport, BFA_TRUE);
1592 return; 1762 return;
1593 } 1763 }
1594 rport->fcxp = fcxp; 1764 rport->fcxp = fcxp;
@@ -1741,10 +1911,11 @@ bfa_fcs_rport_send_logo(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1741 1911
1742 port = rport->port; 1912 port = rport->port;
1743 1913
1744 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 1914 fcxp = fcxp_alloced ? fcxp_alloced :
1915 bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
1745 if (!fcxp) { 1916 if (!fcxp) {
1746 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe, 1917 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1747 bfa_fcs_rport_send_logo, rport); 1918 bfa_fcs_rport_send_logo, rport, BFA_FALSE);
1748 return; 1919 return;
1749 } 1920 }
1750 rport->fcxp = fcxp; 1921 rport->fcxp = fcxp;
@@ -1778,7 +1949,7 @@ bfa_fcs_rport_send_logo_acc(void *rport_cbarg)
1778 1949
1779 port = rport->port; 1950 port = rport->port;
1780 1951
1781 fcxp = bfa_fcs_fcxp_alloc(port->fcs); 1952 fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
1782 if (!fcxp) 1953 if (!fcxp)
1783 return; 1954 return;
1784 1955
@@ -1849,7 +2020,7 @@ bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,
1849 bfa_fcs_itnim_is_initiator(rport->itnim); 2020 bfa_fcs_itnim_is_initiator(rport->itnim);
1850 } 2021 }
1851 2022
1852 fcxp = bfa_fcs_fcxp_alloc(port->fcs); 2023 fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
1853 if (!fcxp) 2024 if (!fcxp)
1854 return; 2025 return;
1855 2026
@@ -1886,7 +2057,7 @@ bfa_fcs_rport_process_rpsc(struct bfa_fcs_rport_s *rport,
1886 2057
1887 speeds.port_op_speed = fc_bfa_speed_to_rpsc_operspeed(pport_attr.speed); 2058 speeds.port_op_speed = fc_bfa_speed_to_rpsc_operspeed(pport_attr.speed);
1888 2059
1889 fcxp = bfa_fcs_fcxp_alloc(port->fcs); 2060 fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
1890 if (!fcxp) 2061 if (!fcxp)
1891 return; 2062 return;
1892 2063
@@ -1920,7 +2091,7 @@ bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
1920 */ 2091 */
1921 if (bfa_fcs_itnim_get_online_state(rport->itnim) == BFA_STATUS_OK) { 2092 if (bfa_fcs_itnim_get_online_state(rport->itnim) == BFA_STATUS_OK) {
1922 2093
1923 fcxp = bfa_fcs_fcxp_alloc(port->fcs); 2094 fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
1924 if (!fcxp) 2095 if (!fcxp)
1925 return; 2096 return;
1926 2097
@@ -1957,6 +2128,15 @@ bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport)
1957 bfa_rport_online(rport->bfa_rport, &rport_info); 2128 bfa_rport_online(rport->bfa_rport, &rport_info);
1958} 2129}
1959 2130
2131static void
2132bfa_fcs_rport_hal_offline(struct bfa_fcs_rport_s *rport)
2133{
2134 if (rport->bfa_rport)
2135 bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
2136 else
2137 bfa_cb_rport_offline(rport);
2138}
2139
1960static struct bfa_fcs_rport_s * 2140static struct bfa_fcs_rport_s *
1961bfa_fcs_rport_alloc(struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid) 2141bfa_fcs_rport_alloc(struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid)
1962{ 2142{
@@ -1967,6 +2147,11 @@ bfa_fcs_rport_alloc(struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid)
1967 /* 2147 /*
1968 * allocate rport 2148 * allocate rport
1969 */ 2149 */
2150 if (fcs->num_rport_logins >= bfa_fcs_rport_max_logins) {
2151 bfa_trc(fcs, rpid);
2152 return NULL;
2153 }
2154
1970 if (bfa_fcb_rport_alloc(fcs->bfad, &rport, &rport_drv) 2155 if (bfa_fcb_rport_alloc(fcs->bfad, &rport, &rport_drv)
1971 != BFA_STATUS_OK) { 2156 != BFA_STATUS_OK) {
1972 bfa_trc(fcs, rpid); 2157 bfa_trc(fcs, rpid);
@@ -1981,16 +2166,9 @@ bfa_fcs_rport_alloc(struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid)
1981 rport->rp_drv = rport_drv; 2166 rport->rp_drv = rport_drv;
1982 rport->pid = rpid; 2167 rport->pid = rpid;
1983 rport->pwwn = pwwn; 2168 rport->pwwn = pwwn;
2169 rport->old_pid = 0;
1984 2170
1985 /* 2171 rport->bfa_rport = NULL;
1986 * allocate BFA rport
1987 */
1988 rport->bfa_rport = bfa_rport_create(port->fcs->bfa, rport);
1989 if (!rport->bfa_rport) {
1990 bfa_trc(fcs, rpid);
1991 kfree(rport_drv);
1992 return NULL;
1993 }
1994 2172
1995 /* 2173 /*
1996 * allocate FC-4s 2174 * allocate FC-4s
@@ -2001,14 +2179,13 @@ bfa_fcs_rport_alloc(struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid)
2001 rport->itnim = bfa_fcs_itnim_create(rport); 2179 rport->itnim = bfa_fcs_itnim_create(rport);
2002 if (!rport->itnim) { 2180 if (!rport->itnim) {
2003 bfa_trc(fcs, rpid); 2181 bfa_trc(fcs, rpid);
2004 bfa_sm_send_event(rport->bfa_rport,
2005 BFA_RPORT_SM_DELETE);
2006 kfree(rport_drv); 2182 kfree(rport_drv);
2007 return NULL; 2183 return NULL;
2008 } 2184 }
2009 } 2185 }
2010 2186
2011 bfa_fcs_lport_add_rport(port, rport); 2187 bfa_fcs_lport_add_rport(port, rport);
2188 fcs->num_rport_logins++;
2012 2189
2013 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); 2190 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
2014 2191
@@ -2024,20 +2201,28 @@ static void
2024bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport) 2201bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport)
2025{ 2202{
2026 struct bfa_fcs_lport_s *port = rport->port; 2203 struct bfa_fcs_lport_s *port = rport->port;
2204 struct bfa_fcs_s *fcs = port->fcs;
2027 2205
2028 /* 2206 /*
2029 * - delete FC-4s 2207 * - delete FC-4s
2030 * - delete BFA rport 2208 * - delete BFA rport
2031 * - remove from queue of rports 2209 * - remove from queue of rports
2032 */ 2210 */
2211 rport->plogi_pending = BFA_FALSE;
2212
2033 if (bfa_fcs_lport_is_initiator(port)) { 2213 if (bfa_fcs_lport_is_initiator(port)) {
2034 bfa_fcs_itnim_delete(rport->itnim); 2214 bfa_fcs_itnim_delete(rport->itnim);
2035 if (rport->pid != 0 && !BFA_FCS_PID_IS_WKA(rport->pid)) 2215 if (rport->pid != 0 && !BFA_FCS_PID_IS_WKA(rport->pid))
2036 bfa_fcs_rpf_rport_offline(rport); 2216 bfa_fcs_rpf_rport_offline(rport);
2037 } 2217 }
2038 2218
2039 bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_DELETE); 2219 if (rport->bfa_rport) {
2220 bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_DELETE);
2221 rport->bfa_rport = NULL;
2222 }
2223
2040 bfa_fcs_lport_del_rport(port, rport); 2224 bfa_fcs_lport_del_rport(port, rport);
2225 fcs->num_rport_logins--;
2041 kfree(rport->rp_drv); 2226 kfree(rport->rp_drv);
2042} 2227}
2043 2228
@@ -2071,7 +2256,18 @@ bfa_fcs_rport_aen_post(struct bfa_fcs_rport_s *rport,
2071} 2256}
2072 2257
2073static void 2258static void
2074bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport) 2259bfa_fcs_rport_fcs_online_action(struct bfa_fcs_rport_s *rport)
2260{
2261 if ((!rport->pid) || (!rport->pwwn)) {
2262 bfa_trc(rport->fcs, rport->pid);
2263 bfa_sm_fault(rport->fcs, rport->pid);
2264 }
2265
2266 bfa_sm_send_event(rport->itnim, BFA_FCS_ITNIM_SM_FCS_ONLINE);
2267}
2268
2269static void
2270bfa_fcs_rport_hal_online_action(struct bfa_fcs_rport_s *rport)
2075{ 2271{
2076 struct bfa_fcs_lport_s *port = rport->port; 2272 struct bfa_fcs_lport_s *port = rport->port;
2077 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad; 2273 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
@@ -2086,7 +2282,7 @@ bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport)
2086 } 2282 }
2087 2283
2088 if (bfa_fcs_lport_is_initiator(port)) { 2284 if (bfa_fcs_lport_is_initiator(port)) {
2089 bfa_fcs_itnim_rport_online(rport->itnim); 2285 bfa_fcs_itnim_brp_online(rport->itnim);
2090 if (!BFA_FCS_PID_IS_WKA(rport->pid)) 2286 if (!BFA_FCS_PID_IS_WKA(rport->pid))
2091 bfa_fcs_rpf_rport_online(rport); 2287 bfa_fcs_rpf_rport_online(rport);
2092 }; 2288 };
@@ -2102,15 +2298,28 @@ bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport)
2102} 2298}
2103 2299
2104static void 2300static void
2105bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport) 2301bfa_fcs_rport_fcs_offline_action(struct bfa_fcs_rport_s *rport)
2302{
2303 if (!BFA_FCS_PID_IS_WKA(rport->pid))
2304 bfa_fcs_rpf_rport_offline(rport);
2305
2306 bfa_fcs_itnim_rport_offline(rport->itnim);
2307}
2308
2309static void
2310bfa_fcs_rport_hal_offline_action(struct bfa_fcs_rport_s *rport)
2106{ 2311{
2107 struct bfa_fcs_lport_s *port = rport->port; 2312 struct bfa_fcs_lport_s *port = rport->port;
2108 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad; 2313 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
2109 char lpwwn_buf[BFA_STRING_32]; 2314 char lpwwn_buf[BFA_STRING_32];
2110 char rpwwn_buf[BFA_STRING_32]; 2315 char rpwwn_buf[BFA_STRING_32];
2111 2316
2317 if (!rport->bfa_rport) {
2318 bfa_fcs_rport_fcs_offline_action(rport);
2319 return;
2320 }
2321
2112 rport->stats.offlines++; 2322 rport->stats.offlines++;
2113 rport->plogi_pending = BFA_FALSE;
2114 2323
2115 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port)); 2324 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
2116 wwn2str(rpwwn_buf, rport->pwwn); 2325 wwn2str(rpwwn_buf, rport->pwwn);
@@ -2340,7 +2549,6 @@ bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport)
2340 bfa_sm_send_event(rport, RPSM_EVENT_SCN); 2549 bfa_sm_send_event(rport, RPSM_EVENT_SCN);
2341} 2550}
2342 2551
2343
2344/* 2552/*
2345 * brief 2553 * brief
2346 * This routine BFA callback for bfa_rport_online() call. 2554 * This routine BFA callback for bfa_rport_online() call.
@@ -2508,7 +2716,7 @@ bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport)
2508 2716
2509 bfa_trc(rport->fcs, rport->pid); 2717 bfa_trc(rport->fcs, rport->pid);
2510 2718
2511 fcxp = bfa_fcs_fcxp_alloc(port->fcs); 2719 fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
2512 if (!fcxp) 2720 if (!fcxp)
2513 return; 2721 return;
2514 len = fc_prlo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), 2722 len = fc_prlo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
@@ -2534,7 +2742,7 @@ bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
2534 2742
2535 bfa_trc(rport->fcs, rx_fchs->s_id); 2743 bfa_trc(rport->fcs, rx_fchs->s_id);
2536 2744
2537 fcxp = bfa_fcs_fcxp_alloc(rport->fcs); 2745 fcxp = bfa_fcs_fcxp_alloc(rport->fcs, BFA_FALSE);
2538 if (!fcxp) 2746 if (!fcxp)
2539 return; 2747 return;
2540 2748
@@ -2582,6 +2790,17 @@ bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, __be16 ox_id)
2582 bfa_sm_send_event(rport, RPSM_EVENT_PRLO_RCVD); 2790 bfa_sm_send_event(rport, RPSM_EVENT_PRLO_RCVD);
2583} 2791}
2584 2792
2793/*
2794 * Called by BFAD to set the max limit on number of bfa_fcs_rport allocation
2795 * which limits number of concurrent logins to remote ports
2796 */
2797void
2798bfa_fcs_rport_set_max_logins(u32 max_logins)
2799{
2800 if (max_logins > 0)
2801 bfa_fcs_rport_max_logins = max_logins;
2802}
2803
2585void 2804void
2586bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport, 2805bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
2587 struct bfa_rport_attr_s *rport_attr) 2806 struct bfa_rport_attr_s *rport_attr)
@@ -2605,9 +2824,11 @@ bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
2605 rport_attr->curr_speed = rport->rpf.rpsc_speed; 2824 rport_attr->curr_speed = rport->rpf.rpsc_speed;
2606 rport_attr->assigned_speed = rport->rpf.assigned_speed; 2825 rport_attr->assigned_speed = rport->rpf.assigned_speed;
2607 2826
2608 qos_attr.qos_priority = rport->bfa_rport->qos_attr.qos_priority; 2827 if (rport->bfa_rport) {
2609 qos_attr.qos_flow_id = 2828 qos_attr.qos_priority = rport->bfa_rport->qos_attr.qos_priority;
2610 cpu_to_be32(rport->bfa_rport->qos_attr.qos_flow_id); 2829 qos_attr.qos_flow_id =
2830 cpu_to_be32(rport->bfa_rport->qos_attr.qos_flow_id);
2831 }
2611 rport_attr->qos_attr = qos_attr; 2832 rport_attr->qos_attr = qos_attr;
2612 2833
2613 rport_attr->trl_enforced = BFA_FALSE; 2834 rport_attr->trl_enforced = BFA_FALSE;
@@ -2940,10 +3161,11 @@ bfa_fcs_rpf_send_rpsc2(void *rpf_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2940 3161
2941 bfa_trc(rport->fcs, rport->pwwn); 3162 bfa_trc(rport->fcs, rport->pwwn);
2942 3163
2943 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 3164 fcxp = fcxp_alloced ? fcxp_alloced :
3165 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
2944 if (!fcxp) { 3166 if (!fcxp) {
2945 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rpf->fcxp_wqe, 3167 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rpf->fcxp_wqe,
2946 bfa_fcs_rpf_send_rpsc2, rpf); 3168 bfa_fcs_rpf_send_rpsc2, rpf, BFA_TRUE);
2947 return; 3169 return;
2948 } 3170 }
2949 rpf->fcxp = fcxp; 3171 rpf->fcxp = fcxp;
diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c
index 21ad2902e5c..75ca8752b9f 100644
--- a/drivers/scsi/bfa/bfa_ioc.c
+++ b/drivers/scsi/bfa/bfa_ioc.c
@@ -92,7 +92,6 @@ static void bfa_ioc_event_notify(struct bfa_ioc_s *ioc ,
92 enum bfa_ioc_event_e event); 92 enum bfa_ioc_event_e event);
93static void bfa_ioc_disable_comp(struct bfa_ioc_s *ioc); 93static void bfa_ioc_disable_comp(struct bfa_ioc_s *ioc);
94static void bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc); 94static void bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc);
95static void bfa_ioc_debug_save_ftrc(struct bfa_ioc_s *ioc);
96static void bfa_ioc_fail_notify(struct bfa_ioc_s *ioc); 95static void bfa_ioc_fail_notify(struct bfa_ioc_s *ioc);
97static void bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc); 96static void bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc);
98 97
@@ -599,8 +598,9 @@ bfa_ioc_sm_fail(struct bfa_ioc_s *ioc, enum ioc_event event)
599 break; 598 break;
600 599
601 case IOC_E_HWERROR: 600 case IOC_E_HWERROR:
601 case IOC_E_HWFAILED:
602 /* 602 /*
603 * HB failure notification, ignore. 603 * HB failure / HW error notification, ignore.
604 */ 604 */
605 break; 605 break;
606 default: 606 default:
@@ -632,6 +632,10 @@ bfa_ioc_sm_hwfail(struct bfa_ioc_s *ioc, enum ioc_event event)
632 bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit); 632 bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
633 break; 633 break;
634 634
635 case IOC_E_HWERROR:
636 /* Ignore - already in hwfail state */
637 break;
638
635 default: 639 default:
636 bfa_sm_fault(ioc, event); 640 bfa_sm_fault(ioc, event);
637 } 641 }
@@ -1455,7 +1459,7 @@ bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
1455 bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0); 1459 bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);
1456 1460
1457 for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) { 1461 for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) {
1458 if (fwhdr->md5sum[i] != drv_fwhdr->md5sum[i]) { 1462 if (fwhdr->md5sum[i] != cpu_to_le32(drv_fwhdr->md5sum[i])) {
1459 bfa_trc(ioc, i); 1463 bfa_trc(ioc, i);
1460 bfa_trc(ioc, fwhdr->md5sum[i]); 1464 bfa_trc(ioc, fwhdr->md5sum[i]);
1461 bfa_trc(ioc, drv_fwhdr->md5sum[i]); 1465 bfa_trc(ioc, drv_fwhdr->md5sum[i]);
@@ -1480,7 +1484,7 @@ bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc, u32 boot_env)
1480 drv_fwhdr = (struct bfi_ioc_image_hdr_s *) 1484 drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
1481 bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0); 1485 bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);
1482 1486
1483 if (fwhdr.signature != drv_fwhdr->signature) { 1487 if (fwhdr.signature != cpu_to_le32(drv_fwhdr->signature)) {
1484 bfa_trc(ioc, fwhdr.signature); 1488 bfa_trc(ioc, fwhdr.signature);
1485 bfa_trc(ioc, drv_fwhdr->signature); 1489 bfa_trc(ioc, drv_fwhdr->signature);
1486 return BFA_FALSE; 1490 return BFA_FALSE;
@@ -1704,7 +1708,7 @@ bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
1704 * write smem 1708 * write smem
1705 */ 1709 */
1706 bfa_mem_write(ioc->ioc_regs.smem_page_start, loff, 1710 bfa_mem_write(ioc->ioc_regs.smem_page_start, loff,
1707 fwimg[BFA_IOC_FLASH_OFFSET_IN_CHUNK(i)]); 1711 cpu_to_le32(fwimg[BFA_IOC_FLASH_OFFSET_IN_CHUNK(i)]));
1708 1712
1709 loff += sizeof(u32); 1713 loff += sizeof(u32);
1710 1714
@@ -2260,6 +2264,12 @@ bfa_ioc_disable(struct bfa_ioc_s *ioc)
2260 bfa_fsm_send_event(ioc, IOC_E_DISABLE); 2264 bfa_fsm_send_event(ioc, IOC_E_DISABLE);
2261} 2265}
2262 2266
2267void
2268bfa_ioc_suspend(struct bfa_ioc_s *ioc)
2269{
2270 ioc->dbg_fwsave_once = BFA_TRUE;
2271 bfa_fsm_send_event(ioc, IOC_E_HWERROR);
2272}
2263 2273
2264/* 2274/*
2265 * Initialize memory for saving firmware trace. Driver must initialize 2275 * Initialize memory for saving firmware trace. Driver must initialize
@@ -2269,7 +2279,7 @@ void
2269bfa_ioc_debug_memclaim(struct bfa_ioc_s *ioc, void *dbg_fwsave) 2279bfa_ioc_debug_memclaim(struct bfa_ioc_s *ioc, void *dbg_fwsave)
2270{ 2280{
2271 ioc->dbg_fwsave = dbg_fwsave; 2281 ioc->dbg_fwsave = dbg_fwsave;
2272 ioc->dbg_fwsave_len = (ioc->iocpf.auto_recover) ? BFA_DBG_FWTRC_LEN : 0; 2282 ioc->dbg_fwsave_len = BFA_DBG_FWTRC_LEN;
2273} 2283}
2274 2284
2275/* 2285/*
@@ -2856,7 +2866,7 @@ bfa_ioc_fw_stats_clear(struct bfa_ioc_s *ioc)
2856/* 2866/*
2857 * Save firmware trace if configured. 2867 * Save firmware trace if configured.
2858 */ 2868 */
2859static void 2869void
2860bfa_ioc_debug_save_ftrc(struct bfa_ioc_s *ioc) 2870bfa_ioc_debug_save_ftrc(struct bfa_ioc_s *ioc)
2861{ 2871{
2862 int tlen; 2872 int tlen;
diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h
index 7b916e04ca5..b2856f96567 100644
--- a/drivers/scsi/bfa/bfa_ioc.h
+++ b/drivers/scsi/bfa/bfa_ioc.h
@@ -820,6 +820,7 @@ void bfa_ioc_attach(struct bfa_ioc_s *ioc, void *bfa,
820 struct bfa_ioc_cbfn_s *cbfn, struct bfa_timer_mod_s *timer_mod); 820 struct bfa_ioc_cbfn_s *cbfn, struct bfa_timer_mod_s *timer_mod);
821void bfa_ioc_auto_recover(bfa_boolean_t auto_recover); 821void bfa_ioc_auto_recover(bfa_boolean_t auto_recover);
822void bfa_ioc_detach(struct bfa_ioc_s *ioc); 822void bfa_ioc_detach(struct bfa_ioc_s *ioc);
823void bfa_ioc_suspend(struct bfa_ioc_s *ioc);
823void bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev, 824void bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev,
824 enum bfi_pcifn_class clscode); 825 enum bfi_pcifn_class clscode);
825void bfa_ioc_mem_claim(struct bfa_ioc_s *ioc, u8 *dm_kva, u64 dm_pa); 826void bfa_ioc_mem_claim(struct bfa_ioc_s *ioc, u8 *dm_kva, u64 dm_pa);
@@ -866,6 +867,7 @@ bfa_boolean_t bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc,
866void bfa_ioc_aen_post(struct bfa_ioc_s *ioc, enum bfa_ioc_aen_event event); 867void bfa_ioc_aen_post(struct bfa_ioc_s *ioc, enum bfa_ioc_aen_event event);
867bfa_status_t bfa_ioc_fw_stats_get(struct bfa_ioc_s *ioc, void *stats); 868bfa_status_t bfa_ioc_fw_stats_get(struct bfa_ioc_s *ioc, void *stats);
868bfa_status_t bfa_ioc_fw_stats_clear(struct bfa_ioc_s *ioc); 869bfa_status_t bfa_ioc_fw_stats_clear(struct bfa_ioc_s *ioc);
870void bfa_ioc_debug_save_ftrc(struct bfa_ioc_s *ioc);
869 871
870/* 872/*
871 * asic block configuration related APIs 873 * asic block configuration related APIs
diff --git a/drivers/scsi/bfa/bfa_modules.h b/drivers/scsi/bfa/bfa_modules.h
index 2d36e482383..189fff71e3c 100644
--- a/drivers/scsi/bfa/bfa_modules.h
+++ b/drivers/scsi/bfa/bfa_modules.h
@@ -121,6 +121,7 @@ struct bfa_s {
121 bfa_boolean_t fcs; /* FCS is attached to BFA */ 121 bfa_boolean_t fcs; /* FCS is attached to BFA */
122 struct bfa_msix_s msix; 122 struct bfa_msix_s msix;
123 int bfa_aen_seq; 123 int bfa_aen_seq;
124 bfa_boolean_t intr_enabled; /* Status of interrupts */
124}; 125};
125 126
126extern bfa_boolean_t bfa_auto_recover; 127extern bfa_boolean_t bfa_auto_recover;
diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c
index 2e856e6710f..b2538d60db3 100644
--- a/drivers/scsi/bfa/bfa_svc.c
+++ b/drivers/scsi/bfa/bfa_svc.c
@@ -440,9 +440,11 @@ claim_fcxps_mem(struct bfa_fcxp_mod_s *mod)
440 fcxp = (struct bfa_fcxp_s *) bfa_mem_kva_curp(mod); 440 fcxp = (struct bfa_fcxp_s *) bfa_mem_kva_curp(mod);
441 memset(fcxp, 0, sizeof(struct bfa_fcxp_s) * mod->num_fcxps); 441 memset(fcxp, 0, sizeof(struct bfa_fcxp_s) * mod->num_fcxps);
442 442
443 INIT_LIST_HEAD(&mod->fcxp_free_q); 443 INIT_LIST_HEAD(&mod->fcxp_req_free_q);
444 INIT_LIST_HEAD(&mod->fcxp_rsp_free_q);
444 INIT_LIST_HEAD(&mod->fcxp_active_q); 445 INIT_LIST_HEAD(&mod->fcxp_active_q);
445 INIT_LIST_HEAD(&mod->fcxp_unused_q); 446 INIT_LIST_HEAD(&mod->fcxp_req_unused_q);
447 INIT_LIST_HEAD(&mod->fcxp_rsp_unused_q);
446 448
447 mod->fcxp_list = fcxp; 449 mod->fcxp_list = fcxp;
448 450
@@ -450,7 +452,14 @@ claim_fcxps_mem(struct bfa_fcxp_mod_s *mod)
450 fcxp->fcxp_mod = mod; 452 fcxp->fcxp_mod = mod;
451 fcxp->fcxp_tag = i; 453 fcxp->fcxp_tag = i;
452 454
453 list_add_tail(&fcxp->qe, &mod->fcxp_free_q); 455 if (i < (mod->num_fcxps / 2)) {
456 list_add_tail(&fcxp->qe, &mod->fcxp_req_free_q);
457 fcxp->req_rsp = BFA_TRUE;
458 } else {
459 list_add_tail(&fcxp->qe, &mod->fcxp_rsp_free_q);
460 fcxp->req_rsp = BFA_FALSE;
461 }
462
454 bfa_reqq_winit(&fcxp->reqq_wqe, bfa_fcxp_qresume, fcxp); 463 bfa_reqq_winit(&fcxp->reqq_wqe, bfa_fcxp_qresume, fcxp);
455 fcxp->reqq_waiting = BFA_FALSE; 464 fcxp->reqq_waiting = BFA_FALSE;
456 465
@@ -514,7 +523,8 @@ bfa_fcxp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
514 if (!cfg->drvcfg.min_cfg) 523 if (!cfg->drvcfg.min_cfg)
515 mod->rsp_pld_sz = BFA_FCXP_MAX_LBUF_SZ; 524 mod->rsp_pld_sz = BFA_FCXP_MAX_LBUF_SZ;
516 525
517 INIT_LIST_HEAD(&mod->wait_q); 526 INIT_LIST_HEAD(&mod->req_wait_q);
527 INIT_LIST_HEAD(&mod->rsp_wait_q);
518 528
519 claim_fcxps_mem(mod); 529 claim_fcxps_mem(mod);
520} 530}
@@ -542,7 +552,8 @@ bfa_fcxp_iocdisable(struct bfa_s *bfa)
542 struct list_head *qe, *qen; 552 struct list_head *qe, *qen;
543 553
544 /* Enqueue unused fcxp resources to free_q */ 554 /* Enqueue unused fcxp resources to free_q */
545 list_splice_tail_init(&mod->fcxp_unused_q, &mod->fcxp_free_q); 555 list_splice_tail_init(&mod->fcxp_req_unused_q, &mod->fcxp_req_free_q);
556 list_splice_tail_init(&mod->fcxp_rsp_unused_q, &mod->fcxp_rsp_free_q);
546 557
547 list_for_each_safe(qe, qen, &mod->fcxp_active_q) { 558 list_for_each_safe(qe, qen, &mod->fcxp_active_q) {
548 fcxp = (struct bfa_fcxp_s *) qe; 559 fcxp = (struct bfa_fcxp_s *) qe;
@@ -559,11 +570,14 @@ bfa_fcxp_iocdisable(struct bfa_s *bfa)
559} 570}
560 571
561static struct bfa_fcxp_s * 572static struct bfa_fcxp_s *
562bfa_fcxp_get(struct bfa_fcxp_mod_s *fm) 573bfa_fcxp_get(struct bfa_fcxp_mod_s *fm, bfa_boolean_t req)
563{ 574{
564 struct bfa_fcxp_s *fcxp; 575 struct bfa_fcxp_s *fcxp;
565 576
566 bfa_q_deq(&fm->fcxp_free_q, &fcxp); 577 if (req)
578 bfa_q_deq(&fm->fcxp_req_free_q, &fcxp);
579 else
580 bfa_q_deq(&fm->fcxp_rsp_free_q, &fcxp);
567 581
568 if (fcxp) 582 if (fcxp)
569 list_add_tail(&fcxp->qe, &fm->fcxp_active_q); 583 list_add_tail(&fcxp->qe, &fm->fcxp_active_q);
@@ -642,7 +656,11 @@ bfa_fcxp_put(struct bfa_fcxp_s *fcxp)
642 struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod; 656 struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
643 struct bfa_fcxp_wqe_s *wqe; 657 struct bfa_fcxp_wqe_s *wqe;
644 658
645 bfa_q_deq(&mod->wait_q, &wqe); 659 if (fcxp->req_rsp)
660 bfa_q_deq(&mod->req_wait_q, &wqe);
661 else
662 bfa_q_deq(&mod->rsp_wait_q, &wqe);
663
646 if (wqe) { 664 if (wqe) {
647 bfa_trc(mod->bfa, fcxp->fcxp_tag); 665 bfa_trc(mod->bfa, fcxp->fcxp_tag);
648 666
@@ -657,7 +675,11 @@ bfa_fcxp_put(struct bfa_fcxp_s *fcxp)
657 675
658 WARN_ON(!bfa_q_is_on_q(&mod->fcxp_active_q, fcxp)); 676 WARN_ON(!bfa_q_is_on_q(&mod->fcxp_active_q, fcxp));
659 list_del(&fcxp->qe); 677 list_del(&fcxp->qe);
660 list_add_tail(&fcxp->qe, &mod->fcxp_free_q); 678
679 if (fcxp->req_rsp)
680 list_add_tail(&fcxp->qe, &mod->fcxp_req_free_q);
681 else
682 list_add_tail(&fcxp->qe, &mod->fcxp_rsp_free_q);
661} 683}
662 684
663static void 685static void
@@ -900,21 +922,23 @@ bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)
900 * Address (given the sge index). 922 * Address (given the sge index).
901 * @param[in] get_rsp_sglen function ptr to be called to get a response SG 923 * @param[in] get_rsp_sglen function ptr to be called to get a response SG
902 * len (given the sge index). 924 * len (given the sge index).
925 * @param[in] req Allocated FCXP is used to send req or rsp?
926 * request - BFA_TRUE, response - BFA_FALSE
903 * 927 *
904 * @return FCXP instance. NULL on failure. 928 * @return FCXP instance. NULL on failure.
905 */ 929 */
906struct bfa_fcxp_s * 930struct bfa_fcxp_s *
907bfa_fcxp_alloc(void *caller, struct bfa_s *bfa, int nreq_sgles, 931bfa_fcxp_req_rsp_alloc(void *caller, struct bfa_s *bfa, int nreq_sgles,
908 int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn, 932 int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
909 bfa_fcxp_get_sglen_t req_sglen_cbfn, 933 bfa_fcxp_get_sglen_t req_sglen_cbfn,
910 bfa_fcxp_get_sgaddr_t rsp_sga_cbfn, 934 bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
911 bfa_fcxp_get_sglen_t rsp_sglen_cbfn) 935 bfa_fcxp_get_sglen_t rsp_sglen_cbfn, bfa_boolean_t req)
912{ 936{
913 struct bfa_fcxp_s *fcxp = NULL; 937 struct bfa_fcxp_s *fcxp = NULL;
914 938
915 WARN_ON(bfa == NULL); 939 WARN_ON(bfa == NULL);
916 940
917 fcxp = bfa_fcxp_get(BFA_FCXP_MOD(bfa)); 941 fcxp = bfa_fcxp_get(BFA_FCXP_MOD(bfa), req);
918 if (fcxp == NULL) 942 if (fcxp == NULL)
919 return NULL; 943 return NULL;
920 944
@@ -1071,17 +1095,20 @@ bfa_fcxp_abort(struct bfa_fcxp_s *fcxp)
1071} 1095}
1072 1096
1073void 1097void
1074bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe, 1098bfa_fcxp_req_rsp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
1075 bfa_fcxp_alloc_cbfn_t alloc_cbfn, void *alloc_cbarg, 1099 bfa_fcxp_alloc_cbfn_t alloc_cbfn, void *alloc_cbarg,
1076 void *caller, int nreq_sgles, 1100 void *caller, int nreq_sgles,
1077 int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn, 1101 int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
1078 bfa_fcxp_get_sglen_t req_sglen_cbfn, 1102 bfa_fcxp_get_sglen_t req_sglen_cbfn,
1079 bfa_fcxp_get_sgaddr_t rsp_sga_cbfn, 1103 bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
1080 bfa_fcxp_get_sglen_t rsp_sglen_cbfn) 1104 bfa_fcxp_get_sglen_t rsp_sglen_cbfn, bfa_boolean_t req)
1081{ 1105{
1082 struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa); 1106 struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
1083 1107
1084 WARN_ON(!list_empty(&mod->fcxp_free_q)); 1108 if (req)
1109 WARN_ON(!list_empty(&mod->fcxp_req_free_q));
1110 else
1111 WARN_ON(!list_empty(&mod->fcxp_rsp_free_q));
1085 1112
1086 wqe->alloc_cbfn = alloc_cbfn; 1113 wqe->alloc_cbfn = alloc_cbfn;
1087 wqe->alloc_cbarg = alloc_cbarg; 1114 wqe->alloc_cbarg = alloc_cbarg;
@@ -1094,7 +1121,10 @@ bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
1094 wqe->rsp_sga_cbfn = rsp_sga_cbfn; 1121 wqe->rsp_sga_cbfn = rsp_sga_cbfn;
1095 wqe->rsp_sglen_cbfn = rsp_sglen_cbfn; 1122 wqe->rsp_sglen_cbfn = rsp_sglen_cbfn;
1096 1123
1097 list_add_tail(&wqe->qe, &mod->wait_q); 1124 if (req)
1125 list_add_tail(&wqe->qe, &mod->req_wait_q);
1126 else
1127 list_add_tail(&wqe->qe, &mod->rsp_wait_q);
1098} 1128}
1099 1129
1100void 1130void
@@ -1102,7 +1132,8 @@ bfa_fcxp_walloc_cancel(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe)
1102{ 1132{
1103 struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa); 1133 struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
1104 1134
1105 WARN_ON(!bfa_q_is_on_q(&mod->wait_q, wqe)); 1135 WARN_ON(!bfa_q_is_on_q(&mod->req_wait_q, wqe) ||
1136 !bfa_q_is_on_q(&mod->rsp_wait_q, wqe));
1106 list_del(&wqe->qe); 1137 list_del(&wqe->qe);
1107} 1138}
1108 1139
@@ -1153,8 +1184,13 @@ bfa_fcxp_res_recfg(struct bfa_s *bfa, u16 num_fcxp_fw)
1153 int i; 1184 int i;
1154 1185
1155 for (i = 0; i < (mod->num_fcxps - num_fcxp_fw); i++) { 1186 for (i = 0; i < (mod->num_fcxps - num_fcxp_fw); i++) {
1156 bfa_q_deq_tail(&mod->fcxp_free_q, &qe); 1187 if (i < ((mod->num_fcxps - num_fcxp_fw) / 2)) {
1157 list_add_tail(qe, &mod->fcxp_unused_q); 1188 bfa_q_deq_tail(&mod->fcxp_req_free_q, &qe);
1189 list_add_tail(qe, &mod->fcxp_req_unused_q);
1190 } else {
1191 bfa_q_deq_tail(&mod->fcxp_rsp_free_q, &qe);
1192 list_add_tail(qe, &mod->fcxp_rsp_unused_q);
1193 }
1158 } 1194 }
1159} 1195}
1160 1196
@@ -1404,11 +1440,11 @@ bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event)
1404 1440
1405 switch (event) { 1441 switch (event) {
1406 case BFA_LPS_SM_FWRSP: 1442 case BFA_LPS_SM_FWRSP:
1443 case BFA_LPS_SM_OFFLINE:
1407 bfa_sm_set_state(lps, bfa_lps_sm_init); 1444 bfa_sm_set_state(lps, bfa_lps_sm_init);
1408 bfa_lps_logout_comp(lps); 1445 bfa_lps_logout_comp(lps);
1409 break; 1446 break;
1410 1447
1411 case BFA_LPS_SM_OFFLINE:
1412 case BFA_LPS_SM_DELETE: 1448 case BFA_LPS_SM_DELETE:
1413 bfa_sm_set_state(lps, bfa_lps_sm_init); 1449 bfa_sm_set_state(lps, bfa_lps_sm_init);
1414 break; 1450 break;
@@ -1786,6 +1822,8 @@ bfa_lps_logout_comp_cb(void *arg, bfa_boolean_t complete)
1786 1822
1787 if (lps->fdisc) 1823 if (lps->fdisc)
1788 bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg); 1824 bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
1825 else
1826 bfa_cb_lps_flogo_comp(lps->bfa->bfad, lps->uarg);
1789} 1827}
1790 1828
1791/* 1829/*
@@ -4237,6 +4275,10 @@ bfa_rport_sm_offline(struct bfa_rport_s *rp, enum bfa_rport_event event)
4237 bfa_sm_set_state(rp, bfa_rport_sm_iocdisable); 4275 bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4238 break; 4276 break;
4239 4277
4278 case BFA_RPORT_SM_OFFLINE:
4279 bfa_rport_offline_cb(rp);
4280 break;
4281
4240 default: 4282 default:
4241 bfa_stats(rp, sm_off_unexp); 4283 bfa_stats(rp, sm_off_unexp);
4242 bfa_sm_fault(rp->bfa, event); 4284 bfa_sm_fault(rp->bfa, event);
@@ -4353,6 +4395,7 @@ bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,
4353 case BFA_RPORT_SM_HWFAIL: 4395 case BFA_RPORT_SM_HWFAIL:
4354 bfa_stats(rp, sm_offp_hwf); 4396 bfa_stats(rp, sm_offp_hwf);
4355 bfa_sm_set_state(rp, bfa_rport_sm_iocdisable); 4397 bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4398 bfa_rport_offline_cb(rp);
4356 break; 4399 break;
4357 4400
4358 default: 4401 default:
@@ -4731,8 +4774,10 @@ bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed)
4731 WARN_ON(speed == 0); 4774 WARN_ON(speed == 0);
4732 WARN_ON(speed == BFA_PORT_SPEED_AUTO); 4775 WARN_ON(speed == BFA_PORT_SPEED_AUTO);
4733 4776
4734 rport->rport_info.speed = speed; 4777 if (rport) {
4735 bfa_sm_send_event(rport, BFA_RPORT_SM_SET_SPEED); 4778 rport->rport_info.speed = speed;
4779 bfa_sm_send_event(rport, BFA_RPORT_SM_SET_SPEED);
4780 }
4736} 4781}
4737 4782
4738/* Set Rport LUN Mask */ 4783/* Set Rport LUN Mask */
diff --git a/drivers/scsi/bfa/bfa_svc.h b/drivers/scsi/bfa/bfa_svc.h
index f3006756463..1abcf7c5166 100644
--- a/drivers/scsi/bfa/bfa_svc.h
+++ b/drivers/scsi/bfa/bfa_svc.h
@@ -97,10 +97,13 @@ struct bfa_fcxp_mod_s {
97 struct bfa_s *bfa; /* backpointer to BFA */ 97 struct bfa_s *bfa; /* backpointer to BFA */
98 struct bfa_fcxp_s *fcxp_list; /* array of FCXPs */ 98 struct bfa_fcxp_s *fcxp_list; /* array of FCXPs */
99 u16 num_fcxps; /* max num FCXP requests */ 99 u16 num_fcxps; /* max num FCXP requests */
100 struct list_head fcxp_free_q; /* free FCXPs */ 100 struct list_head fcxp_req_free_q; /* free FCXPs used for sending req */
101 struct list_head fcxp_active_q; /* active FCXPs */ 101 struct list_head fcxp_rsp_free_q; /* free FCXPs used for sending req */
102 struct list_head wait_q; /* wait queue for free fcxp */ 102 struct list_head fcxp_active_q; /* active FCXPs */
103 struct list_head fcxp_unused_q; /* unused fcxps */ 103 struct list_head req_wait_q; /* wait queue for free req_fcxp */
104 struct list_head rsp_wait_q; /* wait queue for free rsp_fcxp */
105 struct list_head fcxp_req_unused_q; /* unused req_fcxps */
106 struct list_head fcxp_rsp_unused_q; /* unused rsp_fcxps */
104 u32 req_pld_sz; 107 u32 req_pld_sz;
105 u32 rsp_pld_sz; 108 u32 rsp_pld_sz;
106 struct bfa_mem_dma_s dma_seg[BFA_FCXP_DMA_SEGS]; 109 struct bfa_mem_dma_s dma_seg[BFA_FCXP_DMA_SEGS];
@@ -197,6 +200,7 @@ struct bfa_fcxp_s {
197 struct bfa_cb_qe_s hcb_qe; /* comp: callback qelem */ 200 struct bfa_cb_qe_s hcb_qe; /* comp: callback qelem */
198 struct bfa_reqq_wait_s reqq_wqe; 201 struct bfa_reqq_wait_s reqq_wqe;
199 bfa_boolean_t reqq_waiting; 202 bfa_boolean_t reqq_waiting;
203 bfa_boolean_t req_rsp; /* Used to track req/rsp fcxp */
200}; 204};
201 205
202struct bfa_fcxp_wqe_s { 206struct bfa_fcxp_wqe_s {
@@ -586,20 +590,22 @@ void bfa_rport_unset_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp);
586/* 590/*
587 * bfa fcxp API functions 591 * bfa fcxp API functions
588 */ 592 */
589struct bfa_fcxp_s *bfa_fcxp_alloc(void *bfad_fcxp, struct bfa_s *bfa, 593struct bfa_fcxp_s *bfa_fcxp_req_rsp_alloc(void *bfad_fcxp, struct bfa_s *bfa,
590 int nreq_sgles, int nrsp_sgles, 594 int nreq_sgles, int nrsp_sgles,
591 bfa_fcxp_get_sgaddr_t get_req_sga, 595 bfa_fcxp_get_sgaddr_t get_req_sga,
592 bfa_fcxp_get_sglen_t get_req_sglen, 596 bfa_fcxp_get_sglen_t get_req_sglen,
593 bfa_fcxp_get_sgaddr_t get_rsp_sga, 597 bfa_fcxp_get_sgaddr_t get_rsp_sga,
594 bfa_fcxp_get_sglen_t get_rsp_sglen); 598 bfa_fcxp_get_sglen_t get_rsp_sglen,
595void bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe, 599 bfa_boolean_t req);
600void bfa_fcxp_req_rsp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
596 bfa_fcxp_alloc_cbfn_t alloc_cbfn, 601 bfa_fcxp_alloc_cbfn_t alloc_cbfn,
597 void *cbarg, void *bfad_fcxp, 602 void *cbarg, void *bfad_fcxp,
598 int nreq_sgles, int nrsp_sgles, 603 int nreq_sgles, int nrsp_sgles,
599 bfa_fcxp_get_sgaddr_t get_req_sga, 604 bfa_fcxp_get_sgaddr_t get_req_sga,
600 bfa_fcxp_get_sglen_t get_req_sglen, 605 bfa_fcxp_get_sglen_t get_req_sglen,
601 bfa_fcxp_get_sgaddr_t get_rsp_sga, 606 bfa_fcxp_get_sgaddr_t get_rsp_sga,
602 bfa_fcxp_get_sglen_t get_rsp_sglen); 607 bfa_fcxp_get_sglen_t get_rsp_sglen,
608 bfa_boolean_t req);
603void bfa_fcxp_walloc_cancel(struct bfa_s *bfa, 609void bfa_fcxp_walloc_cancel(struct bfa_s *bfa,
604 struct bfa_fcxp_wqe_s *wqe); 610 struct bfa_fcxp_wqe_s *wqe);
605void bfa_fcxp_discard(struct bfa_fcxp_s *fcxp); 611void bfa_fcxp_discard(struct bfa_fcxp_s *fcxp);
@@ -658,6 +664,7 @@ u8 bfa_lps_get_fwtag(struct bfa_s *bfa, u8 lp_tag);
658u32 bfa_lps_get_base_pid(struct bfa_s *bfa); 664u32 bfa_lps_get_base_pid(struct bfa_s *bfa);
659u8 bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid); 665u8 bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid);
660void bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status); 666void bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status);
667void bfa_cb_lps_flogo_comp(void *bfad, void *uarg);
661void bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status); 668void bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status);
662void bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg); 669void bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg);
663void bfa_cb_lps_cvl_event(void *bfad, void *uarg); 670void bfa_cb_lps_cvl_event(void *bfad, void *uarg);
diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c
index 2c8f0c71307..c37494916a1 100644
--- a/drivers/scsi/bfa/bfad.c
+++ b/drivers/scsi/bfa/bfad.c
@@ -57,6 +57,7 @@ int pcie_max_read_reqsz;
57int bfa_debugfs_enable = 1; 57int bfa_debugfs_enable = 1;
58int msix_disable_cb = 0, msix_disable_ct = 0; 58int msix_disable_cb = 0, msix_disable_ct = 0;
59int max_xfer_size = BFAD_MAX_SECTORS >> 1; 59int max_xfer_size = BFAD_MAX_SECTORS >> 1;
60int max_rport_logins = BFA_FCS_MAX_RPORT_LOGINS;
60 61
61/* Firmware releated */ 62/* Firmware releated */
62u32 bfi_image_cb_size, bfi_image_ct_size, bfi_image_ct2_size; 63u32 bfi_image_cb_size, bfi_image_ct_size, bfi_image_ct2_size;
@@ -148,6 +149,8 @@ MODULE_PARM_DESC(bfa_debugfs_enable, "Enables debugfs feature, default=1,"
148module_param(max_xfer_size, int, S_IRUGO | S_IWUSR); 149module_param(max_xfer_size, int, S_IRUGO | S_IWUSR);
149MODULE_PARM_DESC(max_xfer_size, "default=32MB," 150MODULE_PARM_DESC(max_xfer_size, "default=32MB,"
150 " Range[64k|128k|256k|512k|1024k|2048k]"); 151 " Range[64k|128k|256k|512k|1024k|2048k]");
152module_param(max_rport_logins, int, S_IRUGO | S_IWUSR);
153MODULE_PARM_DESC(max_rport_logins, "Max number of logins to initiator and target rports on a port (physical/logical), default=1024");
151 154
152static void 155static void
153bfad_sm_uninit(struct bfad_s *bfad, enum bfad_sm_event event); 156bfad_sm_uninit(struct bfad_s *bfad, enum bfad_sm_event event);
@@ -736,6 +739,9 @@ bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad)
736 } 739 }
737 } 740 }
738 741
742 /* Enable PCIE Advanced Error Recovery (AER) if kernel supports */
743 pci_enable_pcie_error_reporting(pdev);
744
739 bfad->pci_bar0_kva = pci_iomap(pdev, 0, pci_resource_len(pdev, 0)); 745 bfad->pci_bar0_kva = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
740 bfad->pci_bar2_kva = pci_iomap(pdev, 2, pci_resource_len(pdev, 2)); 746 bfad->pci_bar2_kva = pci_iomap(pdev, 2, pci_resource_len(pdev, 2));
741 747
@@ -806,6 +812,8 @@ bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad)
806 } 812 }
807 } 813 }
808 814
815 pci_save_state(pdev);
816
809 return 0; 817 return 0;
810 818
811out_release_region: 819out_release_region:
@@ -822,6 +830,8 @@ bfad_pci_uninit(struct pci_dev *pdev, struct bfad_s *bfad)
822 pci_iounmap(pdev, bfad->pci_bar0_kva); 830 pci_iounmap(pdev, bfad->pci_bar0_kva);
823 pci_iounmap(pdev, bfad->pci_bar2_kva); 831 pci_iounmap(pdev, bfad->pci_bar2_kva);
824 pci_release_regions(pdev); 832 pci_release_regions(pdev);
833 /* Disable PCIE Advanced Error Recovery (AER) */
834 pci_disable_pcie_error_reporting(pdev);
825 pci_disable_device(pdev); 835 pci_disable_device(pdev);
826 pci_set_drvdata(pdev, NULL); 836 pci_set_drvdata(pdev, NULL);
827} 837}
@@ -1258,6 +1268,16 @@ bfad_setup_intr(struct bfad_s *bfad)
1258 1268
1259 error = pci_enable_msix(bfad->pcidev, msix_entries, bfad->nvec); 1269 error = pci_enable_msix(bfad->pcidev, msix_entries, bfad->nvec);
1260 if (error) { 1270 if (error) {
1271 /* In CT1 & CT2, try to allocate just one vector */
1272 if (bfa_asic_id_ctc(pdev->device)) {
1273 printk(KERN_WARNING "bfa %s: trying one msix "
1274 "vector failed to allocate %d[%d]\n",
1275 bfad->pci_name, bfad->nvec, error);
1276 bfad->nvec = 1;
1277 error = pci_enable_msix(bfad->pcidev,
1278 msix_entries, bfad->nvec);
1279 }
1280
1261 /* 1281 /*
1262 * Only error number of vector is available. 1282 * Only error number of vector is available.
1263 * We don't have a mechanism to map multiple 1283 * We don't have a mechanism to map multiple
@@ -1267,12 +1287,13 @@ bfad_setup_intr(struct bfad_s *bfad)
1267 * vectors. Linux doesn't duplicate vectors 1287 * vectors. Linux doesn't duplicate vectors
1268 * in the MSIX table for this case. 1288 * in the MSIX table for this case.
1269 */ 1289 */
1270 1290 if (error) {
1271 printk(KERN_WARNING "bfad%d: " 1291 printk(KERN_WARNING "bfad%d: "
1272 "pci_enable_msix failed (%d)," 1292 "pci_enable_msix failed (%d), "
1273 " use line based.\n", bfad->inst_no, error); 1293 "use line based.\n",
1274 1294 bfad->inst_no, error);
1275 goto line_based; 1295 goto line_based;
1296 }
1276 } 1297 }
1277 1298
1278 /* Disable INTX in MSI-X mode */ 1299 /* Disable INTX in MSI-X mode */
@@ -1470,6 +1491,197 @@ bfad_pci_remove(struct pci_dev *pdev)
1470 kfree(bfad); 1491 kfree(bfad);
1471} 1492}
1472 1493
1494/*
1495 * PCI Error Recovery entry, error detected.
1496 */
1497static pci_ers_result_t
1498bfad_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
1499{
1500 struct bfad_s *bfad = pci_get_drvdata(pdev);
1501 unsigned long flags;
1502 pci_ers_result_t ret = PCI_ERS_RESULT_NONE;
1503
1504 dev_printk(KERN_ERR, &pdev->dev,
1505 "error detected state: %d - flags: 0x%x\n",
1506 state, bfad->bfad_flags);
1507
1508 switch (state) {
1509 case pci_channel_io_normal: /* non-fatal error */
1510 spin_lock_irqsave(&bfad->bfad_lock, flags);
1511 bfad->bfad_flags &= ~BFAD_EEH_BUSY;
1512 /* Suspend/fail all bfa operations */
1513 bfa_ioc_suspend(&bfad->bfa.ioc);
1514 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1515 del_timer_sync(&bfad->hal_tmo);
1516 ret = PCI_ERS_RESULT_CAN_RECOVER;
1517 break;
1518 case pci_channel_io_frozen: /* fatal error */
1519 init_completion(&bfad->comp);
1520 spin_lock_irqsave(&bfad->bfad_lock, flags);
1521 bfad->bfad_flags |= BFAD_EEH_BUSY;
1522 /* Suspend/fail all bfa operations */
1523 bfa_ioc_suspend(&bfad->bfa.ioc);
1524 bfa_fcs_stop(&bfad->bfa_fcs);
1525 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1526 wait_for_completion(&bfad->comp);
1527
1528 bfad_remove_intr(bfad);
1529 del_timer_sync(&bfad->hal_tmo);
1530 pci_disable_device(pdev);
1531 ret = PCI_ERS_RESULT_NEED_RESET;
1532 break;
1533 case pci_channel_io_perm_failure: /* PCI Card is DEAD */
1534 spin_lock_irqsave(&bfad->bfad_lock, flags);
1535 bfad->bfad_flags |= BFAD_EEH_BUSY |
1536 BFAD_EEH_PCI_CHANNEL_IO_PERM_FAILURE;
1537 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1538
1539 /* If the error_detected handler is called with the reason
1540 * pci_channel_io_perm_failure - it will subsequently call
1541 * pci_remove() entry point to remove the pci device from the
1542 * system - So defer the cleanup to pci_remove(); cleaning up
1543 * here causes inconsistent state during pci_remove().
1544 */
1545 ret = PCI_ERS_RESULT_DISCONNECT;
1546 break;
1547 default:
1548 WARN_ON(1);
1549 }
1550
1551 return ret;
1552}
1553
1554int
1555restart_bfa(struct bfad_s *bfad)
1556{
1557 unsigned long flags;
1558 struct pci_dev *pdev = bfad->pcidev;
1559
1560 bfa_attach(&bfad->bfa, bfad, &bfad->ioc_cfg,
1561 &bfad->meminfo, &bfad->hal_pcidev);
1562
1563 /* Enable Interrupt and wait bfa_init completion */
1564 if (bfad_setup_intr(bfad)) {
1565 dev_printk(KERN_WARNING, &pdev->dev,
1566 "%s: bfad_setup_intr failed\n", bfad->pci_name);
1567 bfa_sm_send_event(bfad, BFAD_E_INTR_INIT_FAILED);
1568 return -1;
1569 }
1570
1571 init_completion(&bfad->comp);
1572 spin_lock_irqsave(&bfad->bfad_lock, flags);
1573 bfa_iocfc_init(&bfad->bfa);
1574 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1575
1576 /* Set up interrupt handler for each vectors */
1577 if ((bfad->bfad_flags & BFAD_MSIX_ON) &&
1578 bfad_install_msix_handler(bfad))
1579 dev_printk(KERN_WARNING, &pdev->dev,
1580 "%s: install_msix failed.\n", bfad->pci_name);
1581
1582 bfad_init_timer(bfad);
1583 wait_for_completion(&bfad->comp);
1584 bfad_drv_start(bfad);
1585
1586 return 0;
1587}
1588
1589/*
1590 * PCI Error Recovery entry, re-initialize the chip.
1591 */
1592static pci_ers_result_t
1593bfad_pci_slot_reset(struct pci_dev *pdev)
1594{
1595 struct bfad_s *bfad = pci_get_drvdata(pdev);
1596 u8 byte;
1597
1598 dev_printk(KERN_ERR, &pdev->dev,
1599 "bfad_pci_slot_reset flags: 0x%x\n", bfad->bfad_flags);
1600
1601 if (pci_enable_device(pdev)) {
1602 dev_printk(KERN_ERR, &pdev->dev, "Cannot re-enable "
1603 "PCI device after reset.\n");
1604 return PCI_ERS_RESULT_DISCONNECT;
1605 }
1606
1607 pci_restore_state(pdev);
1608
1609 /*
1610 * Read some byte (e.g. DMA max. payload size which can't
1611 * be 0xff any time) to make sure - we did not hit another PCI error
1612 * in the middle of recovery. If we did, then declare permanent failure.
1613 */
1614 pci_read_config_byte(pdev, 0x68, &byte);
1615 if (byte == 0xff) {
1616 dev_printk(KERN_ERR, &pdev->dev,
1617 "slot_reset failed ... got another PCI error !\n");
1618 goto out_disable_device;
1619 }
1620
1621 pci_save_state(pdev);
1622 pci_set_master(pdev);
1623
1624 if (pci_set_dma_mask(bfad->pcidev, DMA_BIT_MASK(64)) != 0)
1625 if (pci_set_dma_mask(bfad->pcidev, DMA_BIT_MASK(32)) != 0)
1626 goto out_disable_device;
1627
1628 pci_cleanup_aer_uncorrect_error_status(pdev);
1629
1630 if (restart_bfa(bfad) == -1)
1631 goto out_disable_device;
1632
1633 pci_enable_pcie_error_reporting(pdev);
1634 dev_printk(KERN_WARNING, &pdev->dev,
1635 "slot_reset completed flags: 0x%x!\n", bfad->bfad_flags);
1636
1637 return PCI_ERS_RESULT_RECOVERED;
1638
1639out_disable_device:
1640 pci_disable_device(pdev);
1641 return PCI_ERS_RESULT_DISCONNECT;
1642}
1643
1644static pci_ers_result_t
1645bfad_pci_mmio_enabled(struct pci_dev *pdev)
1646{
1647 unsigned long flags;
1648 struct bfad_s *bfad = pci_get_drvdata(pdev);
1649
1650 dev_printk(KERN_INFO, &pdev->dev, "mmio_enabled\n");
1651
1652 /* Fetch FW diagnostic information */
1653 bfa_ioc_debug_save_ftrc(&bfad->bfa.ioc);
1654
1655 /* Cancel all pending IOs */
1656 spin_lock_irqsave(&bfad->bfad_lock, flags);
1657 init_completion(&bfad->comp);
1658 bfa_fcs_stop(&bfad->bfa_fcs);
1659 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1660 wait_for_completion(&bfad->comp);
1661
1662 bfad_remove_intr(bfad);
1663 del_timer_sync(&bfad->hal_tmo);
1664 pci_disable_device(pdev);
1665
1666 return PCI_ERS_RESULT_NEED_RESET;
1667}
1668
1669static void
1670bfad_pci_resume(struct pci_dev *pdev)
1671{
1672 unsigned long flags;
1673 struct bfad_s *bfad = pci_get_drvdata(pdev);
1674
1675 dev_printk(KERN_WARNING, &pdev->dev, "resume\n");
1676
1677 /* wait until the link is online */
1678 bfad_rport_online_wait(bfad);
1679
1680 spin_lock_irqsave(&bfad->bfad_lock, flags);
1681 bfad->bfad_flags &= ~BFAD_EEH_BUSY;
1682 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1683}
1684
1473struct pci_device_id bfad_id_table[] = { 1685struct pci_device_id bfad_id_table[] = {
1474 { 1686 {
1475 .vendor = BFA_PCI_VENDOR_ID_BROCADE, 1687 .vendor = BFA_PCI_VENDOR_ID_BROCADE,
@@ -1513,11 +1725,22 @@ struct pci_device_id bfad_id_table[] = {
1513 1725
1514MODULE_DEVICE_TABLE(pci, bfad_id_table); 1726MODULE_DEVICE_TABLE(pci, bfad_id_table);
1515 1727
1728/*
1729 * PCI error recovery handlers.
1730 */
1731static struct pci_error_handlers bfad_err_handler = {
1732 .error_detected = bfad_pci_error_detected,
1733 .slot_reset = bfad_pci_slot_reset,
1734 .mmio_enabled = bfad_pci_mmio_enabled,
1735 .resume = bfad_pci_resume,
1736};
1737
1516static struct pci_driver bfad_pci_driver = { 1738static struct pci_driver bfad_pci_driver = {
1517 .name = BFAD_DRIVER_NAME, 1739 .name = BFAD_DRIVER_NAME,
1518 .id_table = bfad_id_table, 1740 .id_table = bfad_id_table,
1519 .probe = bfad_pci_probe, 1741 .probe = bfad_pci_probe,
1520 .remove = __devexit_p(bfad_pci_remove), 1742 .remove = __devexit_p(bfad_pci_remove),
1743 .err_handler = &bfad_err_handler,
1521}; 1744};
1522 1745
1523/* 1746/*
@@ -1546,6 +1769,7 @@ bfad_init(void)
1546 1769
1547 bfa_auto_recover = ioc_auto_recover; 1770 bfa_auto_recover = ioc_auto_recover;
1548 bfa_fcs_rport_set_del_timeout(rport_del_timeout); 1771 bfa_fcs_rport_set_del_timeout(rport_del_timeout);
1772 bfa_fcs_rport_set_max_logins(max_rport_logins);
1549 1773
1550 error = pci_register_driver(&bfad_pci_driver); 1774 error = pci_register_driver(&bfad_pci_driver);
1551 if (error) { 1775 if (error) {
diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c
index b8392744017..72f5dc32cc1 100644
--- a/drivers/scsi/bfa/bfad_attr.c
+++ b/drivers/scsi/bfa/bfad_attr.c
@@ -587,6 +587,37 @@ bfad_im_vport_disable(struct fc_vport *fc_vport, bool disable)
587 return 0; 587 return 0;
588} 588}
589 589
590void
591bfad_im_vport_set_symbolic_name(struct fc_vport *fc_vport)
592{
593 struct bfad_vport_s *vport = (struct bfad_vport_s *)fc_vport->dd_data;
594 struct bfad_im_port_s *im_port =
595 (struct bfad_im_port_s *)vport->drv_port.im_port;
596 struct bfad_s *bfad = im_port->bfad;
597 struct Scsi_Host *vshost = vport->drv_port.im_port->shost;
598 char *sym_name = fc_vport->symbolic_name;
599 struct bfa_fcs_vport_s *fcs_vport;
600 wwn_t pwwn;
601 unsigned long flags;
602
603 u64_to_wwn(fc_host_port_name(vshost), (u8 *)&pwwn);
604
605 spin_lock_irqsave(&bfad->bfad_lock, flags);
606 fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, 0, pwwn);
607 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
608
609 if (fcs_vport == NULL)
610 return;
611
612 spin_lock_irqsave(&bfad->bfad_lock, flags);
613 if (strlen(sym_name) > 0) {
614 strcpy(fcs_vport->lport.port_cfg.sym_name.symname, sym_name);
615 bfa_fcs_lport_ns_util_send_rspn_id(
616 BFA_FCS_GET_NS_FROM_PORT((&fcs_vport->lport)), NULL);
617 }
618 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
619}
620
590struct fc_function_template bfad_im_fc_function_template = { 621struct fc_function_template bfad_im_fc_function_template = {
591 622
592 /* Target dynamic attributes */ 623 /* Target dynamic attributes */
@@ -640,6 +671,7 @@ struct fc_function_template bfad_im_fc_function_template = {
640 .vport_create = bfad_im_vport_create, 671 .vport_create = bfad_im_vport_create,
641 .vport_delete = bfad_im_vport_delete, 672 .vport_delete = bfad_im_vport_delete,
642 .vport_disable = bfad_im_vport_disable, 673 .vport_disable = bfad_im_vport_disable,
674 .set_vport_symbolic_name = bfad_im_vport_set_symbolic_name,
643 .bsg_request = bfad_im_bsg_request, 675 .bsg_request = bfad_im_bsg_request,
644 .bsg_timeout = bfad_im_bsg_timeout, 676 .bsg_timeout = bfad_im_bsg_timeout,
645}; 677};
@@ -792,6 +824,13 @@ bfad_im_model_desc_show(struct device *dev, struct device_attribute *attr,
792 else if (nports == 2 && !bfa_ioc_is_cna(&bfad->bfa.ioc)) 824 else if (nports == 2 && !bfa_ioc_is_cna(&bfad->bfa.ioc))
793 snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, 825 snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
794 "Brocade 16Gbps PCIe dual port FC HBA"); 826 "Brocade 16Gbps PCIe dual port FC HBA");
827 } else if (!strcmp(model, "Brocade-1867")) {
828 if (nports == 1 && !bfa_ioc_is_cna(&bfad->bfa.ioc))
829 snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
830 "Brocade 16Gbps PCIe single port FC HBA for IBM");
831 else if (nports == 2 && !bfa_ioc_is_cna(&bfad->bfa.ioc))
832 snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
833 "Brocade 16Gbps PCIe dual port FC HBA for IBM");
795 } else 834 } else
796 snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, 835 snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
797 "Invalid Model"); 836 "Invalid Model");
@@ -909,15 +948,16 @@ bfad_im_num_of_discovered_ports_show(struct device *dev,
909 struct bfad_port_s *port = im_port->port; 948 struct bfad_port_s *port = im_port->port;
910 struct bfad_s *bfad = im_port->bfad; 949 struct bfad_s *bfad = im_port->bfad;
911 int nrports = 2048; 950 int nrports = 2048;
912 wwn_t *rports = NULL; 951 struct bfa_rport_qualifier_s *rports = NULL;
913 unsigned long flags; 952 unsigned long flags;
914 953
915 rports = kzalloc(sizeof(wwn_t) * nrports , GFP_ATOMIC); 954 rports = kzalloc(sizeof(struct bfa_rport_qualifier_s) * nrports,
955 GFP_ATOMIC);
916 if (rports == NULL) 956 if (rports == NULL)
917 return snprintf(buf, PAGE_SIZE, "Failed\n"); 957 return snprintf(buf, PAGE_SIZE, "Failed\n");
918 958
919 spin_lock_irqsave(&bfad->bfad_lock, flags); 959 spin_lock_irqsave(&bfad->bfad_lock, flags);
920 bfa_fcs_lport_get_rports(port->fcs_port, rports, &nrports); 960 bfa_fcs_lport_get_rport_quals(port->fcs_port, rports, &nrports);
921 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 961 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
922 kfree(rports); 962 kfree(rports);
923 963
diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c
index 9c1495b321d..0afa39076ce 100644
--- a/drivers/scsi/bfa/bfad_bsg.c
+++ b/drivers/scsi/bfa/bfad_bsg.c
@@ -535,7 +535,8 @@ bfad_iocmd_lport_get_rports(struct bfad_s *bfad, void *cmd,
535 535
536 if (bfad_chk_iocmd_sz(payload_len, 536 if (bfad_chk_iocmd_sz(payload_len,
537 sizeof(struct bfa_bsg_lport_get_rports_s), 537 sizeof(struct bfa_bsg_lport_get_rports_s),
538 sizeof(wwn_t) * iocmd->nrports) != BFA_STATUS_OK) { 538 sizeof(struct bfa_rport_qualifier_s) * iocmd->nrports)
539 != BFA_STATUS_OK) {
539 iocmd->status = BFA_STATUS_VERSION_FAIL; 540 iocmd->status = BFA_STATUS_VERSION_FAIL;
540 return 0; 541 return 0;
541 } 542 }
@@ -552,8 +553,9 @@ bfad_iocmd_lport_get_rports(struct bfad_s *bfad, void *cmd,
552 goto out; 553 goto out;
553 } 554 }
554 555
555 bfa_fcs_lport_get_rports(fcs_port, (wwn_t *)iocmd_bufptr, 556 bfa_fcs_lport_get_rport_quals(fcs_port,
556 &iocmd->nrports); 557 (struct bfa_rport_qualifier_s *)iocmd_bufptr,
558 &iocmd->nrports);
557 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 559 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
558 iocmd->status = BFA_STATUS_OK; 560 iocmd->status = BFA_STATUS_OK;
559out: 561out:
@@ -578,7 +580,11 @@ bfad_iocmd_rport_get_attr(struct bfad_s *bfad, void *cmd)
578 goto out; 580 goto out;
579 } 581 }
580 582
581 fcs_rport = bfa_fcs_rport_lookup(fcs_port, iocmd->rpwwn); 583 if (iocmd->pid)
584 fcs_rport = bfa_fcs_lport_get_rport_by_qualifier(fcs_port,
585 iocmd->rpwwn, iocmd->pid);
586 else
587 fcs_rport = bfa_fcs_rport_lookup(fcs_port, iocmd->rpwwn);
582 if (fcs_rport == NULL) { 588 if (fcs_rport == NULL) {
583 bfa_trc(bfad, 0); 589 bfa_trc(bfad, 0);
584 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 590 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
@@ -671,9 +677,11 @@ bfad_iocmd_rport_get_stats(struct bfad_s *bfad, void *cmd)
671 677
672 memcpy((void *)&iocmd->stats, (void *)&fcs_rport->stats, 678 memcpy((void *)&iocmd->stats, (void *)&fcs_rport->stats,
673 sizeof(struct bfa_rport_stats_s)); 679 sizeof(struct bfa_rport_stats_s));
674 memcpy((void *)&iocmd->stats.hal_stats, 680 if (bfa_fcs_rport_get_halrport(fcs_rport)) {
675 (void *)&(bfa_fcs_rport_get_halrport(fcs_rport)->stats), 681 memcpy((void *)&iocmd->stats.hal_stats,
676 sizeof(struct bfa_rport_hal_stats_s)); 682 (void *)&(bfa_fcs_rport_get_halrport(fcs_rport)->stats),
683 sizeof(struct bfa_rport_hal_stats_s));
684 }
677 685
678 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 686 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
679 iocmd->status = BFA_STATUS_OK; 687 iocmd->status = BFA_STATUS_OK;
@@ -709,7 +717,8 @@ bfad_iocmd_rport_clr_stats(struct bfad_s *bfad, void *cmd)
709 717
710 memset((char *)&fcs_rport->stats, 0, sizeof(struct bfa_rport_stats_s)); 718 memset((char *)&fcs_rport->stats, 0, sizeof(struct bfa_rport_stats_s));
711 rport = bfa_fcs_rport_get_halrport(fcs_rport); 719 rport = bfa_fcs_rport_get_halrport(fcs_rport);
712 memset(&rport->stats, 0, sizeof(rport->stats)); 720 if (rport)
721 memset(&rport->stats, 0, sizeof(rport->stats));
713 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 722 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
714 iocmd->status = BFA_STATUS_OK; 723 iocmd->status = BFA_STATUS_OK;
715out: 724out:
@@ -744,7 +753,8 @@ bfad_iocmd_rport_set_speed(struct bfad_s *bfad, void *cmd)
744 fcs_rport->rpf.assigned_speed = iocmd->speed; 753 fcs_rport->rpf.assigned_speed = iocmd->speed;
745 /* Set this speed in f/w only if the RPSC speed is not available */ 754 /* Set this speed in f/w only if the RPSC speed is not available */
746 if (fcs_rport->rpf.rpsc_speed == BFA_PORT_SPEED_UNKNOWN) 755 if (fcs_rport->rpf.rpsc_speed == BFA_PORT_SPEED_UNKNOWN)
747 bfa_rport_speed(fcs_rport->bfa_rport, iocmd->speed); 756 if (fcs_rport->bfa_rport)
757 bfa_rport_speed(fcs_rport->bfa_rport, iocmd->speed);
748 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 758 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
749 iocmd->status = BFA_STATUS_OK; 759 iocmd->status = BFA_STATUS_OK;
750out: 760out:
@@ -1030,9 +1040,10 @@ bfad_iocmd_itnim_get_iostats(struct bfad_s *bfad, void *cmd)
1030 iocmd->status = BFA_STATUS_UNKNOWN_RWWN; 1040 iocmd->status = BFA_STATUS_UNKNOWN_RWWN;
1031 else { 1041 else {
1032 iocmd->status = BFA_STATUS_OK; 1042 iocmd->status = BFA_STATUS_OK;
1033 memcpy((void *)&iocmd->iostats, (void *) 1043 if (bfa_fcs_itnim_get_halitn(itnim))
1034 &(bfa_fcs_itnim_get_halitn(itnim)->stats), 1044 memcpy((void *)&iocmd->iostats, (void *)
1035 sizeof(struct bfa_itnim_iostats_s)); 1045 &(bfa_fcs_itnim_get_halitn(itnim)->stats),
1046 sizeof(struct bfa_itnim_iostats_s));
1036 } 1047 }
1037 } 1048 }
1038 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 1049 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
@@ -2949,13 +2960,13 @@ bfad_fcxp_bsg_send(struct fc_bsg_job *job, struct bfad_fcxp *drv_fcxp,
2949 spin_lock_irqsave(&bfad->bfad_lock, flags); 2960 spin_lock_irqsave(&bfad->bfad_lock, flags);
2950 2961
2951 /* Allocate bfa_fcxp structure */ 2962 /* Allocate bfa_fcxp structure */
2952 hal_fcxp = bfa_fcxp_alloc(drv_fcxp, &bfad->bfa, 2963 hal_fcxp = bfa_fcxp_req_rsp_alloc(drv_fcxp, &bfad->bfa,
2953 drv_fcxp->num_req_sgles, 2964 drv_fcxp->num_req_sgles,
2954 drv_fcxp->num_rsp_sgles, 2965 drv_fcxp->num_rsp_sgles,
2955 bfad_fcxp_get_req_sgaddr_cb, 2966 bfad_fcxp_get_req_sgaddr_cb,
2956 bfad_fcxp_get_req_sglen_cb, 2967 bfad_fcxp_get_req_sglen_cb,
2957 bfad_fcxp_get_rsp_sgaddr_cb, 2968 bfad_fcxp_get_rsp_sgaddr_cb,
2958 bfad_fcxp_get_rsp_sglen_cb); 2969 bfad_fcxp_get_rsp_sglen_cb, BFA_TRUE);
2959 if (!hal_fcxp) { 2970 if (!hal_fcxp) {
2960 bfa_trc(bfad, 0); 2971 bfa_trc(bfad, 0);
2961 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 2972 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
diff --git a/drivers/scsi/bfa/bfad_bsg.h b/drivers/scsi/bfa/bfad_bsg.h
index 17ad6728313..8c569ddb750 100644
--- a/drivers/scsi/bfa/bfad_bsg.h
+++ b/drivers/scsi/bfa/bfad_bsg.h
@@ -319,6 +319,8 @@ struct bfa_bsg_rport_attr_s {
319 u16 vf_id; 319 u16 vf_id;
320 wwn_t pwwn; 320 wwn_t pwwn;
321 wwn_t rpwwn; 321 wwn_t rpwwn;
322 u32 pid;
323 u32 rsvd;
322 struct bfa_rport_attr_s attr; 324 struct bfa_rport_attr_s attr;
323}; 325};
324 326
diff --git a/drivers/scsi/bfa/bfad_drv.h b/drivers/scsi/bfa/bfad_drv.h
index 7f74f1d1912..1840651ce1d 100644
--- a/drivers/scsi/bfa/bfad_drv.h
+++ b/drivers/scsi/bfa/bfad_drv.h
@@ -37,6 +37,7 @@
37#include <linux/vmalloc.h> 37#include <linux/vmalloc.h>
38#include <linux/workqueue.h> 38#include <linux/workqueue.h>
39#include <linux/bitops.h> 39#include <linux/bitops.h>
40#include <linux/aer.h>
40#include <scsi/scsi.h> 41#include <scsi/scsi.h>
41#include <scsi/scsi_host.h> 42#include <scsi/scsi_host.h>
42#include <scsi/scsi_tcq.h> 43#include <scsi/scsi_tcq.h>
@@ -56,7 +57,7 @@
56#ifdef BFA_DRIVER_VERSION 57#ifdef BFA_DRIVER_VERSION
57#define BFAD_DRIVER_VERSION BFA_DRIVER_VERSION 58#define BFAD_DRIVER_VERSION BFA_DRIVER_VERSION
58#else 59#else
59#define BFAD_DRIVER_VERSION "3.0.23.0" 60#define BFAD_DRIVER_VERSION "3.1.2.0"
60#endif 61#endif
61 62
62#define BFAD_PROTO_NAME FCPI_NAME 63#define BFAD_PROTO_NAME FCPI_NAME
@@ -81,6 +82,8 @@
81#define BFAD_FC4_PROBE_DONE 0x00000200 82#define BFAD_FC4_PROBE_DONE 0x00000200
82#define BFAD_PORT_DELETE 0x00000001 83#define BFAD_PORT_DELETE 0x00000001
83#define BFAD_INTX_ON 0x00000400 84#define BFAD_INTX_ON 0x00000400
85#define BFAD_EEH_BUSY 0x00000800
86#define BFAD_EEH_PCI_CHANNEL_IO_PERM_FAILURE 0x00001000
84/* 87/*
85 * BFAD related definition 88 * BFAD related definition
86 */ 89 */
diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c
index 2eebf8d4d58..8f92732655c 100644
--- a/drivers/scsi/bfa/bfad_im.c
+++ b/drivers/scsi/bfa/bfad_im.c
@@ -1216,6 +1216,15 @@ bfad_im_queuecommand_lck(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd
1216 return 0; 1216 return 0;
1217 } 1217 }
1218 1218
1219 if (bfad->bfad_flags & BFAD_EEH_BUSY) {
1220 if (bfad->bfad_flags & BFAD_EEH_PCI_CHANNEL_IO_PERM_FAILURE)
1221 cmnd->result = DID_NO_CONNECT << 16;
1222 else
1223 cmnd->result = DID_REQUEUE << 16;
1224 done(cmnd);
1225 return 0;
1226 }
1227
1219 sg_cnt = scsi_dma_map(cmnd); 1228 sg_cnt = scsi_dma_map(cmnd);
1220 if (sg_cnt < 0) 1229 if (sg_cnt < 0)
1221 return SCSI_MLQUEUE_HOST_BUSY; 1230 return SCSI_MLQUEUE_HOST_BUSY;