blob: 7a2cf7713a959c89c3c1ba9f88bd5500a077b97d [file] [log] [blame]
Jing Huang7725ccf2009-09-23 17:46:15 -07001/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002 * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
Jing Huang7725ccf2009-09-23 17:46:15 -07003 * All rights reserved
4 * www.brocade.com
5 *
6 * Linux driver for Brocade Fibre Channel Host Bus Adapter.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License (GPL) Version 2 as
10 * published by the Free Software Foundation
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 */
17
Maggie Zhangf16a1752010-12-09 19:12:32 -080018#include "bfad_drv.h"
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070019#include "bfa_fcs.h"
20#include "bfa_fcbuild.h"
21#include "bfa_fc.h"
Jing Huang7725ccf2009-09-23 17:46:15 -070022
23BFA_TRC_FILE(FCS, PORT);
24
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070025static void bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port,
26 struct fchs_s *rx_fchs, u8 reason_code,
27 u8 reason_code_expl);
28static void bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
29 struct fchs_s *rx_fchs, struct fc_logi_s *plogi);
30static void bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port);
31static void bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port);
32static void bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port);
33static void bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port);
34static void bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port);
35static void bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port);
36static void bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port,
Jing Huang7725ccf2009-09-23 17:46:15 -070037 struct fchs_s *rx_fchs,
38 struct fc_echo_s *echo, u16 len);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070039static void bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port,
Jing Huang7725ccf2009-09-23 17:46:15 -070040 struct fchs_s *rx_fchs,
41 struct fc_rnid_cmd_s *rnid, u16 len);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070042static void bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port,
Jing Huang7725ccf2009-09-23 17:46:15 -070043 struct fc_rnid_general_topology_data_s *gen_topo_data);
44
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070045static void bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port);
46static void bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port);
47static void bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port);
48
49static void bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port);
50static void bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port);
51static void bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port);
52
Jing Huang7725ccf2009-09-23 17:46:15 -070053static struct {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070054 void (*init) (struct bfa_fcs_lport_s *port);
55 void (*online) (struct bfa_fcs_lport_s *port);
56 void (*offline) (struct bfa_fcs_lport_s *port);
Jing Huang7725ccf2009-09-23 17:46:15 -070057} __port_action[] = {
58 {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070059 bfa_fcs_lport_unknown_init, bfa_fcs_lport_unknown_online,
60 bfa_fcs_lport_unknown_offline}, {
61 bfa_fcs_lport_fab_init, bfa_fcs_lport_fab_online,
62 bfa_fcs_lport_fab_offline}, {
63 bfa_fcs_lport_n2n_init, bfa_fcs_lport_n2n_online,
64 bfa_fcs_lport_n2n_offline},
65 };
Jing Huang7725ccf2009-09-23 17:46:15 -070066
Jing Huang5fbe25c2010-10-18 17:17:23 -070067/*
Jing Huang7725ccf2009-09-23 17:46:15 -070068 * fcs_port_sm FCS logical port state machine
69 */
70
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070071enum bfa_fcs_lport_event {
Jing Huang7725ccf2009-09-23 17:46:15 -070072 BFA_FCS_PORT_SM_CREATE = 1,
73 BFA_FCS_PORT_SM_ONLINE = 2,
74 BFA_FCS_PORT_SM_OFFLINE = 3,
75 BFA_FCS_PORT_SM_DELETE = 4,
76 BFA_FCS_PORT_SM_DELRPORT = 5,
77};
78
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070079static void bfa_fcs_lport_sm_uninit(struct bfa_fcs_lport_s *port,
80 enum bfa_fcs_lport_event event);
81static void bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
82 enum bfa_fcs_lport_event event);
83static void bfa_fcs_lport_sm_online(struct bfa_fcs_lport_s *port,
84 enum bfa_fcs_lport_event event);
85static void bfa_fcs_lport_sm_offline(struct bfa_fcs_lport_s *port,
86 enum bfa_fcs_lport_event event);
87static void bfa_fcs_lport_sm_deleting(struct bfa_fcs_lport_s *port,
88 enum bfa_fcs_lport_event event);
Jing Huang7725ccf2009-09-23 17:46:15 -070089
90static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070091bfa_fcs_lport_sm_uninit(
92 struct bfa_fcs_lport_s *port,
93 enum bfa_fcs_lport_event event)
Jing Huang7725ccf2009-09-23 17:46:15 -070094{
95 bfa_trc(port->fcs, port->port_cfg.pwwn);
96 bfa_trc(port->fcs, event);
97
98 switch (event) {
99 case BFA_FCS_PORT_SM_CREATE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700100 bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
Jing Huang7725ccf2009-09-23 17:46:15 -0700101 break;
102
103 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800104 bfa_sm_fault(port->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700105 }
106}
107
108static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700109bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
110 enum bfa_fcs_lport_event event)
Jing Huang7725ccf2009-09-23 17:46:15 -0700111{
112 bfa_trc(port->fcs, port->port_cfg.pwwn);
113 bfa_trc(port->fcs, event);
114
115 switch (event) {
116 case BFA_FCS_PORT_SM_ONLINE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700117 bfa_sm_set_state(port, bfa_fcs_lport_sm_online);
118 bfa_fcs_lport_online_actions(port);
Jing Huang7725ccf2009-09-23 17:46:15 -0700119 break;
120
121 case BFA_FCS_PORT_SM_DELETE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700122 bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
123 bfa_fcs_lport_deleted(port);
Jing Huang7725ccf2009-09-23 17:46:15 -0700124 break;
125
Jing Huang3e98cc02010-07-08 19:52:46 -0700126 case BFA_FCS_PORT_SM_OFFLINE:
127 break;
128
Jing Huang7725ccf2009-09-23 17:46:15 -0700129 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800130 bfa_sm_fault(port->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700131 }
132}
133
134static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700135bfa_fcs_lport_sm_online(
136 struct bfa_fcs_lport_s *port,
137 enum bfa_fcs_lport_event event)
Jing Huang7725ccf2009-09-23 17:46:15 -0700138{
139 struct bfa_fcs_rport_s *rport;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700140 struct list_head *qe, *qen;
Jing Huang7725ccf2009-09-23 17:46:15 -0700141
142 bfa_trc(port->fcs, port->port_cfg.pwwn);
143 bfa_trc(port->fcs, event);
144
145 switch (event) {
146 case BFA_FCS_PORT_SM_OFFLINE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700147 bfa_sm_set_state(port, bfa_fcs_lport_sm_offline);
148 bfa_fcs_lport_offline_actions(port);
Jing Huang7725ccf2009-09-23 17:46:15 -0700149 break;
150
151 case BFA_FCS_PORT_SM_DELETE:
152
153 __port_action[port->fabric->fab_type].offline(port);
154
155 if (port->num_rports == 0) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700156 bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
157 bfa_fcs_lport_deleted(port);
Jing Huang7725ccf2009-09-23 17:46:15 -0700158 } else {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700159 bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting);
Jing Huang7725ccf2009-09-23 17:46:15 -0700160 list_for_each_safe(qe, qen, &port->rport_q) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700161 rport = (struct bfa_fcs_rport_s *) qe;
Maggie Zhangf7f738122010-12-09 19:08:43 -0800162 bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
Jing Huang7725ccf2009-09-23 17:46:15 -0700163 }
164 }
165 break;
166
167 case BFA_FCS_PORT_SM_DELRPORT:
168 break;
169
170 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800171 bfa_sm_fault(port->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700172 }
173}
174
175static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700176bfa_fcs_lport_sm_offline(
177 struct bfa_fcs_lport_s *port,
178 enum bfa_fcs_lport_event event)
Jing Huang7725ccf2009-09-23 17:46:15 -0700179{
180 struct bfa_fcs_rport_s *rport;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700181 struct list_head *qe, *qen;
Jing Huang7725ccf2009-09-23 17:46:15 -0700182
183 bfa_trc(port->fcs, port->port_cfg.pwwn);
184 bfa_trc(port->fcs, event);
185
186 switch (event) {
187 case BFA_FCS_PORT_SM_ONLINE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700188 bfa_sm_set_state(port, bfa_fcs_lport_sm_online);
189 bfa_fcs_lport_online_actions(port);
Jing Huang7725ccf2009-09-23 17:46:15 -0700190 break;
191
192 case BFA_FCS_PORT_SM_DELETE:
193 if (port->num_rports == 0) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700194 bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
195 bfa_fcs_lport_deleted(port);
Jing Huang7725ccf2009-09-23 17:46:15 -0700196 } else {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700197 bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting);
Jing Huang7725ccf2009-09-23 17:46:15 -0700198 list_for_each_safe(qe, qen, &port->rport_q) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700199 rport = (struct bfa_fcs_rport_s *) qe;
Maggie Zhangf7f738122010-12-09 19:08:43 -0800200 bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
Jing Huang7725ccf2009-09-23 17:46:15 -0700201 }
202 }
203 break;
204
205 case BFA_FCS_PORT_SM_DELRPORT:
206 case BFA_FCS_PORT_SM_OFFLINE:
207 break;
208
209 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800210 bfa_sm_fault(port->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700211 }
212}
213
214static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700215bfa_fcs_lport_sm_deleting(
216 struct bfa_fcs_lport_s *port,
217 enum bfa_fcs_lport_event event)
Jing Huang7725ccf2009-09-23 17:46:15 -0700218{
219 bfa_trc(port->fcs, port->port_cfg.pwwn);
220 bfa_trc(port->fcs, event);
221
222 switch (event) {
223 case BFA_FCS_PORT_SM_DELRPORT:
224 if (port->num_rports == 0) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700225 bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
226 bfa_fcs_lport_deleted(port);
Jing Huang7725ccf2009-09-23 17:46:15 -0700227 }
228 break;
229
230 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800231 bfa_sm_fault(port->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700232 }
233}
234
Jing Huang5fbe25c2010-10-18 17:17:23 -0700235/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700236 * fcs_port_pvt
237 */
238
Jing Huang7725ccf2009-09-23 17:46:15 -0700239/*
240 * Send a LS reject
241 */
242static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700243bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
Jing Huang7725ccf2009-09-23 17:46:15 -0700244 u8 reason_code, u8 reason_code_expl)
245{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700246 struct fchs_s fchs;
Jing Huang7725ccf2009-09-23 17:46:15 -0700247 struct bfa_fcxp_s *fcxp;
248 struct bfa_rport_s *bfa_rport = NULL;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700249 int len;
Jing Huang7725ccf2009-09-23 17:46:15 -0700250
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700251 bfa_trc(port->fcs, rx_fchs->d_id);
Jing Huang7725ccf2009-09-23 17:46:15 -0700252 bfa_trc(port->fcs, rx_fchs->s_id);
253
254 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
255 if (!fcxp)
256 return;
257
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700258 len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
259 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
260 rx_fchs->ox_id, reason_code, reason_code_expl);
Jing Huang7725ccf2009-09-23 17:46:15 -0700261
262 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700263 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
264 FC_MAX_PDUSZ, 0);
Jing Huang7725ccf2009-09-23 17:46:15 -0700265}
266
Jing Huang5fbe25c2010-10-18 17:17:23 -0700267/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700268 * Process incoming plogi from a remote port.
269 */
270static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700271bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
272 struct fchs_s *rx_fchs, struct fc_logi_s *plogi)
Jing Huang7725ccf2009-09-23 17:46:15 -0700273{
274 struct bfa_fcs_rport_s *rport;
275
276 bfa_trc(port->fcs, rx_fchs->d_id);
277 bfa_trc(port->fcs, rx_fchs->s_id);
278
279 /*
280 * If min cfg mode is enabled, drop any incoming PLOGIs
281 */
282 if (__fcs_min_cfg(port->fcs)) {
283 bfa_trc(port->fcs, rx_fchs->s_id);
284 return;
285 }
286
287 if (fc_plogi_parse(rx_fchs) != FC_PARSE_OK) {
288 bfa_trc(port->fcs, rx_fchs->s_id);
289 /*
290 * send a LS reject
291 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700292 bfa_fcs_lport_send_ls_rjt(port, rx_fchs,
293 FC_LS_RJT_RSN_PROTOCOL_ERROR,
294 FC_LS_RJT_EXP_SPARMS_ERR_OPTIONS);
Jing Huang7725ccf2009-09-23 17:46:15 -0700295 return;
296 }
297
Jing Huang5fbe25c2010-10-18 17:17:23 -0700298 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700299 * Direct Attach P2P mode : verify address assigned by the r-port.
Jing Huang7725ccf2009-09-23 17:46:15 -0700300 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700301 if ((!bfa_fcs_fabric_is_switched(port->fabric)) &&
302 (memcmp((void *)&bfa_fcs_lport_get_pwwn(port),
303 (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
Jing Huang7725ccf2009-09-23 17:46:15 -0700304 if (BFA_FCS_PID_IS_WKA(rx_fchs->d_id)) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700305 /* Address assigned to us cannot be a WKA */
306 bfa_fcs_lport_send_ls_rjt(port, rx_fchs,
Jing Huang7725ccf2009-09-23 17:46:15 -0700307 FC_LS_RJT_RSN_PROTOCOL_ERROR,
308 FC_LS_RJT_EXP_INVALID_NPORT_ID);
309 return;
310 }
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700311 port->pid = rx_fchs->d_id;
Jing Huang7725ccf2009-09-23 17:46:15 -0700312 }
313
Jing Huang5fbe25c2010-10-18 17:17:23 -0700314 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700315 * First, check if we know the device by pwwn.
316 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700317 rport = bfa_fcs_lport_get_rport_by_pwwn(port, plogi->port_name);
Jing Huang7725ccf2009-09-23 17:46:15 -0700318 if (rport) {
Jing Huang5fbe25c2010-10-18 17:17:23 -0700319 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700320 * Direct Attach P2P mode : handle address assigned by r-port.
Jing Huang7725ccf2009-09-23 17:46:15 -0700321 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700322 if ((!bfa_fcs_fabric_is_switched(port->fabric)) &&
323 (memcmp((void *)&bfa_fcs_lport_get_pwwn(port),
324 (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
325 port->pid = rx_fchs->d_id;
Jing Huang7725ccf2009-09-23 17:46:15 -0700326 rport->pid = rx_fchs->s_id;
327 }
328 bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
329 return;
330 }
331
Jing Huang5fbe25c2010-10-18 17:17:23 -0700332 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700333 * Next, lookup rport by PID.
334 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700335 rport = bfa_fcs_lport_get_rport_by_pid(port, rx_fchs->s_id);
Jing Huang7725ccf2009-09-23 17:46:15 -0700336 if (!rport) {
Jing Huang5fbe25c2010-10-18 17:17:23 -0700337 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700338 * Inbound PLOGI from a new device.
339 */
340 bfa_fcs_rport_plogi_create(port, rx_fchs, plogi);
341 return;
342 }
343
Jing Huang5fbe25c2010-10-18 17:17:23 -0700344 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700345 * Rport is known only by PID.
346 */
347 if (rport->pwwn) {
Jing Huang5fbe25c2010-10-18 17:17:23 -0700348 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700349 * This is a different device with the same pid. Old device
350 * disappeared. Send implicit LOGO to old device.
351 */
352 bfa_assert(rport->pwwn != plogi->port_name);
Maggie Zhangf7f738122010-12-09 19:08:43 -0800353 bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
Jing Huang7725ccf2009-09-23 17:46:15 -0700354
Jing Huang5fbe25c2010-10-18 17:17:23 -0700355 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700356 * Inbound PLOGI from a new device (with old PID).
357 */
358 bfa_fcs_rport_plogi_create(port, rx_fchs, plogi);
359 return;
360 }
361
Jing Huang5fbe25c2010-10-18 17:17:23 -0700362 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700363 * PLOGI crossing each other.
364 */
365 bfa_assert(rport->pwwn == WWN_NULL);
366 bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
367}
368
369/*
370 * Process incoming ECHO.
371 * Since it does not require a login, it is processed here.
372 */
373static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700374bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
375 struct fc_echo_s *echo, u16 rx_len)
Jing Huang7725ccf2009-09-23 17:46:15 -0700376{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700377 struct fchs_s fchs;
378 struct bfa_fcxp_s *fcxp;
379 struct bfa_rport_s *bfa_rport = NULL;
380 int len, pyld_len;
Jing Huang7725ccf2009-09-23 17:46:15 -0700381
382 bfa_trc(port->fcs, rx_fchs->s_id);
383 bfa_trc(port->fcs, rx_fchs->d_id);
Jing Huang7725ccf2009-09-23 17:46:15 -0700384
385 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
386 if (!fcxp)
387 return;
388
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700389 len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
390 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
391 rx_fchs->ox_id);
Jing Huang7725ccf2009-09-23 17:46:15 -0700392
393 /*
394 * Copy the payload (if any) from the echo frame
395 */
396 pyld_len = rx_len - sizeof(struct fchs_s);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700397 bfa_trc(port->fcs, rx_len);
Jing Huang7725ccf2009-09-23 17:46:15 -0700398 bfa_trc(port->fcs, pyld_len);
399
400 if (pyld_len > len)
401 memcpy(((u8 *) bfa_fcxp_get_reqbuf(fcxp)) +
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700402 sizeof(struct fc_echo_s), (echo + 1),
403 (pyld_len - sizeof(struct fc_echo_s)));
Jing Huang7725ccf2009-09-23 17:46:15 -0700404
405 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700406 BFA_FALSE, FC_CLASS_3, pyld_len, &fchs, NULL, NULL,
407 FC_MAX_PDUSZ, 0);
Jing Huang7725ccf2009-09-23 17:46:15 -0700408}
409
410/*
411 * Process incoming RNID.
412 * Since it does not require a login, it is processed here.
413 */
414static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700415bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
416 struct fc_rnid_cmd_s *rnid, u16 rx_len)
Jing Huang7725ccf2009-09-23 17:46:15 -0700417{
418 struct fc_rnid_common_id_data_s common_id_data;
419 struct fc_rnid_general_topology_data_s gen_topo_data;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700420 struct fchs_s fchs;
Jing Huang7725ccf2009-09-23 17:46:15 -0700421 struct bfa_fcxp_s *fcxp;
422 struct bfa_rport_s *bfa_rport = NULL;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700423 u16 len;
424 u32 data_format;
Jing Huang7725ccf2009-09-23 17:46:15 -0700425
426 bfa_trc(port->fcs, rx_fchs->s_id);
427 bfa_trc(port->fcs, rx_fchs->d_id);
428 bfa_trc(port->fcs, rx_len);
429
430 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
431 if (!fcxp)
432 return;
433
434 /*
435 * Check Node Indentification Data Format
436 * We only support General Topology Discovery Format.
437 * For any other requested Data Formats, we return Common Node Id Data
438 * only, as per FC-LS.
439 */
440 bfa_trc(port->fcs, rnid->node_id_data_format);
441 if (rnid->node_id_data_format == RNID_NODEID_DATA_FORMAT_DISCOVERY) {
442 data_format = RNID_NODEID_DATA_FORMAT_DISCOVERY;
443 /*
444 * Get General topology data for this port
445 */
446 bfa_fs_port_get_gen_topo_data(port, &gen_topo_data);
447 } else {
448 data_format = RNID_NODEID_DATA_FORMAT_COMMON;
449 }
450
451 /*
452 * Copy the Node Id Info
453 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700454 common_id_data.port_name = bfa_fcs_lport_get_pwwn(port);
455 common_id_data.node_name = bfa_fcs_lport_get_nwwn(port);
Jing Huang7725ccf2009-09-23 17:46:15 -0700456
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700457 len = fc_rnid_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
458 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
459 rx_fchs->ox_id, data_format, &common_id_data,
460 &gen_topo_data);
Jing Huang7725ccf2009-09-23 17:46:15 -0700461
462 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700463 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
464 FC_MAX_PDUSZ, 0);
Jing Huang7725ccf2009-09-23 17:46:15 -0700465}
466
467/*
468 * Fill out General Topolpgy Discovery Data for RNID ELS.
469 */
470static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700471bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port,
Jing Huang7725ccf2009-09-23 17:46:15 -0700472 struct fc_rnid_general_topology_data_s *gen_topo_data)
473{
Jing Huang6a18b162010-10-18 17:08:54 -0700474 memset(gen_topo_data, 0,
Jing Huang7725ccf2009-09-23 17:46:15 -0700475 sizeof(struct fc_rnid_general_topology_data_s));
476
Jing Huangba816ea2010-10-18 17:10:50 -0700477 gen_topo_data->asso_type = cpu_to_be32(RNID_ASSOCIATED_TYPE_HOST);
Jing Huang7725ccf2009-09-23 17:46:15 -0700478 gen_topo_data->phy_port_num = 0; /* @todo */
Jing Huangba816ea2010-10-18 17:10:50 -0700479 gen_topo_data->num_attached_nodes = cpu_to_be32(1);
Jing Huang7725ccf2009-09-23 17:46:15 -0700480}
481
482static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700483bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port)
Jing Huang7725ccf2009-09-23 17:46:15 -0700484{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700485 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
486 char lpwwn_buf[BFA_STRING_32];
487
Jing Huang7725ccf2009-09-23 17:46:15 -0700488 bfa_trc(port->fcs, port->fabric->oper_type);
489
490 __port_action[port->fabric->fab_type].init(port);
491 __port_action[port->fabric->fab_type].online(port);
492
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700493 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
Jing Huang88166242010-12-09 17:11:53 -0800494 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700495 "Logical port online: WWN = %s Role = %s\n",
496 lpwwn_buf, "Initiator");
497
498 bfad->bfad_flags |= BFAD_PORT_ONLINE;
Jing Huang7725ccf2009-09-23 17:46:15 -0700499}
500
501static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700502bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port)
Jing Huang7725ccf2009-09-23 17:46:15 -0700503{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700504 struct list_head *qe, *qen;
Jing Huang7725ccf2009-09-23 17:46:15 -0700505 struct bfa_fcs_rport_s *rport;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700506 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
507 char lpwwn_buf[BFA_STRING_32];
Jing Huang7725ccf2009-09-23 17:46:15 -0700508
509 bfa_trc(port->fcs, port->fabric->oper_type);
510
511 __port_action[port->fabric->fab_type].offline(port);
512
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700513 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
Maggie Zhangf7f738122010-12-09 19:08:43 -0800514 if (bfa_sm_cmp_state(port->fabric,
515 bfa_fcs_fabric_sm_online) == BFA_TRUE)
Jing Huang88166242010-12-09 17:11:53 -0800516 BFA_LOG(KERN_ERR, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700517 "Logical port lost fabric connectivity: WWN = %s Role = %s\n",
518 lpwwn_buf, "Initiator");
Jing Huangf8ceafd2009-09-25 12:29:54 -0700519 else
Jing Huang88166242010-12-09 17:11:53 -0800520 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700521 "Logical port taken offline: WWN = %s Role = %s\n",
522 lpwwn_buf, "Initiator");
Jing Huang7725ccf2009-09-23 17:46:15 -0700523
524 list_for_each_safe(qe, qen, &port->rport_q) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700525 rport = (struct bfa_fcs_rport_s *) qe;
Maggie Zhangf7f738122010-12-09 19:08:43 -0800526 bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
Jing Huang7725ccf2009-09-23 17:46:15 -0700527 }
528}
529
530static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700531bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port)
Jing Huang7725ccf2009-09-23 17:46:15 -0700532{
533 bfa_assert(0);
534}
535
536static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700537bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port)
Jing Huang7725ccf2009-09-23 17:46:15 -0700538{
539 bfa_assert(0);
540}
541
542static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700543bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port)
Jing Huang7725ccf2009-09-23 17:46:15 -0700544{
545 bfa_assert(0);
546}
547
548static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700549bfa_fcs_lport_abts_acc(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs)
Jing Huang7725ccf2009-09-23 17:46:15 -0700550{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700551 struct fchs_s fchs;
552 struct bfa_fcxp_s *fcxp;
553 int len;
Jing Huang7725ccf2009-09-23 17:46:15 -0700554
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700555 bfa_trc(port->fcs, rx_fchs->d_id);
556 bfa_trc(port->fcs, rx_fchs->s_id);
557
558 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
559 if (!fcxp)
560 return;
561
562 len = fc_ba_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
563 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
564 rx_fchs->ox_id, 0);
565
566 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
567 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
568 FC_MAX_PDUSZ, 0);
569}
570static void
571bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port)
572{
573 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
574 char lpwwn_buf[BFA_STRING_32];
575
576 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
Jing Huang88166242010-12-09 17:11:53 -0800577 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700578 "Logical port deleted: WWN = %s Role = %s\n",
579 lpwwn_buf, "Initiator");
580
581 /* Base port will be deleted by the OS driver */
Jing Huang7725ccf2009-09-23 17:46:15 -0700582 if (port->vport) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700583 bfa_fcb_lport_delete(port->fcs->bfad, port->port_cfg.roles,
584 port->fabric->vf_drv,
585 port->vport ? port->vport->vport_drv : NULL);
Jing Huang7725ccf2009-09-23 17:46:15 -0700586 bfa_fcs_vport_delete_comp(port->vport);
587 } else {
Maggie Zhangf7f738122010-12-09 19:08:43 -0800588 bfa_wc_down(&port->fabric->wc);
Jing Huang7725ccf2009-09-23 17:46:15 -0700589 }
590}
591
592
Jing Huang5fbe25c2010-10-18 17:17:23 -0700593/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700594 * Unsolicited frame receive handling.
Jing Huang7725ccf2009-09-23 17:46:15 -0700595 */
596void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700597bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport,
598 struct fchs_s *fchs, u16 len)
Jing Huang7725ccf2009-09-23 17:46:15 -0700599{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700600 u32 pid = fchs->s_id;
Jing Huang7725ccf2009-09-23 17:46:15 -0700601 struct bfa_fcs_rport_s *rport = NULL;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700602 struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
Jing Huang7725ccf2009-09-23 17:46:15 -0700603
604 bfa_stats(lport, uf_recvs);
605
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700606 if (!bfa_fcs_lport_is_online(lport)) {
Jing Huang7725ccf2009-09-23 17:46:15 -0700607 bfa_stats(lport, uf_recv_drops);
608 return;
609 }
610
Jing Huang5fbe25c2010-10-18 17:17:23 -0700611 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700612 * First, handle ELSs that donot require a login.
613 */
614 /*
615 * Handle PLOGI first
616 */
617 if ((fchs->type == FC_TYPE_ELS) &&
618 (els_cmd->els_code == FC_ELS_PLOGI)) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700619 bfa_fcs_lport_plogi(lport, fchs, (struct fc_logi_s *) els_cmd);
Jing Huang7725ccf2009-09-23 17:46:15 -0700620 return;
621 }
622
623 /*
624 * Handle ECHO separately.
625 */
626 if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_ECHO)) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700627 bfa_fcs_lport_echo(lport, fchs,
628 (struct fc_echo_s *)els_cmd, len);
Jing Huang7725ccf2009-09-23 17:46:15 -0700629 return;
630 }
631
632 /*
633 * Handle RNID separately.
634 */
635 if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_RNID)) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700636 bfa_fcs_lport_rnid(lport, fchs,
Jing Huang7725ccf2009-09-23 17:46:15 -0700637 (struct fc_rnid_cmd_s *) els_cmd, len);
638 return;
639 }
640
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700641 if (fchs->type == FC_TYPE_BLS) {
642 if ((fchs->routing == FC_RTG_BASIC_LINK) &&
643 (fchs->cat_info == FC_CAT_ABTS))
644 bfa_fcs_lport_abts_acc(lport, fchs);
645 return;
646 }
Jing Huang5fbe25c2010-10-18 17:17:23 -0700647 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700648 * look for a matching remote port ID
649 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700650 rport = bfa_fcs_lport_get_rport_by_pid(lport, pid);
Jing Huang7725ccf2009-09-23 17:46:15 -0700651 if (rport) {
652 bfa_trc(rport->fcs, fchs->s_id);
653 bfa_trc(rport->fcs, fchs->d_id);
654 bfa_trc(rport->fcs, fchs->type);
655
656 bfa_fcs_rport_uf_recv(rport, fchs, len);
657 return;
658 }
659
Jing Huang5fbe25c2010-10-18 17:17:23 -0700660 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700661 * Only handles ELS frames for now.
662 */
663 if (fchs->type != FC_TYPE_ELS) {
664 bfa_trc(lport->fcs, fchs->type);
665 bfa_assert(0);
666 return;
667 }
668
669 bfa_trc(lport->fcs, els_cmd->els_code);
670 if (els_cmd->els_code == FC_ELS_RSCN) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700671 bfa_fcs_lport_scn_process_rscn(lport, fchs, len);
Jing Huang7725ccf2009-09-23 17:46:15 -0700672 return;
673 }
674
675 if (els_cmd->els_code == FC_ELS_LOGO) {
Jing Huang5fbe25c2010-10-18 17:17:23 -0700676 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700677 * @todo Handle LOGO frames received.
678 */
Jing Huang7725ccf2009-09-23 17:46:15 -0700679 return;
680 }
681
682 if (els_cmd->els_code == FC_ELS_PRLI) {
Jing Huang5fbe25c2010-10-18 17:17:23 -0700683 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700684 * @todo Handle PRLI frames received.
685 */
Jing Huang7725ccf2009-09-23 17:46:15 -0700686 return;
687 }
688
Jing Huang5fbe25c2010-10-18 17:17:23 -0700689 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700690 * Unhandled ELS frames. Send a LS_RJT.
691 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700692 bfa_fcs_lport_send_ls_rjt(lport, fchs, FC_LS_RJT_RSN_CMD_NOT_SUPP,
Jing Huang7725ccf2009-09-23 17:46:15 -0700693 FC_LS_RJT_EXP_NO_ADDL_INFO);
694
695}
696
Jing Huang5fbe25c2010-10-18 17:17:23 -0700697/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700698 * PID based Lookup for a R-Port in the Port R-Port Queue
699 */
700struct bfa_fcs_rport_s *
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700701bfa_fcs_lport_get_rport_by_pid(struct bfa_fcs_lport_s *port, u32 pid)
Jing Huang7725ccf2009-09-23 17:46:15 -0700702{
703 struct bfa_fcs_rport_s *rport;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700704 struct list_head *qe;
Jing Huang7725ccf2009-09-23 17:46:15 -0700705
706 list_for_each(qe, &port->rport_q) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700707 rport = (struct bfa_fcs_rport_s *) qe;
Jing Huang7725ccf2009-09-23 17:46:15 -0700708 if (rport->pid == pid)
709 return rport;
710 }
711
712 bfa_trc(port->fcs, pid);
713 return NULL;
714}
715
Jing Huang5fbe25c2010-10-18 17:17:23 -0700716/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700717 * PWWN based Lookup for a R-Port in the Port R-Port Queue
718 */
719struct bfa_fcs_rport_s *
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700720bfa_fcs_lport_get_rport_by_pwwn(struct bfa_fcs_lport_s *port, wwn_t pwwn)
Jing Huang7725ccf2009-09-23 17:46:15 -0700721{
722 struct bfa_fcs_rport_s *rport;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700723 struct list_head *qe;
Jing Huang7725ccf2009-09-23 17:46:15 -0700724
725 list_for_each(qe, &port->rport_q) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700726 rport = (struct bfa_fcs_rport_s *) qe;
Jing Huang7725ccf2009-09-23 17:46:15 -0700727 if (wwn_is_equal(rport->pwwn, pwwn))
728 return rport;
729 }
730
731 bfa_trc(port->fcs, pwwn);
Jing Huangf8ceafd2009-09-25 12:29:54 -0700732 return NULL;
Jing Huang7725ccf2009-09-23 17:46:15 -0700733}
734
Jing Huang5fbe25c2010-10-18 17:17:23 -0700735/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700736 * NWWN based Lookup for a R-Port in the Port R-Port Queue
737 */
738struct bfa_fcs_rport_s *
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700739bfa_fcs_lport_get_rport_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t nwwn)
Jing Huang7725ccf2009-09-23 17:46:15 -0700740{
741 struct bfa_fcs_rport_s *rport;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700742 struct list_head *qe;
Jing Huang7725ccf2009-09-23 17:46:15 -0700743
744 list_for_each(qe, &port->rport_q) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700745 rport = (struct bfa_fcs_rport_s *) qe;
Jing Huang7725ccf2009-09-23 17:46:15 -0700746 if (wwn_is_equal(rport->nwwn, nwwn))
747 return rport;
748 }
749
750 bfa_trc(port->fcs, nwwn);
Jing Huangf8ceafd2009-09-25 12:29:54 -0700751 return NULL;
Jing Huang7725ccf2009-09-23 17:46:15 -0700752}
753
Jing Huang5fbe25c2010-10-18 17:17:23 -0700754/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700755 * Called by rport module when new rports are discovered.
756 */
757void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700758bfa_fcs_lport_add_rport(
759 struct bfa_fcs_lport_s *port,
760 struct bfa_fcs_rport_s *rport)
Jing Huang7725ccf2009-09-23 17:46:15 -0700761{
762 list_add_tail(&rport->qe, &port->rport_q);
763 port->num_rports++;
764}
765
Jing Huang5fbe25c2010-10-18 17:17:23 -0700766/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700767 * Called by rport module to when rports are deleted.
768 */
769void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700770bfa_fcs_lport_del_rport(
771 struct bfa_fcs_lport_s *port,
772 struct bfa_fcs_rport_s *rport)
Jing Huang7725ccf2009-09-23 17:46:15 -0700773{
774 bfa_assert(bfa_q_is_on_q(&port->rport_q, rport));
775 list_del(&rport->qe);
776 port->num_rports--;
777
778 bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELRPORT);
779}
780
Jing Huang5fbe25c2010-10-18 17:17:23 -0700781/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700782 * Called by fabric for base port when fabric login is complete.
783 * Called by vport for virtual ports when FDISC is complete.
784 */
785void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700786bfa_fcs_lport_online(struct bfa_fcs_lport_s *port)
Jing Huang7725ccf2009-09-23 17:46:15 -0700787{
788 bfa_sm_send_event(port, BFA_FCS_PORT_SM_ONLINE);
789}
790
Jing Huang5fbe25c2010-10-18 17:17:23 -0700791/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700792 * Called by fabric for base port when fabric goes offline.
793 * Called by vport for virtual ports when virtual port becomes offline.
794 */
795void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700796bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port)
Jing Huang7725ccf2009-09-23 17:46:15 -0700797{
798 bfa_sm_send_event(port, BFA_FCS_PORT_SM_OFFLINE);
799}
800
Jing Huang5fbe25c2010-10-18 17:17:23 -0700801/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700802 * Called by fabric to delete base lport and associated resources.
803 *
804 * Called by vport to delete lport and associated resources. Should call
805 * bfa_fcs_vport_delete_comp() for vports on completion.
806 */
807void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700808bfa_fcs_lport_delete(struct bfa_fcs_lport_s *port)
Jing Huang7725ccf2009-09-23 17:46:15 -0700809{
810 bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELETE);
811}
812
Jing Huang5fbe25c2010-10-18 17:17:23 -0700813/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700814 * Return TRUE if port is online, else return FALSE
815 */
816bfa_boolean_t
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700817bfa_fcs_lport_is_online(struct bfa_fcs_lport_s *port)
Jing Huang7725ccf2009-09-23 17:46:15 -0700818{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700819 return bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online);
Jing Huang7725ccf2009-09-23 17:46:15 -0700820}
821
Jing Huang5fbe25c2010-10-18 17:17:23 -0700822/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700823 * Attach time initialization of logical ports.
Jing Huang7725ccf2009-09-23 17:46:15 -0700824 */
825void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700826bfa_fcs_lport_attach(struct bfa_fcs_lport_s *lport, struct bfa_fcs_s *fcs,
827 u16 vf_id, struct bfa_fcs_vport_s *vport)
Jing Huang7725ccf2009-09-23 17:46:15 -0700828{
829 lport->fcs = fcs;
830 lport->fabric = bfa_fcs_vf_lookup(fcs, vf_id);
Jing Huang7725ccf2009-09-23 17:46:15 -0700831 lport->vport = vport;
Maggie Zhangf7f738122010-12-09 19:08:43 -0800832 lport->lp_tag = (vport) ? vport->lps->lp_tag :
833 lport->fabric->lps->lp_tag;
Jing Huang7725ccf2009-09-23 17:46:15 -0700834
835 INIT_LIST_HEAD(&lport->rport_q);
836 lport->num_rports = 0;
Krishna Gudipatie6714322010-03-03 17:44:02 -0800837}
Jing Huang7725ccf2009-09-23 17:46:15 -0700838
Jing Huang5fbe25c2010-10-18 17:17:23 -0700839/*
Krishna Gudipatie6714322010-03-03 17:44:02 -0800840 * Logical port initialization of base or virtual port.
841 * Called by fabric for base port or by vport for virtual ports.
842 */
843
844void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700845bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport,
846 struct bfa_lport_cfg_s *port_cfg)
Krishna Gudipatie6714322010-03-03 17:44:02 -0800847{
848 struct bfa_fcs_vport_s *vport = lport->vport;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700849 struct bfad_s *bfad = (struct bfad_s *)lport->fcs->bfad;
850 char lpwwn_buf[BFA_STRING_32];
Krishna Gudipatie6714322010-03-03 17:44:02 -0800851
Jing Huang6a18b162010-10-18 17:08:54 -0700852 lport->port_cfg = *port_cfg;
Krishna Gudipatie6714322010-03-03 17:44:02 -0800853
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700854 lport->bfad_port = bfa_fcb_lport_new(lport->fcs->bfad, lport,
855 lport->port_cfg.roles,
856 lport->fabric->vf_drv,
857 vport ? vport->vport_drv : NULL);
Krishna Gudipatie6714322010-03-03 17:44:02 -0800858
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700859 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(lport));
Jing Huang88166242010-12-09 17:11:53 -0800860 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700861 "New logical port created: WWN = %s Role = %s\n",
862 lpwwn_buf, "Initiator");
Jing Huang7725ccf2009-09-23 17:46:15 -0700863
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700864 bfa_sm_set_state(lport, bfa_fcs_lport_sm_uninit);
Jing Huang7725ccf2009-09-23 17:46:15 -0700865 bfa_sm_send_event(lport, BFA_FCS_PORT_SM_CREATE);
866}
867
Jing Huang5fbe25c2010-10-18 17:17:23 -0700868/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700869 * fcs_lport_api
870 */
871
872void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700873bfa_fcs_lport_get_attr(
874 struct bfa_fcs_lport_s *port,
875 struct bfa_lport_attr_s *port_attr)
Jing Huang7725ccf2009-09-23 17:46:15 -0700876{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700877 if (bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online))
Jing Huang7725ccf2009-09-23 17:46:15 -0700878 port_attr->pid = port->pid;
879 else
880 port_attr->pid = 0;
881
882 port_attr->port_cfg = port->port_cfg;
883
884 if (port->fabric) {
Maggie Zhangf7f738122010-12-09 19:08:43 -0800885 port_attr->port_type = port->fabric->oper_type;
886 port_attr->loopback = bfa_sm_cmp_state(port->fabric, bfa_fcs_fabric_sm_loopback);
Krishna Gudipatif926a052010-03-05 19:36:00 -0800887 port_attr->authfail =
Maggie Zhangf7f738122010-12-09 19:08:43 -0800888 bfa_sm_cmp_state(port->fabric,
889 bfa_fcs_fabric_sm_auth_failed);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700890 port_attr->fabric_name = bfa_fcs_lport_get_fabric_name(port);
Jing Huang7725ccf2009-09-23 17:46:15 -0700891 memcpy(port_attr->fabric_ip_addr,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700892 bfa_fcs_lport_get_fabric_ipaddr(port),
893 BFA_FCS_FABRIC_IPADDR_SZ);
Jing Huang7725ccf2009-09-23 17:46:15 -0700894
Krishna Gudipati86e32da2010-03-05 19:35:33 -0800895 if (port->vport != NULL) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700896 port_attr->port_type = BFA_PORT_TYPE_VPORT;
Krishna Gudipati86e32da2010-03-05 19:35:33 -0800897 port_attr->fpma_mac =
Maggie Zhangf7f738122010-12-09 19:08:43 -0800898 port->vport->lps->lp_mac;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700899 } else {
Krishna Gudipati86e32da2010-03-05 19:35:33 -0800900 port_attr->fpma_mac =
Maggie Zhangf7f738122010-12-09 19:08:43 -0800901 port->fabric->lps->lp_mac;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700902 }
Jing Huang7725ccf2009-09-23 17:46:15 -0700903 } else {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700904 port_attr->port_type = BFA_PORT_TYPE_UNKNOWN;
905 port_attr->state = BFA_LPORT_UNINIT;
Jing Huang7725ccf2009-09-23 17:46:15 -0700906 }
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700907}
908
Jing Huang5fbe25c2010-10-18 17:17:23 -0700909/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700910 * bfa_fcs_lport_fab port fab functions
911 */
912
Jing Huang5fbe25c2010-10-18 17:17:23 -0700913/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700914 * Called by port to initialize fabric services of the base port.
915 */
916static void
917bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port)
918{
919 bfa_fcs_lport_ns_init(port);
920 bfa_fcs_lport_scn_init(port);
921 bfa_fcs_lport_ms_init(port);
922}
923
Jing Huang5fbe25c2010-10-18 17:17:23 -0700924/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700925 * Called by port to notify transition to online state.
926 */
927static void
928bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port)
929{
930 bfa_fcs_lport_ns_online(port);
931 bfa_fcs_lport_scn_online(port);
932}
933
Jing Huang5fbe25c2010-10-18 17:17:23 -0700934/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700935 * Called by port to notify transition to offline state.
936 */
937static void
938bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port)
939{
940 bfa_fcs_lport_ns_offline(port);
941 bfa_fcs_lport_scn_offline(port);
942 bfa_fcs_lport_ms_offline(port);
943}
944
Jing Huang5fbe25c2010-10-18 17:17:23 -0700945/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700946 * bfa_fcs_lport_n2n functions
947 */
948
Jing Huang5fbe25c2010-10-18 17:17:23 -0700949/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700950 * Called by fcs/port to initialize N2N topology.
951 */
952static void
953bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port)
954{
955}
956
Jing Huang5fbe25c2010-10-18 17:17:23 -0700957/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700958 * Called by fcs/port to notify transition to online state.
959 */
960static void
961bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port)
962{
963 struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n;
964 struct bfa_lport_cfg_s *pcfg = &port->port_cfg;
965 struct bfa_fcs_rport_s *rport;
966
967 bfa_trc(port->fcs, pcfg->pwwn);
968
969 /*
970 * If our PWWN is > than that of the r-port, we have to initiate PLOGI
971 * and assign an Address. if not, we need to wait for its PLOGI.
972 *
973 * If our PWWN is < than that of the remote port, it will send a PLOGI
974 * with the PIDs assigned. The rport state machine take care of this
975 * incoming PLOGI.
976 */
977 if (memcmp
978 ((void *)&pcfg->pwwn, (void *)&n2n_port->rem_port_wwn,
979 sizeof(wwn_t)) > 0) {
980 port->pid = N2N_LOCAL_PID;
Jing Huang5fbe25c2010-10-18 17:17:23 -0700981 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700982 * First, check if we know the device by pwwn.
983 */
984 rport = bfa_fcs_lport_get_rport_by_pwwn(port,
985 n2n_port->rem_port_wwn);
986 if (rport) {
987 bfa_trc(port->fcs, rport->pid);
988 bfa_trc(port->fcs, rport->pwwn);
989 rport->pid = N2N_REMOTE_PID;
Maggie Zhangf7f738122010-12-09 19:08:43 -0800990 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700991 return;
992 }
993
994 /*
995 * In n2n there can be only one rport. Delete the old one
996 * whose pid should be zero, because it is offline.
997 */
998 if (port->num_rports > 0) {
999 rport = bfa_fcs_lport_get_rport_by_pid(port, 0);
1000 bfa_assert(rport != NULL);
1001 if (rport) {
1002 bfa_trc(port->fcs, rport->pwwn);
Maggie Zhangf7f738122010-12-09 19:08:43 -08001003 bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001004 }
1005 }
1006 bfa_fcs_rport_create(port, N2N_REMOTE_PID);
1007 }
1008}
1009
Jing Huang5fbe25c2010-10-18 17:17:23 -07001010/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001011 * Called by fcs/port to notify transition to offline state.
1012 */
1013static void
1014bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port)
1015{
1016 struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n;
1017
1018 bfa_trc(port->fcs, port->pid);
1019 port->pid = 0;
1020 n2n_port->rem_port_wwn = 0;
1021 n2n_port->reply_oxid = 0;
1022}
1023
1024#define BFA_FCS_FDMI_CMD_MAX_RETRIES 2
1025
1026/*
1027 * forward declarations
1028 */
1029static void bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg,
1030 struct bfa_fcxp_s *fcxp_alloced);
1031static void bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg,
1032 struct bfa_fcxp_s *fcxp_alloced);
1033static void bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg,
1034 struct bfa_fcxp_s *fcxp_alloced);
1035static void bfa_fcs_lport_fdmi_rhba_response(void *fcsarg,
1036 struct bfa_fcxp_s *fcxp,
1037 void *cbarg,
1038 bfa_status_t req_status,
1039 u32 rsp_len,
1040 u32 resid_len,
1041 struct fchs_s *rsp_fchs);
1042static void bfa_fcs_lport_fdmi_rprt_response(void *fcsarg,
1043 struct bfa_fcxp_s *fcxp,
1044 void *cbarg,
1045 bfa_status_t req_status,
1046 u32 rsp_len,
1047 u32 resid_len,
1048 struct fchs_s *rsp_fchs);
1049static void bfa_fcs_lport_fdmi_rpa_response(void *fcsarg,
1050 struct bfa_fcxp_s *fcxp,
1051 void *cbarg,
1052 bfa_status_t req_status,
1053 u32 rsp_len,
1054 u32 resid_len,
1055 struct fchs_s *rsp_fchs);
1056static void bfa_fcs_lport_fdmi_timeout(void *arg);
1057static u16 bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1058 u8 *pyld);
1059static u16 bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1060 u8 *pyld);
1061static u16 bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1062 u8 *pyld);
1063static u16 bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *
1064 fdmi, u8 *pyld);
1065static void bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
1066 struct bfa_fcs_fdmi_hba_attr_s *hba_attr);
1067static void bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
1068 struct bfa_fcs_fdmi_port_attr_s *port_attr);
Jing Huang5fbe25c2010-10-18 17:17:23 -07001069/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001070 * fcs_fdmi_sm FCS FDMI state machine
1071 */
1072
Jing Huang5fbe25c2010-10-18 17:17:23 -07001073/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001074 * FDMI State Machine events
1075 */
1076enum port_fdmi_event {
1077 FDMISM_EVENT_PORT_ONLINE = 1,
1078 FDMISM_EVENT_PORT_OFFLINE = 2,
1079 FDMISM_EVENT_RSP_OK = 4,
1080 FDMISM_EVENT_RSP_ERROR = 5,
1081 FDMISM_EVENT_TIMEOUT = 6,
1082 FDMISM_EVENT_RHBA_SENT = 7,
1083 FDMISM_EVENT_RPRT_SENT = 8,
1084 FDMISM_EVENT_RPA_SENT = 9,
1085};
1086
1087static void bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi,
1088 enum port_fdmi_event event);
1089static void bfa_fcs_lport_fdmi_sm_sending_rhba(
1090 struct bfa_fcs_lport_fdmi_s *fdmi,
1091 enum port_fdmi_event event);
1092static void bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1093 enum port_fdmi_event event);
1094static void bfa_fcs_lport_fdmi_sm_rhba_retry(
1095 struct bfa_fcs_lport_fdmi_s *fdmi,
1096 enum port_fdmi_event event);
1097static void bfa_fcs_lport_fdmi_sm_sending_rprt(
1098 struct bfa_fcs_lport_fdmi_s *fdmi,
1099 enum port_fdmi_event event);
1100static void bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1101 enum port_fdmi_event event);
1102static void bfa_fcs_lport_fdmi_sm_rprt_retry(
1103 struct bfa_fcs_lport_fdmi_s *fdmi,
1104 enum port_fdmi_event event);
1105static void bfa_fcs_lport_fdmi_sm_sending_rpa(
1106 struct bfa_fcs_lport_fdmi_s *fdmi,
1107 enum port_fdmi_event event);
1108static void bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1109 enum port_fdmi_event event);
1110static void bfa_fcs_lport_fdmi_sm_rpa_retry(
1111 struct bfa_fcs_lport_fdmi_s *fdmi,
1112 enum port_fdmi_event event);
1113static void bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi,
1114 enum port_fdmi_event event);
1115static void bfa_fcs_lport_fdmi_sm_disabled(
1116 struct bfa_fcs_lport_fdmi_s *fdmi,
1117 enum port_fdmi_event event);
Jing Huang5fbe25c2010-10-18 17:17:23 -07001118/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001119 * Start in offline state - awaiting MS to send start.
1120 */
1121static void
1122bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi,
1123 enum port_fdmi_event event)
1124{
1125 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1126
1127 bfa_trc(port->fcs, port->port_cfg.pwwn);
1128 bfa_trc(port->fcs, event);
1129
1130 fdmi->retry_cnt = 0;
1131
1132 switch (event) {
1133 case FDMISM_EVENT_PORT_ONLINE:
1134 if (port->vport) {
1135 /*
1136 * For Vports, register a new port.
1137 */
1138 bfa_sm_set_state(fdmi,
1139 bfa_fcs_lport_fdmi_sm_sending_rprt);
1140 bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL);
1141 } else {
1142 /*
1143 * For a base port, we should first register the HBA
1144 * atribute. The HBA attribute also contains the base
1145 * port registration.
1146 */
1147 bfa_sm_set_state(fdmi,
1148 bfa_fcs_lport_fdmi_sm_sending_rhba);
1149 bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL);
1150 }
1151 break;
1152
1153 case FDMISM_EVENT_PORT_OFFLINE:
1154 break;
1155
1156 default:
1157 bfa_sm_fault(port->fcs, event);
1158 }
1159}
1160
1161static void
1162bfa_fcs_lport_fdmi_sm_sending_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1163 enum port_fdmi_event event)
1164{
1165 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1166
1167 bfa_trc(port->fcs, port->port_cfg.pwwn);
1168 bfa_trc(port->fcs, event);
1169
1170 switch (event) {
1171 case FDMISM_EVENT_RHBA_SENT:
1172 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rhba);
1173 break;
1174
1175 case FDMISM_EVENT_PORT_OFFLINE:
1176 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1177 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1178 &fdmi->fcxp_wqe);
1179 break;
1180
1181 default:
1182 bfa_sm_fault(port->fcs, event);
1183 }
1184}
1185
1186static void
1187bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1188 enum port_fdmi_event event)
1189{
1190 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1191
1192 bfa_trc(port->fcs, port->port_cfg.pwwn);
1193 bfa_trc(port->fcs, event);
1194
1195 switch (event) {
1196 case FDMISM_EVENT_RSP_ERROR:
1197 /*
1198 * if max retries have not been reached, start timer for a
1199 * delayed retry
1200 */
1201 if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1202 bfa_sm_set_state(fdmi,
1203 bfa_fcs_lport_fdmi_sm_rhba_retry);
1204 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1205 &fdmi->timer,
1206 bfa_fcs_lport_fdmi_timeout, fdmi,
1207 BFA_FCS_RETRY_TIMEOUT);
1208 } else {
1209 /*
1210 * set state to offline
1211 */
1212 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1213 }
1214 break;
1215
1216 case FDMISM_EVENT_RSP_OK:
1217 /*
1218 * Initiate Register Port Attributes
1219 */
1220 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa);
1221 fdmi->retry_cnt = 0;
1222 bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL);
1223 break;
1224
1225 case FDMISM_EVENT_PORT_OFFLINE:
1226 bfa_fcxp_discard(fdmi->fcxp);
1227 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1228 break;
1229
1230 default:
1231 bfa_sm_fault(port->fcs, event);
1232 }
1233}
1234
1235static void
1236bfa_fcs_lport_fdmi_sm_rhba_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1237 enum port_fdmi_event event)
1238{
1239 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1240
1241 bfa_trc(port->fcs, port->port_cfg.pwwn);
1242 bfa_trc(port->fcs, event);
1243
1244 switch (event) {
1245 case FDMISM_EVENT_TIMEOUT:
1246 /*
1247 * Retry Timer Expired. Re-send
1248 */
1249 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rhba);
1250 bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL);
1251 break;
1252
1253 case FDMISM_EVENT_PORT_OFFLINE:
1254 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1255 bfa_timer_stop(&fdmi->timer);
1256 break;
1257
1258 default:
1259 bfa_sm_fault(port->fcs, event);
1260 }
1261}
1262
1263/*
1264* RPRT : Register Port
1265 */
1266static void
1267bfa_fcs_lport_fdmi_sm_sending_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1268 enum port_fdmi_event event)
1269{
1270 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1271
1272 bfa_trc(port->fcs, port->port_cfg.pwwn);
1273 bfa_trc(port->fcs, event);
1274
1275 switch (event) {
1276 case FDMISM_EVENT_RPRT_SENT:
1277 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rprt);
1278 break;
1279
1280 case FDMISM_EVENT_PORT_OFFLINE:
1281 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1282 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1283 &fdmi->fcxp_wqe);
1284 break;
1285
1286 default:
1287 bfa_sm_fault(port->fcs, event);
1288 }
1289}
1290
1291static void
1292bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1293 enum port_fdmi_event event)
1294{
1295 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1296
1297 bfa_trc(port->fcs, port->port_cfg.pwwn);
1298 bfa_trc(port->fcs, event);
1299
1300 switch (event) {
1301 case FDMISM_EVENT_RSP_ERROR:
1302 /*
1303 * if max retries have not been reached, start timer for a
1304 * delayed retry
1305 */
1306 if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1307 bfa_sm_set_state(fdmi,
1308 bfa_fcs_lport_fdmi_sm_rprt_retry);
1309 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1310 &fdmi->timer,
1311 bfa_fcs_lport_fdmi_timeout, fdmi,
1312 BFA_FCS_RETRY_TIMEOUT);
1313
1314 } else {
1315 /*
1316 * set state to offline
1317 */
1318 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1319 fdmi->retry_cnt = 0;
1320 }
1321 break;
1322
1323 case FDMISM_EVENT_RSP_OK:
1324 fdmi->retry_cnt = 0;
1325 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online);
1326 break;
1327
1328 case FDMISM_EVENT_PORT_OFFLINE:
1329 bfa_fcxp_discard(fdmi->fcxp);
1330 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1331 break;
1332
1333 default:
1334 bfa_sm_fault(port->fcs, event);
1335 }
1336}
1337
1338static void
1339bfa_fcs_lport_fdmi_sm_rprt_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1340 enum port_fdmi_event event)
1341{
1342 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1343
1344 bfa_trc(port->fcs, port->port_cfg.pwwn);
1345 bfa_trc(port->fcs, event);
1346
1347 switch (event) {
1348 case FDMISM_EVENT_TIMEOUT:
1349 /*
1350 * Retry Timer Expired. Re-send
1351 */
1352 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rprt);
1353 bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL);
1354 break;
1355
1356 case FDMISM_EVENT_PORT_OFFLINE:
1357 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1358 bfa_timer_stop(&fdmi->timer);
1359 break;
1360
1361 default:
1362 bfa_sm_fault(port->fcs, event);
1363 }
1364}
1365
1366/*
1367 * Register Port Attributes
1368 */
1369static void
1370bfa_fcs_lport_fdmi_sm_sending_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1371 enum port_fdmi_event event)
1372{
1373 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1374
1375 bfa_trc(port->fcs, port->port_cfg.pwwn);
1376 bfa_trc(port->fcs, event);
1377
1378 switch (event) {
1379 case FDMISM_EVENT_RPA_SENT:
1380 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa);
1381 break;
1382
1383 case FDMISM_EVENT_PORT_OFFLINE:
1384 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1385 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1386 &fdmi->fcxp_wqe);
1387 break;
1388
1389 default:
1390 bfa_sm_fault(port->fcs, event);
1391 }
1392}
1393
1394static void
1395bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1396 enum port_fdmi_event event)
1397{
1398 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1399
1400 bfa_trc(port->fcs, port->port_cfg.pwwn);
1401 bfa_trc(port->fcs, event);
1402
1403 switch (event) {
1404 case FDMISM_EVENT_RSP_ERROR:
1405 /*
1406 * if max retries have not been reached, start timer for a
1407 * delayed retry
1408 */
1409 if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1410 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa_retry);
1411 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1412 &fdmi->timer,
1413 bfa_fcs_lport_fdmi_timeout, fdmi,
1414 BFA_FCS_RETRY_TIMEOUT);
1415 } else {
1416 /*
1417 * set state to offline
1418 */
1419 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1420 fdmi->retry_cnt = 0;
1421 }
1422 break;
1423
1424 case FDMISM_EVENT_RSP_OK:
1425 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online);
1426 fdmi->retry_cnt = 0;
1427 break;
1428
1429 case FDMISM_EVENT_PORT_OFFLINE:
1430 bfa_fcxp_discard(fdmi->fcxp);
1431 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1432 break;
1433
1434 default:
1435 bfa_sm_fault(port->fcs, event);
1436 }
1437}
1438
1439static void
1440bfa_fcs_lport_fdmi_sm_rpa_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1441 enum port_fdmi_event event)
1442{
1443 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1444
1445 bfa_trc(port->fcs, port->port_cfg.pwwn);
1446 bfa_trc(port->fcs, event);
1447
1448 switch (event) {
1449 case FDMISM_EVENT_TIMEOUT:
1450 /*
1451 * Retry Timer Expired. Re-send
1452 */
1453 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa);
1454 bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL);
1455 break;
1456
1457 case FDMISM_EVENT_PORT_OFFLINE:
1458 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1459 bfa_timer_stop(&fdmi->timer);
1460 break;
1461
1462 default:
1463 bfa_sm_fault(port->fcs, event);
1464 }
1465}
1466
1467static void
1468bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi,
1469 enum port_fdmi_event event)
1470{
1471 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1472
1473 bfa_trc(port->fcs, port->port_cfg.pwwn);
1474 bfa_trc(port->fcs, event);
1475
1476 switch (event) {
1477 case FDMISM_EVENT_PORT_OFFLINE:
1478 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1479 break;
1480
1481 default:
1482 bfa_sm_fault(port->fcs, event);
1483 }
1484}
Jing Huang5fbe25c2010-10-18 17:17:23 -07001485/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001486 * FDMI is disabled state.
1487 */
1488static void
1489bfa_fcs_lport_fdmi_sm_disabled(struct bfa_fcs_lport_fdmi_s *fdmi,
1490 enum port_fdmi_event event)
1491{
1492 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1493
1494 bfa_trc(port->fcs, port->port_cfg.pwwn);
1495 bfa_trc(port->fcs, event);
1496
1497 /* No op State. It can only be enabled at Driver Init. */
1498}
1499
Jing Huang5fbe25c2010-10-18 17:17:23 -07001500/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001501* RHBA : Register HBA Attributes.
1502 */
1503static void
1504bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1505{
1506 struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
1507 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1508 struct fchs_s fchs;
1509 int len, attr_len;
1510 struct bfa_fcxp_s *fcxp;
1511 u8 *pyld;
1512
1513 bfa_trc(port->fcs, port->port_cfg.pwwn);
1514
1515 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1516 if (!fcxp) {
1517 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
1518 bfa_fcs_lport_fdmi_send_rhba, fdmi);
1519 return;
1520 }
1521 fdmi->fcxp = fcxp;
1522
1523 pyld = bfa_fcxp_get_reqbuf(fcxp);
Jing Huang6a18b162010-10-18 17:08:54 -07001524 memset(pyld, 0, FC_MAX_PDUSZ);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001525
1526 len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
1527 FDMI_RHBA);
1528
1529 attr_len =
1530 bfa_fcs_lport_fdmi_build_rhba_pyld(fdmi,
1531 (u8 *) ((struct ct_hdr_s *) pyld
1532 + 1));
1533
1534 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1535 FC_CLASS_3, (len + attr_len), &fchs,
1536 bfa_fcs_lport_fdmi_rhba_response, (void *)fdmi,
1537 FC_MAX_PDUSZ, FC_FCCT_TOV);
1538
1539 bfa_sm_send_event(fdmi, FDMISM_EVENT_RHBA_SENT);
1540}
1541
1542static u16
1543bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
1544{
1545 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1546 struct bfa_fcs_fdmi_hba_attr_s hba_attr;
1547 struct bfa_fcs_fdmi_hba_attr_s *fcs_hba_attr = &hba_attr;
1548 struct fdmi_rhba_s *rhba = (struct fdmi_rhba_s *) pyld;
1549 struct fdmi_attr_s *attr;
1550 u8 *curr_ptr;
1551 u16 len, count;
Maggie50444a32010-11-29 18:26:32 -08001552 u16 templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001553
1554 /*
1555 * get hba attributes
1556 */
1557 bfa_fcs_fdmi_get_hbaattr(fdmi, fcs_hba_attr);
1558
1559 rhba->hba_id = bfa_fcs_lport_get_pwwn(port);
Jing Huangba816ea2010-10-18 17:10:50 -07001560 rhba->port_list.num_ports = cpu_to_be32(1);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001561 rhba->port_list.port_entry = bfa_fcs_lport_get_pwwn(port);
1562
1563 len = sizeof(rhba->hba_id) + sizeof(rhba->port_list);
1564
1565 count = 0;
1566 len += sizeof(rhba->hba_attr_blk.attr_count);
1567
1568 /*
1569 * fill out the invididual entries of the HBA attrib Block
1570 */
1571 curr_ptr = (u8 *) &rhba->hba_attr_blk.hba_attr;
1572
1573 /*
1574 * Node Name
1575 */
1576 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001577 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NODENAME);
Maggie50444a32010-11-29 18:26:32 -08001578 templen = sizeof(wwn_t);
1579 memcpy(attr->value, &bfa_fcs_lport_get_nwwn(port), templen);
1580 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1581 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001582 count++;
Maggie50444a32010-11-29 18:26:32 -08001583 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1584 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001585
1586 /*
1587 * Manufacturer
1588 */
1589 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001590 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MANUFACTURER);
Maggie50444a32010-11-29 18:26:32 -08001591 templen = (u16) strlen(fcs_hba_attr->manufacturer);
1592 memcpy(attr->value, fcs_hba_attr->manufacturer, templen);
1593 templen = fc_roundup(templen, sizeof(u32));
1594 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1595 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001596 count++;
Maggie50444a32010-11-29 18:26:32 -08001597 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1598 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001599
1600 /*
1601 * Serial Number
1602 */
1603 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001604 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_SERIALNUM);
Maggie50444a32010-11-29 18:26:32 -08001605 templen = (u16) strlen(fcs_hba_attr->serial_num);
1606 memcpy(attr->value, fcs_hba_attr->serial_num, templen);
1607 templen = fc_roundup(templen, sizeof(u32));
1608 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1609 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001610 count++;
Maggie50444a32010-11-29 18:26:32 -08001611 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1612 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001613
1614 /*
1615 * Model
1616 */
1617 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001618 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL);
Maggie50444a32010-11-29 18:26:32 -08001619 templen = (u16) strlen(fcs_hba_attr->model);
1620 memcpy(attr->value, fcs_hba_attr->model, templen);
1621 templen = fc_roundup(templen, sizeof(u32));
1622 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1623 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001624 count++;
Maggie50444a32010-11-29 18:26:32 -08001625 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1626 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001627
1628 /*
1629 * Model Desc
1630 */
1631 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001632 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL_DESC);
Maggie50444a32010-11-29 18:26:32 -08001633 templen = (u16) strlen(fcs_hba_attr->model_desc);
1634 memcpy(attr->value, fcs_hba_attr->model_desc, templen);
1635 templen = fc_roundup(templen, sizeof(u32));
1636 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1637 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001638 count++;
Maggie50444a32010-11-29 18:26:32 -08001639 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1640 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001641
1642 /*
1643 * H/W Version
1644 */
1645 if (fcs_hba_attr->hw_version[0] != '\0') {
1646 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001647 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_HW_VERSION);
Maggie50444a32010-11-29 18:26:32 -08001648 templen = (u16) strlen(fcs_hba_attr->hw_version);
1649 memcpy(attr->value, fcs_hba_attr->hw_version, templen);
1650 templen = fc_roundup(templen, sizeof(u32));
1651 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1652 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001653 count++;
Maggie50444a32010-11-29 18:26:32 -08001654 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1655 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001656 }
1657
1658 /*
1659 * Driver Version
1660 */
1661 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001662 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_DRIVER_VERSION);
Maggie50444a32010-11-29 18:26:32 -08001663 templen = (u16) strlen(fcs_hba_attr->driver_version);
1664 memcpy(attr->value, fcs_hba_attr->driver_version, templen);
1665 templen = fc_roundup(templen, sizeof(u32));
1666 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1667 len += templen;;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001668 count++;
Maggie50444a32010-11-29 18:26:32 -08001669 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1670 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001671
1672 /*
1673 * Option Rom Version
1674 */
1675 if (fcs_hba_attr->option_rom_ver[0] != '\0') {
1676 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001677 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_ROM_VERSION);
Maggie50444a32010-11-29 18:26:32 -08001678 templen = (u16) strlen(fcs_hba_attr->option_rom_ver);
1679 memcpy(attr->value, fcs_hba_attr->option_rom_ver, templen);
1680 templen = fc_roundup(templen, sizeof(u32));
1681 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1682 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001683 count++;
Maggie50444a32010-11-29 18:26:32 -08001684 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1685 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001686 }
1687
1688 /*
1689 * f/w Version = driver version
1690 */
1691 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001692 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_FW_VERSION);
Maggie50444a32010-11-29 18:26:32 -08001693 templen = (u16) strlen(fcs_hba_attr->driver_version);
1694 memcpy(attr->value, fcs_hba_attr->driver_version, templen);
1695 templen = fc_roundup(templen, sizeof(u32));
1696 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1697 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001698 count++;
Maggie50444a32010-11-29 18:26:32 -08001699 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1700 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001701
1702 /*
1703 * OS Name
1704 */
1705 if (fcs_hba_attr->os_name[0] != '\0') {
1706 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001707 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_OS_NAME);
Maggie50444a32010-11-29 18:26:32 -08001708 templen = (u16) strlen(fcs_hba_attr->os_name);
1709 memcpy(attr->value, fcs_hba_attr->os_name, templen);
1710 templen = fc_roundup(templen, sizeof(u32));
1711 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1712 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001713 count++;
Maggie50444a32010-11-29 18:26:32 -08001714 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1715 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001716 }
1717
1718 /*
1719 * MAX_CT_PAYLOAD
1720 */
1721 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001722 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MAX_CT);
Maggie50444a32010-11-29 18:26:32 -08001723 templen = sizeof(fcs_hba_attr->max_ct_pyld);
1724 memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, templen);
1725 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001726 count++;
Maggie50444a32010-11-29 18:26:32 -08001727 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1728 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001729
1730 /*
1731 * Update size of payload
1732 */
Jing Huang5fbe25c2010-10-18 17:17:23 -07001733 len += ((sizeof(attr->type) + sizeof(attr->len)) * count);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001734
Jing Huangba816ea2010-10-18 17:10:50 -07001735 rhba->hba_attr_blk.attr_count = cpu_to_be32(count);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001736 return len;
1737}
1738
1739static void
1740bfa_fcs_lport_fdmi_rhba_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
1741 void *cbarg, bfa_status_t req_status,
1742 u32 rsp_len, u32 resid_len,
1743 struct fchs_s *rsp_fchs)
1744{
1745 struct bfa_fcs_lport_fdmi_s *fdmi =
1746 (struct bfa_fcs_lport_fdmi_s *) cbarg;
1747 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1748 struct ct_hdr_s *cthdr = NULL;
1749
1750 bfa_trc(port->fcs, port->port_cfg.pwwn);
1751
1752 /*
1753 * Sanity Checks
1754 */
1755 if (req_status != BFA_STATUS_OK) {
1756 bfa_trc(port->fcs, req_status);
1757 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
1758 return;
1759 }
1760
1761 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
Jing Huangba816ea2010-10-18 17:10:50 -07001762 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001763
1764 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
1765 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
1766 return;
1767 }
1768
1769 bfa_trc(port->fcs, cthdr->reason_code);
1770 bfa_trc(port->fcs, cthdr->exp_code);
1771 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
1772}
1773
Jing Huang5fbe25c2010-10-18 17:17:23 -07001774/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001775* RPRT : Register Port
1776 */
1777static void
1778bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1779{
1780 struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
1781 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1782 struct fchs_s fchs;
1783 u16 len, attr_len;
1784 struct bfa_fcxp_s *fcxp;
1785 u8 *pyld;
1786
1787 bfa_trc(port->fcs, port->port_cfg.pwwn);
1788
1789 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1790 if (!fcxp) {
1791 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
1792 bfa_fcs_lport_fdmi_send_rprt, fdmi);
1793 return;
1794 }
1795 fdmi->fcxp = fcxp;
1796
1797 pyld = bfa_fcxp_get_reqbuf(fcxp);
Jing Huang6a18b162010-10-18 17:08:54 -07001798 memset(pyld, 0, FC_MAX_PDUSZ);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001799
1800 len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
1801 FDMI_RPRT);
1802
1803 attr_len =
1804 bfa_fcs_lport_fdmi_build_rprt_pyld(fdmi,
1805 (u8 *) ((struct ct_hdr_s *) pyld
1806 + 1));
1807
1808 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1809 FC_CLASS_3, len + attr_len, &fchs,
1810 bfa_fcs_lport_fdmi_rprt_response, (void *)fdmi,
1811 FC_MAX_PDUSZ, FC_FCCT_TOV);
1812
1813 bfa_sm_send_event(fdmi, FDMISM_EVENT_RPRT_SENT);
1814}
1815
Jing Huang5fbe25c2010-10-18 17:17:23 -07001816/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001817 * This routine builds Port Attribute Block that used in RPA, RPRT commands.
1818 */
1819static u16
1820bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi,
1821 u8 *pyld)
1822{
1823 struct bfa_fcs_fdmi_port_attr_s fcs_port_attr;
1824 struct fdmi_port_attr_s *port_attrib = (struct fdmi_port_attr_s *) pyld;
1825 struct fdmi_attr_s *attr;
1826 u8 *curr_ptr;
1827 u16 len;
1828 u8 count = 0;
Maggie50444a32010-11-29 18:26:32 -08001829 u16 templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001830
1831 /*
1832 * get port attributes
1833 */
1834 bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr);
1835
1836 len = sizeof(port_attrib->attr_count);
1837
1838 /*
1839 * fill out the invididual entries
1840 */
1841 curr_ptr = (u8 *) &port_attrib->port_attr;
1842
1843 /*
1844 * FC4 Types
1845 */
1846 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001847 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FC4_TYPES);
Maggie50444a32010-11-29 18:26:32 -08001848 templen = sizeof(fcs_port_attr.supp_fc4_types);
1849 memcpy(attr->value, fcs_port_attr.supp_fc4_types, templen);
1850 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1851 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001852 ++count;
1853 attr->len =
Maggie50444a32010-11-29 18:26:32 -08001854 cpu_to_be16(templen + sizeof(attr->type) +
1855 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001856
1857 /*
1858 * Supported Speed
1859 */
1860 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001861 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_SUPP_SPEED);
Maggie50444a32010-11-29 18:26:32 -08001862 templen = sizeof(fcs_port_attr.supp_speed);
1863 memcpy(attr->value, &fcs_port_attr.supp_speed, templen);
1864 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1865 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001866 ++count;
1867 attr->len =
Maggie50444a32010-11-29 18:26:32 -08001868 cpu_to_be16(templen + sizeof(attr->type) +
1869 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001870
1871 /*
1872 * current Port Speed
1873 */
1874 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001875 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_SPEED);
Maggie50444a32010-11-29 18:26:32 -08001876 templen = sizeof(fcs_port_attr.curr_speed);
1877 memcpy(attr->value, &fcs_port_attr.curr_speed, templen);
1878 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1879 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001880 ++count;
Maggie50444a32010-11-29 18:26:32 -08001881 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1882 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001883
1884 /*
1885 * max frame size
1886 */
1887 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001888 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FRAME_SIZE);
Maggie50444a32010-11-29 18:26:32 -08001889 templen = sizeof(fcs_port_attr.max_frm_size);
1890 memcpy(attr->value, &fcs_port_attr.max_frm_size, templen);
1891 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1892 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001893 ++count;
Maggie50444a32010-11-29 18:26:32 -08001894 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1895 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001896
1897 /*
1898 * OS Device Name
1899 */
1900 if (fcs_port_attr.os_device_name[0] != '\0') {
1901 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001902 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_DEV_NAME);
Maggie50444a32010-11-29 18:26:32 -08001903 templen = (u16) strlen(fcs_port_attr.os_device_name);
1904 memcpy(attr->value, fcs_port_attr.os_device_name, templen);
1905 templen = fc_roundup(templen, sizeof(u32));
1906 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1907 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001908 ++count;
Maggie50444a32010-11-29 18:26:32 -08001909 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1910 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001911 }
1912 /*
1913 * Host Name
1914 */
1915 if (fcs_port_attr.host_name[0] != '\0') {
1916 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001917 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_HOST_NAME);
Maggie50444a32010-11-29 18:26:32 -08001918 templen = (u16) strlen(fcs_port_attr.host_name);
1919 memcpy(attr->value, fcs_port_attr.host_name, templen);
1920 templen = fc_roundup(templen, sizeof(u32));
1921 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1922 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001923 ++count;
Maggie50444a32010-11-29 18:26:32 -08001924 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1925 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001926 }
1927
1928 /*
1929 * Update size of payload
1930 */
Jing Huangba816ea2010-10-18 17:10:50 -07001931 port_attrib->attr_count = cpu_to_be32(count);
Jing Huang5fbe25c2010-10-18 17:17:23 -07001932 len += ((sizeof(attr->type) + sizeof(attr->len)) * count);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001933 return len;
1934}
1935
1936static u16
1937bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
1938{
1939 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1940 struct fdmi_rprt_s *rprt = (struct fdmi_rprt_s *) pyld;
1941 u16 len;
1942
1943 rprt->hba_id = bfa_fcs_lport_get_pwwn(bfa_fcs_get_base_port(port->fcs));
1944 rprt->port_name = bfa_fcs_lport_get_pwwn(port);
1945
1946 len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
1947 (u8 *) &rprt->port_attr_blk);
1948
1949 len += sizeof(rprt->hba_id) + sizeof(rprt->port_name);
1950
1951 return len;
1952}
1953
1954static void
1955bfa_fcs_lport_fdmi_rprt_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
1956 void *cbarg, bfa_status_t req_status,
1957 u32 rsp_len, u32 resid_len,
1958 struct fchs_s *rsp_fchs)
1959{
1960 struct bfa_fcs_lport_fdmi_s *fdmi =
1961 (struct bfa_fcs_lport_fdmi_s *) cbarg;
1962 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1963 struct ct_hdr_s *cthdr = NULL;
1964
1965 bfa_trc(port->fcs, port->port_cfg.pwwn);
1966
1967 /*
1968 * Sanity Checks
1969 */
1970 if (req_status != BFA_STATUS_OK) {
1971 bfa_trc(port->fcs, req_status);
1972 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
1973 return;
1974 }
1975
1976 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
Jing Huangba816ea2010-10-18 17:10:50 -07001977 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001978
1979 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
1980 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
1981 return;
1982 }
1983
1984 bfa_trc(port->fcs, cthdr->reason_code);
1985 bfa_trc(port->fcs, cthdr->exp_code);
1986 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
1987}
1988
Jing Huang5fbe25c2010-10-18 17:17:23 -07001989/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001990* RPA : Register Port Attributes.
1991 */
1992static void
1993bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1994{
1995 struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
1996 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1997 struct fchs_s fchs;
1998 u16 len, attr_len;
1999 struct bfa_fcxp_s *fcxp;
2000 u8 *pyld;
2001
2002 bfa_trc(port->fcs, port->port_cfg.pwwn);
2003
2004 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2005 if (!fcxp) {
2006 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
2007 bfa_fcs_lport_fdmi_send_rpa, fdmi);
2008 return;
2009 }
2010 fdmi->fcxp = fcxp;
2011
2012 pyld = bfa_fcxp_get_reqbuf(fcxp);
Jing Huang6a18b162010-10-18 17:08:54 -07002013 memset(pyld, 0, FC_MAX_PDUSZ);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002014
2015 len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
2016 FDMI_RPA);
2017
Jing Huang5fbe25c2010-10-18 17:17:23 -07002018 attr_len = bfa_fcs_lport_fdmi_build_rpa_pyld(fdmi,
2019 (u8 *) ((struct ct_hdr_s *) pyld + 1));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002020
2021 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2022 FC_CLASS_3, len + attr_len, &fchs,
2023 bfa_fcs_lport_fdmi_rpa_response, (void *)fdmi,
2024 FC_MAX_PDUSZ, FC_FCCT_TOV);
2025
2026 bfa_sm_send_event(fdmi, FDMISM_EVENT_RPA_SENT);
2027}
2028
2029static u16
2030bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
2031{
2032 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2033 struct fdmi_rpa_s *rpa = (struct fdmi_rpa_s *) pyld;
2034 u16 len;
2035
2036 rpa->port_name = bfa_fcs_lport_get_pwwn(port);
2037
2038 len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
2039 (u8 *) &rpa->port_attr_blk);
2040
2041 len += sizeof(rpa->port_name);
2042
2043 return len;
2044}
2045
2046static void
2047bfa_fcs_lport_fdmi_rpa_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2048 void *cbarg, bfa_status_t req_status, u32 rsp_len,
2049 u32 resid_len, struct fchs_s *rsp_fchs)
2050{
2051 struct bfa_fcs_lport_fdmi_s *fdmi =
2052 (struct bfa_fcs_lport_fdmi_s *) cbarg;
2053 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2054 struct ct_hdr_s *cthdr = NULL;
2055
2056 bfa_trc(port->fcs, port->port_cfg.pwwn);
2057
2058 /*
2059 * Sanity Checks
2060 */
2061 if (req_status != BFA_STATUS_OK) {
2062 bfa_trc(port->fcs, req_status);
2063 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2064 return;
2065 }
2066
2067 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
Jing Huangba816ea2010-10-18 17:10:50 -07002068 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002069
2070 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2071 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
2072 return;
2073 }
2074
2075 bfa_trc(port->fcs, cthdr->reason_code);
2076 bfa_trc(port->fcs, cthdr->exp_code);
2077 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2078}
2079
2080static void
2081bfa_fcs_lport_fdmi_timeout(void *arg)
2082{
2083 struct bfa_fcs_lport_fdmi_s *fdmi = (struct bfa_fcs_lport_fdmi_s *) arg;
2084
2085 bfa_sm_send_event(fdmi, FDMISM_EVENT_TIMEOUT);
2086}
2087
Maggie52f94b62010-11-29 18:21:32 -08002088static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002089bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
2090 struct bfa_fcs_fdmi_hba_attr_s *hba_attr)
2091{
2092 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2093 struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info;
2094
Jing Huang6a18b162010-10-18 17:08:54 -07002095 memset(hba_attr, 0, sizeof(struct bfa_fcs_fdmi_hba_attr_s));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002096
2097 bfa_ioc_get_adapter_manufacturer(&port->fcs->bfa->ioc,
2098 hba_attr->manufacturer);
2099 bfa_ioc_get_adapter_serial_num(&port->fcs->bfa->ioc,
2100 hba_attr->serial_num);
2101 bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc,
2102 hba_attr->model);
2103 bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc,
2104 hba_attr->model_desc);
2105 bfa_ioc_get_pci_chip_rev(&port->fcs->bfa->ioc,
2106 hba_attr->hw_version);
2107 bfa_ioc_get_adapter_optrom_ver(&port->fcs->bfa->ioc,
2108 hba_attr->option_rom_ver);
2109 bfa_ioc_get_adapter_fw_ver(&port->fcs->bfa->ioc,
2110 hba_attr->fw_version);
2111
2112 strncpy(hba_attr->driver_version, (char *)driver_info->version,
2113 sizeof(hba_attr->driver_version));
2114
2115 strncpy(hba_attr->os_name, driver_info->host_os_name,
2116 sizeof(hba_attr->os_name));
2117
2118 /*
2119 * If there is a patch level, append it
2120 * to the os name along with a separator
2121 */
2122 if (driver_info->host_os_patch[0] != '\0') {
2123 strncat(hba_attr->os_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
2124 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
2125 strncat(hba_attr->os_name, driver_info->host_os_patch,
2126 sizeof(driver_info->host_os_patch));
2127 }
2128
Jing Huangba816ea2010-10-18 17:10:50 -07002129 hba_attr->max_ct_pyld = cpu_to_be32(FC_MAX_PDUSZ);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002130}
2131
Maggie52f94b62010-11-29 18:21:32 -08002132static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002133bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
2134 struct bfa_fcs_fdmi_port_attr_s *port_attr)
2135{
2136 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2137 struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info;
2138 struct bfa_port_attr_s pport_attr;
2139
Jing Huang6a18b162010-10-18 17:08:54 -07002140 memset(port_attr, 0, sizeof(struct bfa_fcs_fdmi_port_attr_s));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002141
2142 /*
2143 * get pport attributes from hal
2144 */
2145 bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
2146
2147 /*
2148 * get FC4 type Bitmask
2149 */
2150 fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->supp_fc4_types);
2151
2152 /*
2153 * Supported Speeds
2154 */
Jing Huangba816ea2010-10-18 17:10:50 -07002155 port_attr->supp_speed = cpu_to_be32(BFA_FCS_FDMI_SUPORTED_SPEEDS);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002156
2157 /*
2158 * Current Speed
2159 */
Jing Huangba816ea2010-10-18 17:10:50 -07002160 port_attr->curr_speed = cpu_to_be32(pport_attr.speed);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002161
2162 /*
2163 * Max PDU Size.
2164 */
Jing Huangba816ea2010-10-18 17:10:50 -07002165 port_attr->max_frm_size = cpu_to_be32(FC_MAX_PDUSZ);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002166
2167 /*
2168 * OS device Name
2169 */
2170 strncpy(port_attr->os_device_name, (char *)driver_info->os_device_name,
2171 sizeof(port_attr->os_device_name));
2172
2173 /*
2174 * Host name
2175 */
2176 strncpy(port_attr->host_name, (char *)driver_info->host_machine_name,
2177 sizeof(port_attr->host_name));
Jing Huang7725ccf2009-09-23 17:46:15 -07002178
2179}
2180
2181
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002182void
2183bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s *ms)
2184{
2185 struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2186
2187 fdmi->ms = ms;
2188 if (ms->port->fcs->fdmi_enabled)
2189 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
2190 else
2191 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_disabled);
2192}
2193
2194void
2195bfa_fcs_lport_fdmi_offline(struct bfa_fcs_lport_ms_s *ms)
2196{
2197 struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2198
2199 fdmi->ms = ms;
2200 bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_OFFLINE);
2201}
2202
2203void
2204bfa_fcs_lport_fdmi_online(struct bfa_fcs_lport_ms_s *ms)
2205{
2206 struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2207
2208 fdmi->ms = ms;
2209 bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_ONLINE);
2210}
2211
2212#define BFA_FCS_MS_CMD_MAX_RETRIES 2
2213
2214/*
2215 * forward declarations
2216 */
2217static void bfa_fcs_lport_ms_send_plogi(void *ms_cbarg,
2218 struct bfa_fcxp_s *fcxp_alloced);
2219static void bfa_fcs_lport_ms_timeout(void *arg);
2220static void bfa_fcs_lport_ms_plogi_response(void *fcsarg,
2221 struct bfa_fcxp_s *fcxp,
2222 void *cbarg,
2223 bfa_status_t req_status,
2224 u32 rsp_len,
2225 u32 resid_len,
2226 struct fchs_s *rsp_fchs);
2227
2228static void bfa_fcs_lport_ms_send_gmal(void *ms_cbarg,
2229 struct bfa_fcxp_s *fcxp_alloced);
2230static void bfa_fcs_lport_ms_gmal_response(void *fcsarg,
2231 struct bfa_fcxp_s *fcxp,
2232 void *cbarg,
2233 bfa_status_t req_status,
2234 u32 rsp_len,
2235 u32 resid_len,
2236 struct fchs_s *rsp_fchs);
2237static void bfa_fcs_lport_ms_send_gfn(void *ms_cbarg,
2238 struct bfa_fcxp_s *fcxp_alloced);
2239static void bfa_fcs_lport_ms_gfn_response(void *fcsarg,
2240 struct bfa_fcxp_s *fcxp,
2241 void *cbarg,
2242 bfa_status_t req_status,
2243 u32 rsp_len,
2244 u32 resid_len,
2245 struct fchs_s *rsp_fchs);
Jing Huang5fbe25c2010-10-18 17:17:23 -07002246/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002247 * fcs_ms_sm FCS MS state machine
2248 */
2249
Jing Huang5fbe25c2010-10-18 17:17:23 -07002250/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002251 * MS State Machine events
2252 */
2253enum port_ms_event {
2254 MSSM_EVENT_PORT_ONLINE = 1,
2255 MSSM_EVENT_PORT_OFFLINE = 2,
2256 MSSM_EVENT_RSP_OK = 3,
2257 MSSM_EVENT_RSP_ERROR = 4,
2258 MSSM_EVENT_TIMEOUT = 5,
2259 MSSM_EVENT_FCXP_SENT = 6,
2260 MSSM_EVENT_PORT_FABRIC_RSCN = 7
2261};
2262
2263static void bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
2264 enum port_ms_event event);
2265static void bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
2266 enum port_ms_event event);
2267static void bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
2268 enum port_ms_event event);
2269static void bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
2270 enum port_ms_event event);
2271static void bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
2272 enum port_ms_event event);
2273static void bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
2274 enum port_ms_event event);
2275static void bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
2276 enum port_ms_event event);
2277static void bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
2278 enum port_ms_event event);
2279static void bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
2280 enum port_ms_event event);
2281static void bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
2282 enum port_ms_event event);
2283static void bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
2284 enum port_ms_event event);
Jing Huang5fbe25c2010-10-18 17:17:23 -07002285/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002286 * Start in offline state - awaiting NS to send start.
2287 */
2288static void
2289bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
2290 enum port_ms_event event)
2291{
2292 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2293 bfa_trc(ms->port->fcs, event);
2294
2295 switch (event) {
2296 case MSSM_EVENT_PORT_ONLINE:
2297 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
2298 bfa_fcs_lport_ms_send_plogi(ms, NULL);
2299 break;
2300
2301 case MSSM_EVENT_PORT_OFFLINE:
2302 break;
2303
2304 default:
2305 bfa_sm_fault(ms->port->fcs, event);
2306 }
2307}
2308
2309static void
2310bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
2311 enum port_ms_event event)
2312{
2313 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2314 bfa_trc(ms->port->fcs, event);
2315
2316 switch (event) {
2317 case MSSM_EVENT_FCXP_SENT:
2318 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi);
2319 break;
2320
2321 case MSSM_EVENT_PORT_OFFLINE:
2322 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2323 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2324 &ms->fcxp_wqe);
2325 break;
2326
2327 default:
2328 bfa_sm_fault(ms->port->fcs, event);
2329 }
2330}
2331
2332static void
2333bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
2334 enum port_ms_event event)
2335{
2336 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2337 bfa_trc(ms->port->fcs, event);
2338
2339 switch (event) {
2340 case MSSM_EVENT_RSP_ERROR:
2341 /*
2342 * Start timer for a delayed retry
2343 */
2344 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_retry);
2345 ms->port->stats.ms_retries++;
2346 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2347 &ms->timer, bfa_fcs_lport_ms_timeout, ms,
2348 BFA_FCS_RETRY_TIMEOUT);
2349 break;
2350
2351 case MSSM_EVENT_RSP_OK:
2352 /*
2353 * since plogi is done, now invoke MS related sub-modules
2354 */
2355 bfa_fcs_lport_fdmi_online(ms);
2356
Jing Huang5fbe25c2010-10-18 17:17:23 -07002357 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002358 * if this is a Vport, go to online state.
2359 */
2360 if (ms->port->vport) {
2361 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2362 break;
2363 }
2364
2365 /*
2366 * For a base port we need to get the
2367 * switch's IP address.
2368 */
2369 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
2370 bfa_fcs_lport_ms_send_gmal(ms, NULL);
2371 break;
2372
2373 case MSSM_EVENT_PORT_OFFLINE:
2374 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2375 bfa_fcxp_discard(ms->fcxp);
2376 break;
2377
2378 default:
2379 bfa_sm_fault(ms->port->fcs, event);
2380 }
2381}
2382
2383static void
2384bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
2385 enum port_ms_event event)
2386{
2387 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2388 bfa_trc(ms->port->fcs, event);
2389
2390 switch (event) {
2391 case MSSM_EVENT_TIMEOUT:
2392 /*
2393 * Retry Timer Expired. Re-send
2394 */
2395 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
2396 bfa_fcs_lport_ms_send_plogi(ms, NULL);
2397 break;
2398
2399 case MSSM_EVENT_PORT_OFFLINE:
2400 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2401 bfa_timer_stop(&ms->timer);
2402 break;
2403
2404 default:
2405 bfa_sm_fault(ms->port->fcs, event);
2406 }
2407}
2408
2409static void
2410bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
2411 enum port_ms_event event)
2412{
2413 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2414 bfa_trc(ms->port->fcs, event);
2415
2416 switch (event) {
2417 case MSSM_EVENT_PORT_OFFLINE:
2418 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2419 break;
2420
2421 case MSSM_EVENT_PORT_FABRIC_RSCN:
2422 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2423 ms->retry_cnt = 0;
2424 bfa_fcs_lport_ms_send_gfn(ms, NULL);
2425 break;
2426
2427 default:
2428 bfa_sm_fault(ms->port->fcs, event);
2429 }
2430}
2431
2432static void
2433bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
2434 enum port_ms_event event)
2435{
2436 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2437 bfa_trc(ms->port->fcs, event);
2438
2439 switch (event) {
2440 case MSSM_EVENT_FCXP_SENT:
2441 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal);
2442 break;
2443
2444 case MSSM_EVENT_PORT_OFFLINE:
2445 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2446 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2447 &ms->fcxp_wqe);
2448 break;
2449
2450 default:
2451 bfa_sm_fault(ms->port->fcs, event);
2452 }
2453}
2454
2455static void
2456bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
2457 enum port_ms_event event)
2458{
2459 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2460 bfa_trc(ms->port->fcs, event);
2461
2462 switch (event) {
2463 case MSSM_EVENT_RSP_ERROR:
2464 /*
2465 * Start timer for a delayed retry
2466 */
2467 if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
2468 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_retry);
2469 ms->port->stats.ms_retries++;
2470 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2471 &ms->timer, bfa_fcs_lport_ms_timeout, ms,
2472 BFA_FCS_RETRY_TIMEOUT);
2473 } else {
2474 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2475 bfa_fcs_lport_ms_send_gfn(ms, NULL);
2476 ms->retry_cnt = 0;
2477 }
2478 break;
2479
2480 case MSSM_EVENT_RSP_OK:
2481 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2482 bfa_fcs_lport_ms_send_gfn(ms, NULL);
2483 break;
2484
2485 case MSSM_EVENT_PORT_OFFLINE:
2486 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2487 bfa_fcxp_discard(ms->fcxp);
2488 break;
2489
2490 default:
2491 bfa_sm_fault(ms->port->fcs, event);
2492 }
2493}
2494
2495static void
2496bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
2497 enum port_ms_event event)
2498{
2499 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2500 bfa_trc(ms->port->fcs, event);
2501
2502 switch (event) {
2503 case MSSM_EVENT_TIMEOUT:
2504 /*
2505 * Retry Timer Expired. Re-send
2506 */
2507 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
2508 bfa_fcs_lport_ms_send_gmal(ms, NULL);
2509 break;
2510
2511 case MSSM_EVENT_PORT_OFFLINE:
2512 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2513 bfa_timer_stop(&ms->timer);
2514 break;
2515
2516 default:
2517 bfa_sm_fault(ms->port->fcs, event);
2518 }
2519}
Jing Huang5fbe25c2010-10-18 17:17:23 -07002520/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002521 * ms_pvt MS local functions
2522 */
2523
2524static void
2525bfa_fcs_lport_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2526{
2527 struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
2528 bfa_fcs_lport_t *port = ms->port;
2529 struct fchs_s fchs;
2530 int len;
2531 struct bfa_fcxp_s *fcxp;
2532
2533 bfa_trc(port->fcs, port->pid);
2534
2535 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2536 if (!fcxp) {
2537 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
2538 bfa_fcs_lport_ms_send_gmal, ms);
2539 return;
2540 }
2541 ms->fcxp = fcxp;
2542
2543 len = fc_gmal_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2544 bfa_fcs_lport_get_fcid(port),
Maggie Zhangf7f738122010-12-09 19:08:43 -08002545 port->fabric->lps->pr_nwwn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002546
2547 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2548 FC_CLASS_3, len, &fchs,
2549 bfa_fcs_lport_ms_gmal_response, (void *)ms,
2550 FC_MAX_PDUSZ, FC_FCCT_TOV);
2551
2552 bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
2553}
2554
2555static void
2556bfa_fcs_lport_ms_gmal_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2557 void *cbarg, bfa_status_t req_status,
2558 u32 rsp_len, u32 resid_len,
2559 struct fchs_s *rsp_fchs)
2560{
2561 struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
2562 bfa_fcs_lport_t *port = ms->port;
2563 struct ct_hdr_s *cthdr = NULL;
2564 struct fcgs_gmal_resp_s *gmal_resp;
2565 struct fcgs_gmal_entry_s *gmal_entry;
2566 u32 num_entries;
2567 u8 *rsp_str;
2568
2569 bfa_trc(port->fcs, req_status);
2570 bfa_trc(port->fcs, port->port_cfg.pwwn);
2571
2572 /*
2573 * Sanity Checks
2574 */
2575 if (req_status != BFA_STATUS_OK) {
2576 bfa_trc(port->fcs, req_status);
2577 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2578 return;
2579 }
2580
2581 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
Jing Huangba816ea2010-10-18 17:10:50 -07002582 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002583
2584 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2585 gmal_resp = (struct fcgs_gmal_resp_s *)(cthdr + 1);
2586
Jing Huangba816ea2010-10-18 17:10:50 -07002587 num_entries = be32_to_cpu(gmal_resp->ms_len);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002588 if (num_entries == 0) {
2589 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2590 return;
2591 }
2592 /*
2593 * The response could contain multiple Entries.
2594 * Entries for SNMP interface, etc.
2595 * We look for the entry with a telnet prefix.
2596 * First "http://" entry refers to IP addr
2597 */
2598
2599 gmal_entry = (struct fcgs_gmal_entry_s *)gmal_resp->ms_ma;
2600 while (num_entries > 0) {
2601 if (strncmp(gmal_entry->prefix,
2602 CT_GMAL_RESP_PREFIX_HTTP,
2603 sizeof(gmal_entry->prefix)) == 0) {
2604
2605 /*
2606 * if the IP address is terminating with a '/',
2607 * remove it.
2608 * Byte 0 consists of the length of the string.
2609 */
2610 rsp_str = &(gmal_entry->prefix[0]);
2611 if (rsp_str[gmal_entry->len-1] == '/')
2612 rsp_str[gmal_entry->len-1] = 0;
2613
2614 /* copy IP Address to fabric */
2615 strncpy(bfa_fcs_lport_get_fabric_ipaddr(port),
2616 gmal_entry->ip_addr,
2617 BFA_FCS_FABRIC_IPADDR_SZ);
2618 break;
2619 } else {
2620 --num_entries;
2621 ++gmal_entry;
2622 }
2623 }
2624
2625 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
2626 return;
2627 }
2628
2629 bfa_trc(port->fcs, cthdr->reason_code);
2630 bfa_trc(port->fcs, cthdr->exp_code);
2631 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2632}
2633
2634static void
2635bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
2636 enum port_ms_event event)
2637{
2638 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2639 bfa_trc(ms->port->fcs, event);
2640
2641 switch (event) {
2642 case MSSM_EVENT_FCXP_SENT:
2643 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn);
2644 break;
2645
2646 case MSSM_EVENT_PORT_OFFLINE:
2647 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2648 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2649 &ms->fcxp_wqe);
2650 break;
2651
2652 default:
2653 bfa_sm_fault(ms->port->fcs, event);
2654 }
2655}
2656
2657static void
2658bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
2659 enum port_ms_event event)
2660{
2661 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2662 bfa_trc(ms->port->fcs, event);
2663
2664 switch (event) {
2665 case MSSM_EVENT_RSP_ERROR:
2666 /*
2667 * Start timer for a delayed retry
2668 */
2669 if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
2670 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_retry);
2671 ms->port->stats.ms_retries++;
2672 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2673 &ms->timer, bfa_fcs_lport_ms_timeout, ms,
2674 BFA_FCS_RETRY_TIMEOUT);
2675 } else {
2676 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2677 ms->retry_cnt = 0;
2678 }
2679 break;
2680
2681 case MSSM_EVENT_RSP_OK:
2682 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2683 break;
2684
2685 case MSSM_EVENT_PORT_OFFLINE:
2686 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2687 bfa_fcxp_discard(ms->fcxp);
2688 break;
2689
2690 default:
2691 bfa_sm_fault(ms->port->fcs, event);
2692 }
2693}
2694
2695static void
2696bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
2697 enum port_ms_event event)
2698{
2699 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2700 bfa_trc(ms->port->fcs, event);
2701
2702 switch (event) {
2703 case MSSM_EVENT_TIMEOUT:
2704 /*
2705 * Retry Timer Expired. Re-send
2706 */
2707 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2708 bfa_fcs_lport_ms_send_gfn(ms, NULL);
2709 break;
2710
2711 case MSSM_EVENT_PORT_OFFLINE:
2712 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2713 bfa_timer_stop(&ms->timer);
2714 break;
2715
2716 default:
2717 bfa_sm_fault(ms->port->fcs, event);
2718 }
2719}
Jing Huang5fbe25c2010-10-18 17:17:23 -07002720/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002721 * ms_pvt MS local functions
2722 */
2723
2724static void
2725bfa_fcs_lport_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2726{
2727 struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
2728 bfa_fcs_lport_t *port = ms->port;
2729 struct fchs_s fchs;
2730 int len;
2731 struct bfa_fcxp_s *fcxp;
2732
2733 bfa_trc(port->fcs, port->pid);
2734
2735 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2736 if (!fcxp) {
2737 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
2738 bfa_fcs_lport_ms_send_gfn, ms);
2739 return;
2740 }
2741 ms->fcxp = fcxp;
2742
2743 len = fc_gfn_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2744 bfa_fcs_lport_get_fcid(port),
Maggie Zhangf7f738122010-12-09 19:08:43 -08002745 port->fabric->lps->pr_nwwn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002746
2747 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2748 FC_CLASS_3, len, &fchs,
2749 bfa_fcs_lport_ms_gfn_response, (void *)ms,
2750 FC_MAX_PDUSZ, FC_FCCT_TOV);
2751
2752 bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
2753}
2754
2755static void
2756bfa_fcs_lport_ms_gfn_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2757 void *cbarg, bfa_status_t req_status, u32 rsp_len,
2758 u32 resid_len, struct fchs_s *rsp_fchs)
2759{
2760 struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
2761 bfa_fcs_lport_t *port = ms->port;
2762 struct ct_hdr_s *cthdr = NULL;
2763 wwn_t *gfn_resp;
2764
2765 bfa_trc(port->fcs, req_status);
2766 bfa_trc(port->fcs, port->port_cfg.pwwn);
2767
2768 /*
2769 * Sanity Checks
2770 */
2771 if (req_status != BFA_STATUS_OK) {
2772 bfa_trc(port->fcs, req_status);
2773 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2774 return;
2775 }
2776
2777 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
Jing Huangba816ea2010-10-18 17:10:50 -07002778 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002779
2780 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2781 gfn_resp = (wwn_t *)(cthdr + 1);
2782 /* check if it has actually changed */
2783 if ((memcmp((void *)&bfa_fcs_lport_get_fabric_name(port),
2784 gfn_resp, sizeof(wwn_t)) != 0)) {
2785 bfa_fcs_fabric_set_fabric_name(port->fabric, *gfn_resp);
2786 }
2787 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
2788 return;
2789 }
2790
2791 bfa_trc(port->fcs, cthdr->reason_code);
2792 bfa_trc(port->fcs, cthdr->exp_code);
2793 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2794}
2795
Jing Huang5fbe25c2010-10-18 17:17:23 -07002796/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002797 * ms_pvt MS local functions
2798 */
2799
2800static void
2801bfa_fcs_lport_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2802{
2803 struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
2804 struct bfa_fcs_lport_s *port = ms->port;
2805 struct fchs_s fchs;
2806 int len;
2807 struct bfa_fcxp_s *fcxp;
2808
2809 bfa_trc(port->fcs, port->pid);
2810
2811 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2812 if (!fcxp) {
2813 port->stats.ms_plogi_alloc_wait++;
2814 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
2815 bfa_fcs_lport_ms_send_plogi, ms);
2816 return;
2817 }
2818 ms->fcxp = fcxp;
2819
2820 len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
Maggie Zhangf16a1752010-12-09 19:12:32 -08002821 bfa_hton3b(FC_MGMT_SERVER),
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002822 bfa_fcs_lport_get_fcid(port), 0,
2823 port->port_cfg.pwwn, port->port_cfg.nwwn,
2824 bfa_fcport_get_maxfrsize(port->fcs->bfa));
2825
2826 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2827 FC_CLASS_3, len, &fchs,
2828 bfa_fcs_lport_ms_plogi_response, (void *)ms,
2829 FC_MAX_PDUSZ, FC_ELS_TOV);
2830
2831 port->stats.ms_plogi_sent++;
2832 bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
2833}
2834
2835static void
2836bfa_fcs_lport_ms_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2837 void *cbarg, bfa_status_t req_status,
2838 u32 rsp_len, u32 resid_len, struct fchs_s *rsp_fchs)
2839{
2840 struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
2841 struct bfa_fcs_lport_s *port = ms->port;
2842 struct fc_els_cmd_s *els_cmd;
2843 struct fc_ls_rjt_s *ls_rjt;
2844
2845 bfa_trc(port->fcs, req_status);
2846 bfa_trc(port->fcs, port->port_cfg.pwwn);
2847
2848 /*
2849 * Sanity Checks
2850 */
2851 if (req_status != BFA_STATUS_OK) {
2852 port->stats.ms_plogi_rsp_err++;
2853 bfa_trc(port->fcs, req_status);
2854 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2855 return;
2856 }
2857
2858 els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
2859
2860 switch (els_cmd->els_code) {
2861
2862 case FC_ELS_ACC:
2863 if (rsp_len < sizeof(struct fc_logi_s)) {
2864 bfa_trc(port->fcs, rsp_len);
2865 port->stats.ms_plogi_acc_err++;
2866 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2867 break;
2868 }
2869 port->stats.ms_plogi_accepts++;
2870 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
2871 break;
2872
2873 case FC_ELS_LS_RJT:
2874 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
2875
2876 bfa_trc(port->fcs, ls_rjt->reason_code);
2877 bfa_trc(port->fcs, ls_rjt->reason_code_expl);
2878
2879 port->stats.ms_rejects++;
2880 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2881 break;
2882
2883 default:
2884 port->stats.ms_plogi_unknown_rsp++;
2885 bfa_trc(port->fcs, els_cmd->els_code);
2886 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2887 }
2888}
2889
2890static void
2891bfa_fcs_lport_ms_timeout(void *arg)
2892{
2893 struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) arg;
2894
2895 ms->port->stats.ms_timeouts++;
2896 bfa_sm_send_event(ms, MSSM_EVENT_TIMEOUT);
2897}
2898
2899
2900void
2901bfa_fcs_lport_ms_init(struct bfa_fcs_lport_s *port)
2902{
2903 struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
2904
2905 ms->port = port;
2906 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2907
2908 /*
2909 * Invoke init routines of sub modules.
2910 */
2911 bfa_fcs_lport_fdmi_init(ms);
2912}
2913
2914void
2915bfa_fcs_lport_ms_offline(struct bfa_fcs_lport_s *port)
2916{
2917 struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
2918
2919 ms->port = port;
2920 bfa_sm_send_event(ms, MSSM_EVENT_PORT_OFFLINE);
2921 bfa_fcs_lport_fdmi_offline(ms);
2922}
2923
2924void
2925bfa_fcs_lport_ms_online(struct bfa_fcs_lport_s *port)
2926{
2927 struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
2928
2929 ms->port = port;
2930 bfa_sm_send_event(ms, MSSM_EVENT_PORT_ONLINE);
2931}
2932void
2933bfa_fcs_lport_ms_fabric_rscn(struct bfa_fcs_lport_s *port)
2934{
2935 struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
2936
2937 /* todo. Handle this only when in Online state */
2938 if (bfa_sm_cmp_state(ms, bfa_fcs_lport_ms_sm_online))
2939 bfa_sm_send_event(ms, MSSM_EVENT_PORT_FABRIC_RSCN);
2940}
2941
Jing Huang5fbe25c2010-10-18 17:17:23 -07002942/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002943 * @page ns_sm_info VPORT NS State Machine
2944 *
2945 * @section ns_sm_interactions VPORT NS State Machine Interactions
2946 *
2947 * @section ns_sm VPORT NS State Machine
2948 * img ns_sm.jpg
2949 */
2950
2951/*
2952 * forward declarations
2953 */
2954static void bfa_fcs_lport_ns_send_plogi(void *ns_cbarg,
2955 struct bfa_fcxp_s *fcxp_alloced);
2956static void bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg,
2957 struct bfa_fcxp_s *fcxp_alloced);
2958static void bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg,
2959 struct bfa_fcxp_s *fcxp_alloced);
2960static void bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg,
2961 struct bfa_fcxp_s *fcxp_alloced);
2962static void bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg,
2963 struct bfa_fcxp_s *fcxp_alloced);
2964static void bfa_fcs_lport_ns_timeout(void *arg);
2965static void bfa_fcs_lport_ns_plogi_response(void *fcsarg,
2966 struct bfa_fcxp_s *fcxp,
2967 void *cbarg,
2968 bfa_status_t req_status,
2969 u32 rsp_len,
2970 u32 resid_len,
2971 struct fchs_s *rsp_fchs);
2972static void bfa_fcs_lport_ns_rspn_id_response(void *fcsarg,
2973 struct bfa_fcxp_s *fcxp,
2974 void *cbarg,
2975 bfa_status_t req_status,
2976 u32 rsp_len,
2977 u32 resid_len,
2978 struct fchs_s *rsp_fchs);
2979static void bfa_fcs_lport_ns_rft_id_response(void *fcsarg,
2980 struct bfa_fcxp_s *fcxp,
2981 void *cbarg,
2982 bfa_status_t req_status,
2983 u32 rsp_len,
2984 u32 resid_len,
2985 struct fchs_s *rsp_fchs);
2986static void bfa_fcs_lport_ns_rff_id_response(void *fcsarg,
2987 struct bfa_fcxp_s *fcxp,
2988 void *cbarg,
2989 bfa_status_t req_status,
2990 u32 rsp_len,
2991 u32 resid_len,
2992 struct fchs_s *rsp_fchs);
2993static void bfa_fcs_lport_ns_gid_ft_response(void *fcsarg,
2994 struct bfa_fcxp_s *fcxp,
2995 void *cbarg,
2996 bfa_status_t req_status,
2997 u32 rsp_len,
2998 u32 resid_len,
2999 struct fchs_s *rsp_fchs);
3000static void bfa_fcs_lport_ns_process_gidft_pids(
3001 struct bfa_fcs_lport_s *port,
3002 u32 *pid_buf, u32 n_pids);
3003
3004static void bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port);
Jing Huang5fbe25c2010-10-18 17:17:23 -07003005/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003006 * fcs_ns_sm FCS nameserver interface state machine
3007 */
3008
Jing Huang5fbe25c2010-10-18 17:17:23 -07003009/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003010 * VPort NS State Machine events
3011 */
3012enum vport_ns_event {
3013 NSSM_EVENT_PORT_ONLINE = 1,
3014 NSSM_EVENT_PORT_OFFLINE = 2,
3015 NSSM_EVENT_PLOGI_SENT = 3,
3016 NSSM_EVENT_RSP_OK = 4,
3017 NSSM_EVENT_RSP_ERROR = 5,
3018 NSSM_EVENT_TIMEOUT = 6,
3019 NSSM_EVENT_NS_QUERY = 7,
3020 NSSM_EVENT_RSPNID_SENT = 8,
3021 NSSM_EVENT_RFTID_SENT = 9,
3022 NSSM_EVENT_RFFID_SENT = 10,
3023 NSSM_EVENT_GIDFT_SENT = 11,
3024};
3025
3026static void bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
3027 enum vport_ns_event event);
3028static void bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns,
3029 enum vport_ns_event event);
3030static void bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
3031 enum vport_ns_event event);
3032static void bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
3033 enum vport_ns_event event);
3034static void bfa_fcs_lport_ns_sm_sending_rspn_id(
3035 struct bfa_fcs_lport_ns_s *ns,
3036 enum vport_ns_event event);
3037static void bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3038 enum vport_ns_event event);
3039static void bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3040 enum vport_ns_event event);
3041static void bfa_fcs_lport_ns_sm_sending_rft_id(
3042 struct bfa_fcs_lport_ns_s *ns,
3043 enum vport_ns_event event);
3044static void bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns,
3045 enum vport_ns_event event);
3046static void bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns,
3047 enum vport_ns_event event);
3048static void bfa_fcs_lport_ns_sm_sending_rff_id(
3049 struct bfa_fcs_lport_ns_s *ns,
3050 enum vport_ns_event event);
3051static void bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns,
3052 enum vport_ns_event event);
3053static void bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns,
3054 enum vport_ns_event event);
3055static void bfa_fcs_lport_ns_sm_sending_gid_ft(
3056 struct bfa_fcs_lport_ns_s *ns,
3057 enum vport_ns_event event);
3058static void bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3059 enum vport_ns_event event);
3060static void bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
3061 enum vport_ns_event event);
3062static void bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
3063 enum vport_ns_event event);
Jing Huang5fbe25c2010-10-18 17:17:23 -07003064/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003065 * Start in offline state - awaiting linkup
3066 */
3067static void
3068bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
3069 enum vport_ns_event event)
3070{
3071 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3072 bfa_trc(ns->port->fcs, event);
3073
3074 switch (event) {
3075 case NSSM_EVENT_PORT_ONLINE:
3076 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending);
3077 bfa_fcs_lport_ns_send_plogi(ns, NULL);
3078 break;
3079
3080 case NSSM_EVENT_PORT_OFFLINE:
3081 break;
3082
3083 default:
3084 bfa_sm_fault(ns->port->fcs, event);
3085 }
3086}
3087
3088static void
3089bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns,
3090 enum vport_ns_event event)
3091{
3092 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3093 bfa_trc(ns->port->fcs, event);
3094
3095 switch (event) {
3096 case NSSM_EVENT_PLOGI_SENT:
3097 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi);
3098 break;
3099
3100 case NSSM_EVENT_PORT_OFFLINE:
3101 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3102 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3103 &ns->fcxp_wqe);
3104 break;
3105
3106 default:
3107 bfa_sm_fault(ns->port->fcs, event);
3108 }
3109}
3110
3111static void
3112bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
3113 enum vport_ns_event event)
3114{
3115 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3116 bfa_trc(ns->port->fcs, event);
3117
3118 switch (event) {
3119 case NSSM_EVENT_RSP_ERROR:
3120 /*
3121 * Start timer for a delayed retry
3122 */
3123 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_retry);
3124 ns->port->stats.ns_retries++;
3125 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3126 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3127 BFA_FCS_RETRY_TIMEOUT);
3128 break;
3129
3130 case NSSM_EVENT_RSP_OK:
3131 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
3132 bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
3133 break;
3134
3135 case NSSM_EVENT_PORT_OFFLINE:
3136 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3137 bfa_fcxp_discard(ns->fcxp);
3138 break;
3139
3140 default:
3141 bfa_sm_fault(ns->port->fcs, event);
3142 }
3143}
3144
3145static void
3146bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
3147 enum vport_ns_event event)
3148{
3149 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3150 bfa_trc(ns->port->fcs, event);
3151
3152 switch (event) {
3153 case NSSM_EVENT_TIMEOUT:
3154 /*
3155 * Retry Timer Expired. Re-send
3156 */
3157 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending);
3158 bfa_fcs_lport_ns_send_plogi(ns, NULL);
3159 break;
3160
3161 case NSSM_EVENT_PORT_OFFLINE:
3162 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3163 bfa_timer_stop(&ns->timer);
3164 break;
3165
3166 default:
3167 bfa_sm_fault(ns->port->fcs, event);
3168 }
3169}
3170
3171static void
3172bfa_fcs_lport_ns_sm_sending_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3173 enum vport_ns_event event)
3174{
3175 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3176 bfa_trc(ns->port->fcs, event);
3177
3178 switch (event) {
3179 case NSSM_EVENT_RSPNID_SENT:
3180 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id);
3181 break;
3182
3183 case NSSM_EVENT_PORT_OFFLINE:
3184 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3185 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3186 &ns->fcxp_wqe);
3187 break;
3188
3189 default:
3190 bfa_sm_fault(ns->port->fcs, event);
3191 }
3192}
3193
3194static void
3195bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3196 enum vport_ns_event event)
3197{
3198 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3199 bfa_trc(ns->port->fcs, event);
3200
3201 switch (event) {
3202 case NSSM_EVENT_RSP_ERROR:
3203 /*
3204 * Start timer for a delayed retry
3205 */
3206 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id_retry);
3207 ns->port->stats.ns_retries++;
3208 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3209 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3210 BFA_FCS_RETRY_TIMEOUT);
3211 break;
3212
3213 case NSSM_EVENT_RSP_OK:
3214 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id);
3215 bfa_fcs_lport_ns_send_rft_id(ns, NULL);
3216 break;
3217
3218 case NSSM_EVENT_PORT_OFFLINE:
3219 bfa_fcxp_discard(ns->fcxp);
3220 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3221 break;
3222
3223 default:
3224 bfa_sm_fault(ns->port->fcs, event);
3225 }
3226}
3227
3228static void
3229bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3230 enum vport_ns_event event)
3231{
3232 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3233 bfa_trc(ns->port->fcs, event);
3234
3235 switch (event) {
3236 case NSSM_EVENT_TIMEOUT:
3237 /*
3238 * Retry Timer Expired. Re-send
3239 */
3240 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
3241 bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
3242 break;
3243
3244 case NSSM_EVENT_PORT_OFFLINE:
3245 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3246 bfa_timer_stop(&ns->timer);
3247 break;
3248
3249 default:
3250 bfa_sm_fault(ns->port->fcs, event);
3251 }
3252}
3253
3254static void
3255bfa_fcs_lport_ns_sm_sending_rft_id(struct bfa_fcs_lport_ns_s *ns,
3256 enum vport_ns_event event)
3257{
3258 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3259 bfa_trc(ns->port->fcs, event);
3260
3261 switch (event) {
3262 case NSSM_EVENT_RFTID_SENT:
3263 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id);
3264 break;
3265
3266 case NSSM_EVENT_PORT_OFFLINE:
3267 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3268 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3269 &ns->fcxp_wqe);
3270 break;
3271
3272 default:
3273 bfa_sm_fault(ns->port->fcs, event);
3274 }
3275}
3276
3277static void
3278bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns,
3279 enum vport_ns_event event)
3280{
3281 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3282 bfa_trc(ns->port->fcs, event);
3283
3284 switch (event) {
3285 case NSSM_EVENT_RSP_OK:
3286 /* Now move to register FC4 Features */
3287 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id);
3288 bfa_fcs_lport_ns_send_rff_id(ns, NULL);
3289 break;
3290
3291 case NSSM_EVENT_RSP_ERROR:
3292 /*
3293 * Start timer for a delayed retry
3294 */
3295 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id_retry);
3296 ns->port->stats.ns_retries++;
3297 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3298 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3299 BFA_FCS_RETRY_TIMEOUT);
3300 break;
3301
3302 case NSSM_EVENT_PORT_OFFLINE:
3303 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3304 bfa_fcxp_discard(ns->fcxp);
3305 break;
3306
3307 default:
3308 bfa_sm_fault(ns->port->fcs, event);
3309 }
3310}
3311
3312static void
3313bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns,
3314 enum vport_ns_event event)
3315{
3316 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3317 bfa_trc(ns->port->fcs, event);
3318
3319 switch (event) {
3320 case NSSM_EVENT_TIMEOUT:
3321 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id);
3322 bfa_fcs_lport_ns_send_rft_id(ns, NULL);
3323 break;
3324
3325 case NSSM_EVENT_PORT_OFFLINE:
3326 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3327 bfa_timer_stop(&ns->timer);
3328 break;
3329
3330 default:
3331 bfa_sm_fault(ns->port->fcs, event);
3332 }
3333}
3334
3335static void
3336bfa_fcs_lport_ns_sm_sending_rff_id(struct bfa_fcs_lport_ns_s *ns,
3337 enum vport_ns_event event)
3338{
3339 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3340 bfa_trc(ns->port->fcs, event);
3341
3342 switch (event) {
3343 case NSSM_EVENT_RFFID_SENT:
3344 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id);
3345 break;
3346
3347 case NSSM_EVENT_PORT_OFFLINE:
3348 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3349 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3350 &ns->fcxp_wqe);
3351 break;
3352
3353 default:
3354 bfa_sm_fault(ns->port->fcs, event);
3355 }
3356}
3357
3358static void
3359bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns,
3360 enum vport_ns_event event)
3361{
3362 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3363 bfa_trc(ns->port->fcs, event);
3364
3365 switch (event) {
3366 case NSSM_EVENT_RSP_OK:
3367
3368 /*
3369 * If min cfg mode is enabled, we donot initiate rport
3370 * discovery with the fabric. Instead, we will retrieve the
3371 * boot targets from HAL/FW.
3372 */
3373 if (__fcs_min_cfg(ns->port->fcs)) {
3374 bfa_fcs_lport_ns_boot_target_disc(ns->port);
3375 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online);
3376 return;
3377 }
3378
3379 /*
3380 * If the port role is Initiator Mode issue NS query.
3381 * If it is Target Mode, skip this and go to online.
3382 */
3383 if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
3384 bfa_sm_set_state(ns,
3385 bfa_fcs_lport_ns_sm_sending_gid_ft);
3386 bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
3387 }
3388 /*
3389 * kick off mgmt srvr state machine
3390 */
3391 bfa_fcs_lport_ms_online(ns->port);
3392 break;
3393
3394 case NSSM_EVENT_RSP_ERROR:
3395 /*
3396 * Start timer for a delayed retry
3397 */
3398 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id_retry);
3399 ns->port->stats.ns_retries++;
3400 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3401 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3402 BFA_FCS_RETRY_TIMEOUT);
3403 break;
3404
3405 case NSSM_EVENT_PORT_OFFLINE:
3406 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3407 bfa_fcxp_discard(ns->fcxp);
3408 break;
3409
3410 default:
3411 bfa_sm_fault(ns->port->fcs, event);
3412 }
3413}
3414
3415static void
3416bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns,
3417 enum vport_ns_event event)
3418{
3419 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3420 bfa_trc(ns->port->fcs, event);
3421
3422 switch (event) {
3423 case NSSM_EVENT_TIMEOUT:
3424 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id);
3425 bfa_fcs_lport_ns_send_rff_id(ns, NULL);
3426 break;
3427
3428 case NSSM_EVENT_PORT_OFFLINE:
3429 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3430 bfa_timer_stop(&ns->timer);
3431 break;
3432
3433 default:
3434 bfa_sm_fault(ns->port->fcs, event);
3435 }
3436}
3437static void
3438bfa_fcs_lport_ns_sm_sending_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3439 enum vport_ns_event event)
3440{
3441 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3442 bfa_trc(ns->port->fcs, event);
3443
3444 switch (event) {
3445 case NSSM_EVENT_GIDFT_SENT:
3446 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft);
3447 break;
3448
3449 case NSSM_EVENT_PORT_OFFLINE:
3450 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3451 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3452 &ns->fcxp_wqe);
3453 break;
3454
3455 default:
3456 bfa_sm_fault(ns->port->fcs, event);
3457 }
3458}
3459
3460static void
3461bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3462 enum vport_ns_event event)
3463{
3464 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3465 bfa_trc(ns->port->fcs, event);
3466
3467 switch (event) {
3468 case NSSM_EVENT_RSP_OK:
3469 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online);
3470 break;
3471
3472 case NSSM_EVENT_RSP_ERROR:
3473 /*
3474 * TBD: for certain reject codes, we don't need to retry
3475 */
3476 /*
3477 * Start timer for a delayed retry
3478 */
3479 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft_retry);
3480 ns->port->stats.ns_retries++;
3481 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3482 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3483 BFA_FCS_RETRY_TIMEOUT);
3484 break;
3485
3486 case NSSM_EVENT_PORT_OFFLINE:
3487 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3488 bfa_fcxp_discard(ns->fcxp);
3489 break;
3490
3491 case NSSM_EVENT_NS_QUERY:
3492 break;
3493
3494 default:
3495 bfa_sm_fault(ns->port->fcs, event);
3496 }
3497}
3498
3499static void
3500bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
3501 enum vport_ns_event event)
3502{
3503 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3504 bfa_trc(ns->port->fcs, event);
3505
3506 switch (event) {
3507 case NSSM_EVENT_TIMEOUT:
3508 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_gid_ft);
3509 bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
3510 break;
3511
3512 case NSSM_EVENT_PORT_OFFLINE:
3513 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3514 bfa_timer_stop(&ns->timer);
3515 break;
3516
3517 default:
3518 bfa_sm_fault(ns->port->fcs, event);
3519 }
3520}
3521
3522static void
3523bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
3524 enum vport_ns_event event)
3525{
3526 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3527 bfa_trc(ns->port->fcs, event);
3528
3529 switch (event) {
3530 case NSSM_EVENT_PORT_OFFLINE:
3531 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3532 break;
3533
3534 case NSSM_EVENT_NS_QUERY:
3535 /*
3536 * If the port role is Initiator Mode issue NS query.
3537 * If it is Target Mode, skip this and go to online.
3538 */
3539 if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
3540 bfa_sm_set_state(ns,
3541 bfa_fcs_lport_ns_sm_sending_gid_ft);
3542 bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
3543 };
3544 break;
3545
3546 default:
3547 bfa_sm_fault(ns->port->fcs, event);
3548 }
3549}
3550
3551
3552
Jing Huang5fbe25c2010-10-18 17:17:23 -07003553/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003554 * ns_pvt Nameserver local functions
3555 */
3556
3557static void
3558bfa_fcs_lport_ns_send_plogi(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3559{
3560 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3561 struct bfa_fcs_lport_s *port = ns->port;
3562 struct fchs_s fchs;
3563 int len;
3564 struct bfa_fcxp_s *fcxp;
3565
3566 bfa_trc(port->fcs, port->pid);
3567
3568fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3569 if (!fcxp) {
3570 port->stats.ns_plogi_alloc_wait++;
3571 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3572 bfa_fcs_lport_ns_send_plogi, ns);
3573 return;
3574 }
3575 ns->fcxp = fcxp;
3576
3577 len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
Maggie Zhangf16a1752010-12-09 19:12:32 -08003578 bfa_hton3b(FC_NAME_SERVER),
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003579 bfa_fcs_lport_get_fcid(port), 0,
3580 port->port_cfg.pwwn, port->port_cfg.nwwn,
3581 bfa_fcport_get_maxfrsize(port->fcs->bfa));
3582
3583 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3584 FC_CLASS_3, len, &fchs,
3585 bfa_fcs_lport_ns_plogi_response, (void *)ns,
3586 FC_MAX_PDUSZ, FC_ELS_TOV);
3587 port->stats.ns_plogi_sent++;
3588
3589 bfa_sm_send_event(ns, NSSM_EVENT_PLOGI_SENT);
3590}
3591
3592static void
3593bfa_fcs_lport_ns_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3594 void *cbarg, bfa_status_t req_status, u32 rsp_len,
3595 u32 resid_len, struct fchs_s *rsp_fchs)
3596{
3597 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3598 struct bfa_fcs_lport_s *port = ns->port;
3599 /* struct fc_logi_s *plogi_resp; */
3600 struct fc_els_cmd_s *els_cmd;
3601 struct fc_ls_rjt_s *ls_rjt;
3602
3603 bfa_trc(port->fcs, req_status);
3604 bfa_trc(port->fcs, port->port_cfg.pwwn);
3605
3606 /*
3607 * Sanity Checks
3608 */
3609 if (req_status != BFA_STATUS_OK) {
3610 bfa_trc(port->fcs, req_status);
3611 port->stats.ns_plogi_rsp_err++;
3612 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3613 return;
3614 }
3615
3616 els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
3617
3618 switch (els_cmd->els_code) {
3619
3620 case FC_ELS_ACC:
3621 if (rsp_len < sizeof(struct fc_logi_s)) {
3622 bfa_trc(port->fcs, rsp_len);
3623 port->stats.ns_plogi_acc_err++;
3624 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3625 break;
3626 }
3627 port->stats.ns_plogi_accepts++;
3628 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3629 break;
3630
3631 case FC_ELS_LS_RJT:
3632 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
3633
3634 bfa_trc(port->fcs, ls_rjt->reason_code);
3635 bfa_trc(port->fcs, ls_rjt->reason_code_expl);
3636
3637 port->stats.ns_rejects++;
3638
3639 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3640 break;
3641
3642 default:
3643 port->stats.ns_plogi_unknown_rsp++;
3644 bfa_trc(port->fcs, els_cmd->els_code);
3645 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3646 }
3647}
3648
Jing Huang5fbe25c2010-10-18 17:17:23 -07003649/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003650 * Register the symbolic port name.
3651 */
3652static void
3653bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3654{
3655 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3656 struct bfa_fcs_lport_s *port = ns->port;
3657 struct fchs_s fchs;
3658 int len;
3659 struct bfa_fcxp_s *fcxp;
3660 u8 symbl[256];
3661 u8 *psymbl = &symbl[0];
3662
Jing Huang6a18b162010-10-18 17:08:54 -07003663 memset(symbl, 0, sizeof(symbl));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003664
3665 bfa_trc(port->fcs, port->port_cfg.pwwn);
3666
3667 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3668 if (!fcxp) {
3669 port->stats.ns_rspnid_alloc_wait++;
3670 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3671 bfa_fcs_lport_ns_send_rspn_id, ns);
3672 return;
3673 }
3674 ns->fcxp = fcxp;
3675
3676 /*
3677 * for V-Port, form a Port Symbolic Name
3678 */
3679 if (port->vport) {
Jing Huang5fbe25c2010-10-18 17:17:23 -07003680 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003681 * For Vports, we append the vport's port symbolic name
3682 * to that of the base port.
3683 */
3684
3685 strncpy((char *)psymbl,
3686 (char *) &
3687 (bfa_fcs_lport_get_psym_name
3688 (bfa_fcs_get_base_port(port->fcs))),
3689 strlen((char *) &
3690 bfa_fcs_lport_get_psym_name(bfa_fcs_get_base_port
3691 (port->fcs))));
3692
3693 /* Ensure we have a null terminating string. */
3694 ((char *)psymbl)[strlen((char *) &
3695 bfa_fcs_lport_get_psym_name(bfa_fcs_get_base_port
3696 (port->fcs)))] = 0;
3697 strncat((char *)psymbl,
3698 (char *) &(bfa_fcs_lport_get_psym_name(port)),
3699 strlen((char *) &bfa_fcs_lport_get_psym_name(port)));
3700 } else {
3701 psymbl = (u8 *) &(bfa_fcs_lport_get_psym_name(port));
3702 }
3703
3704 len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3705 bfa_fcs_lport_get_fcid(port), 0, psymbl);
3706
3707 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3708 FC_CLASS_3, len, &fchs,
3709 bfa_fcs_lport_ns_rspn_id_response, (void *)ns,
3710 FC_MAX_PDUSZ, FC_FCCT_TOV);
3711
3712 port->stats.ns_rspnid_sent++;
3713
3714 bfa_sm_send_event(ns, NSSM_EVENT_RSPNID_SENT);
3715}
3716
3717static void
3718bfa_fcs_lport_ns_rspn_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3719 void *cbarg, bfa_status_t req_status,
3720 u32 rsp_len, u32 resid_len,
3721 struct fchs_s *rsp_fchs)
3722{
3723 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3724 struct bfa_fcs_lport_s *port = ns->port;
3725 struct ct_hdr_s *cthdr = NULL;
3726
3727 bfa_trc(port->fcs, port->port_cfg.pwwn);
3728
3729 /*
3730 * Sanity Checks
3731 */
3732 if (req_status != BFA_STATUS_OK) {
3733 bfa_trc(port->fcs, req_status);
3734 port->stats.ns_rspnid_rsp_err++;
3735 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3736 return;
3737 }
3738
3739 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
Jing Huangba816ea2010-10-18 17:10:50 -07003740 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003741
3742 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
3743 port->stats.ns_rspnid_accepts++;
3744 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3745 return;
3746 }
3747
3748 port->stats.ns_rspnid_rejects++;
3749 bfa_trc(port->fcs, cthdr->reason_code);
3750 bfa_trc(port->fcs, cthdr->exp_code);
3751 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3752}
3753
Jing Huang5fbe25c2010-10-18 17:17:23 -07003754/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003755 * Register FC4-Types
3756 */
3757static void
3758bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3759{
3760 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3761 struct bfa_fcs_lport_s *port = ns->port;
3762 struct fchs_s fchs;
3763 int len;
3764 struct bfa_fcxp_s *fcxp;
3765
3766 bfa_trc(port->fcs, port->port_cfg.pwwn);
3767
3768 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3769 if (!fcxp) {
3770 port->stats.ns_rftid_alloc_wait++;
3771 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3772 bfa_fcs_lport_ns_send_rft_id, ns);
3773 return;
3774 }
3775 ns->fcxp = fcxp;
3776
3777 len = fc_rftid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3778 bfa_fcs_lport_get_fcid(port), 0, port->port_cfg.roles);
3779
3780 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3781 FC_CLASS_3, len, &fchs,
3782 bfa_fcs_lport_ns_rft_id_response, (void *)ns,
3783 FC_MAX_PDUSZ, FC_FCCT_TOV);
3784
3785 port->stats.ns_rftid_sent++;
3786 bfa_sm_send_event(ns, NSSM_EVENT_RFTID_SENT);
3787}
3788
3789static void
3790bfa_fcs_lport_ns_rft_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3791 void *cbarg, bfa_status_t req_status,
3792 u32 rsp_len, u32 resid_len,
3793 struct fchs_s *rsp_fchs)
3794{
3795 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3796 struct bfa_fcs_lport_s *port = ns->port;
3797 struct ct_hdr_s *cthdr = NULL;
3798
3799 bfa_trc(port->fcs, port->port_cfg.pwwn);
3800
3801 /*
3802 * Sanity Checks
3803 */
3804 if (req_status != BFA_STATUS_OK) {
3805 bfa_trc(port->fcs, req_status);
3806 port->stats.ns_rftid_rsp_err++;
3807 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3808 return;
3809 }
3810
3811 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
Jing Huangba816ea2010-10-18 17:10:50 -07003812 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003813
3814 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
3815 port->stats.ns_rftid_accepts++;
3816 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3817 return;
3818 }
3819
3820 port->stats.ns_rftid_rejects++;
3821 bfa_trc(port->fcs, cthdr->reason_code);
3822 bfa_trc(port->fcs, cthdr->exp_code);
3823 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3824}
3825
Jing Huang5fbe25c2010-10-18 17:17:23 -07003826/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003827 * Register FC4-Features : Should be done after RFT_ID
3828 */
3829static void
3830bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3831{
3832 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3833 struct bfa_fcs_lport_s *port = ns->port;
3834 struct fchs_s fchs;
3835 int len;
3836 struct bfa_fcxp_s *fcxp;
3837 u8 fc4_ftrs = 0;
3838
3839 bfa_trc(port->fcs, port->port_cfg.pwwn);
3840
3841 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3842 if (!fcxp) {
3843 port->stats.ns_rffid_alloc_wait++;
3844 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3845 bfa_fcs_lport_ns_send_rff_id, ns);
3846 return;
3847 }
3848 ns->fcxp = fcxp;
3849
3850 if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port))
3851 fc4_ftrs = FC_GS_FCP_FC4_FEATURE_INITIATOR;
3852
3853 len = fc_rffid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3854 bfa_fcs_lport_get_fcid(port), 0,
3855 FC_TYPE_FCP, fc4_ftrs);
3856
3857 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3858 FC_CLASS_3, len, &fchs,
3859 bfa_fcs_lport_ns_rff_id_response, (void *)ns,
3860 FC_MAX_PDUSZ, FC_FCCT_TOV);
3861
3862 port->stats.ns_rffid_sent++;
3863 bfa_sm_send_event(ns, NSSM_EVENT_RFFID_SENT);
3864}
3865
3866static void
3867bfa_fcs_lport_ns_rff_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3868 void *cbarg, bfa_status_t req_status,
3869 u32 rsp_len, u32 resid_len,
3870 struct fchs_s *rsp_fchs)
3871{
3872 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3873 struct bfa_fcs_lport_s *port = ns->port;
3874 struct ct_hdr_s *cthdr = NULL;
3875
3876 bfa_trc(port->fcs, port->port_cfg.pwwn);
3877
3878 /*
3879 * Sanity Checks
3880 */
3881 if (req_status != BFA_STATUS_OK) {
3882 bfa_trc(port->fcs, req_status);
3883 port->stats.ns_rffid_rsp_err++;
3884 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3885 return;
3886 }
3887
3888 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
Jing Huangba816ea2010-10-18 17:10:50 -07003889 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003890
3891 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
3892 port->stats.ns_rffid_accepts++;
3893 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3894 return;
3895 }
3896
3897 port->stats.ns_rffid_rejects++;
3898 bfa_trc(port->fcs, cthdr->reason_code);
3899 bfa_trc(port->fcs, cthdr->exp_code);
3900
3901 if (cthdr->reason_code == CT_RSN_NOT_SUPP) {
3902 /* if this command is not supported, we don't retry */
3903 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3904 } else
3905 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3906}
Jing Huang5fbe25c2010-10-18 17:17:23 -07003907/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003908 * Query Fabric for FC4-Types Devices.
3909 *
3910* TBD : Need to use a local (FCS private) response buffer, since the response
3911 * can be larger than 2K.
3912 */
3913static void
3914bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3915{
3916 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3917 struct bfa_fcs_lport_s *port = ns->port;
3918 struct fchs_s fchs;
3919 int len;
3920 struct bfa_fcxp_s *fcxp;
3921
3922 bfa_trc(port->fcs, port->pid);
3923
3924 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3925 if (!fcxp) {
3926 port->stats.ns_gidft_alloc_wait++;
3927 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3928 bfa_fcs_lport_ns_send_gid_ft, ns);
3929 return;
3930 }
3931 ns->fcxp = fcxp;
3932
3933 /*
3934 * This query is only initiated for FCP initiator mode.
3935 */
3936 len = fc_gid_ft_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3937 ns->port->pid, FC_TYPE_FCP);
3938
3939 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3940 FC_CLASS_3, len, &fchs,
3941 bfa_fcs_lport_ns_gid_ft_response, (void *)ns,
3942 bfa_fcxp_get_maxrsp(port->fcs->bfa), FC_FCCT_TOV);
3943
3944 port->stats.ns_gidft_sent++;
3945
3946 bfa_sm_send_event(ns, NSSM_EVENT_GIDFT_SENT);
3947}
3948
3949static void
3950bfa_fcs_lport_ns_gid_ft_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3951 void *cbarg, bfa_status_t req_status,
3952 u32 rsp_len, u32 resid_len,
3953 struct fchs_s *rsp_fchs)
3954{
3955 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3956 struct bfa_fcs_lport_s *port = ns->port;
3957 struct ct_hdr_s *cthdr = NULL;
3958 u32 n_pids;
3959
3960 bfa_trc(port->fcs, port->port_cfg.pwwn);
3961
3962 /*
3963 * Sanity Checks
3964 */
3965 if (req_status != BFA_STATUS_OK) {
3966 bfa_trc(port->fcs, req_status);
3967 port->stats.ns_gidft_rsp_err++;
3968 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3969 return;
3970 }
3971
3972 if (resid_len != 0) {
3973 /*
3974 * TBD : we will need to allocate a larger buffer & retry the
3975 * command
3976 */
3977 bfa_trc(port->fcs, rsp_len);
3978 bfa_trc(port->fcs, resid_len);
3979 return;
3980 }
3981
3982 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
Jing Huangba816ea2010-10-18 17:10:50 -07003983 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003984
3985 switch (cthdr->cmd_rsp_code) {
3986
3987 case CT_RSP_ACCEPT:
3988
3989 port->stats.ns_gidft_accepts++;
3990 n_pids = (fc_get_ctresp_pyld_len(rsp_len) / sizeof(u32));
3991 bfa_trc(port->fcs, n_pids);
3992 bfa_fcs_lport_ns_process_gidft_pids(port,
3993 (u32 *) (cthdr + 1),
3994 n_pids);
3995 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3996 break;
3997
3998 case CT_RSP_REJECT:
3999
4000 /*
4001 * Check the reason code & explanation.
4002 * There may not have been any FC4 devices in the fabric
4003 */
4004 port->stats.ns_gidft_rejects++;
4005 bfa_trc(port->fcs, cthdr->reason_code);
4006 bfa_trc(port->fcs, cthdr->exp_code);
4007
4008 if ((cthdr->reason_code == CT_RSN_UNABLE_TO_PERF)
4009 && (cthdr->exp_code == CT_NS_EXP_FT_NOT_REG)) {
4010
4011 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4012 } else {
4013 /*
4014 * for all other errors, retry
4015 */
4016 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4017 }
4018 break;
4019
4020 default:
4021 port->stats.ns_gidft_unknown_rsp++;
4022 bfa_trc(port->fcs, cthdr->cmd_rsp_code);
4023 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4024 }
4025}
4026
Jing Huang5fbe25c2010-10-18 17:17:23 -07004027/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004028 * This routine will be called by bfa_timer on timer timeouts.
4029 *
4030 * param[in] port - pointer to bfa_fcs_lport_t.
4031 *
4032 * return
4033 * void
4034 *
4035 * Special Considerations:
4036 *
4037 * note
4038 */
4039static void
4040bfa_fcs_lport_ns_timeout(void *arg)
4041{
4042 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) arg;
4043
4044 ns->port->stats.ns_timeouts++;
4045 bfa_sm_send_event(ns, NSSM_EVENT_TIMEOUT);
4046}
4047
4048/*
4049 * Process the PID list in GID_FT response
4050 */
4051static void
4052bfa_fcs_lport_ns_process_gidft_pids(struct bfa_fcs_lport_s *port, u32 *pid_buf,
4053 u32 n_pids)
4054{
4055 struct fcgs_gidft_resp_s *gidft_entry;
4056 struct bfa_fcs_rport_s *rport;
4057 u32 ii;
4058
4059 for (ii = 0; ii < n_pids; ii++) {
4060 gidft_entry = (struct fcgs_gidft_resp_s *) &pid_buf[ii];
4061
4062 if (gidft_entry->pid == port->pid)
4063 continue;
4064
4065 /*
4066 * Check if this rport already exists
4067 */
4068 rport = bfa_fcs_lport_get_rport_by_pid(port, gidft_entry->pid);
4069 if (rport == NULL) {
4070 /*
4071 * this is a new device. create rport
4072 */
4073 rport = bfa_fcs_rport_create(port, gidft_entry->pid);
4074 } else {
4075 /*
4076 * this rport already exists
4077 */
4078 bfa_fcs_rport_scn(rport);
4079 }
4080
4081 bfa_trc(port->fcs, gidft_entry->pid);
4082
4083 /*
4084 * if the last entry bit is set, bail out.
4085 */
4086 if (gidft_entry->last)
4087 return;
4088 }
4089}
4090
Jing Huang5fbe25c2010-10-18 17:17:23 -07004091/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004092 * fcs_ns_public FCS nameserver public interfaces
4093 */
4094
4095/*
4096 * Functions called by port/fab.
4097 * These will send relevant Events to the ns state machine.
4098 */
4099void
4100bfa_fcs_lport_ns_init(struct bfa_fcs_lport_s *port)
4101{
4102 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4103
4104 ns->port = port;
4105 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4106}
4107
4108void
4109bfa_fcs_lport_ns_offline(struct bfa_fcs_lport_s *port)
4110{
4111 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4112
4113 ns->port = port;
4114 bfa_sm_send_event(ns, NSSM_EVENT_PORT_OFFLINE);
4115}
4116
4117void
4118bfa_fcs_lport_ns_online(struct bfa_fcs_lport_s *port)
4119{
4120 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4121
4122 ns->port = port;
4123 bfa_sm_send_event(ns, NSSM_EVENT_PORT_ONLINE);
4124}
4125
4126void
4127bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s *port)
4128{
4129 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4130
4131 bfa_trc(port->fcs, port->pid);
4132 bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY);
4133}
4134
Maggie52f94b62010-11-29 18:21:32 -08004135static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004136bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port)
4137{
4138
4139 struct bfa_fcs_rport_s *rport;
4140 u8 nwwns;
4141 wwn_t wwns[BFA_PREBOOT_BOOTLUN_MAX];
4142 int ii;
4143
4144 bfa_iocfc_get_bootwwns(port->fcs->bfa, &nwwns, wwns);
4145
4146 for (ii = 0 ; ii < nwwns; ++ii) {
4147 rport = bfa_fcs_rport_create_by_wwn(port, wwns[ii]);
4148 bfa_assert(rport);
4149 }
4150}
4151
Jing Huang5fbe25c2010-10-18 17:17:23 -07004152/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004153 * FCS SCN
4154 */
4155
4156#define FC_QOS_RSCN_EVENT 0x0c
4157#define FC_FABRIC_NAME_RSCN_EVENT 0x0d
4158
4159/*
4160 * forward declarations
4161 */
4162static void bfa_fcs_lport_scn_send_scr(void *scn_cbarg,
4163 struct bfa_fcxp_s *fcxp_alloced);
4164static void bfa_fcs_lport_scn_scr_response(void *fcsarg,
4165 struct bfa_fcxp_s *fcxp,
4166 void *cbarg,
4167 bfa_status_t req_status,
4168 u32 rsp_len,
4169 u32 resid_len,
4170 struct fchs_s *rsp_fchs);
4171static void bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
4172 struct fchs_s *rx_fchs);
4173static void bfa_fcs_lport_scn_timeout(void *arg);
4174
Jing Huang5fbe25c2010-10-18 17:17:23 -07004175/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004176 * fcs_scm_sm FCS SCN state machine
4177 */
4178
Jing Huang5fbe25c2010-10-18 17:17:23 -07004179/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004180 * VPort SCN State Machine events
4181 */
4182enum port_scn_event {
4183 SCNSM_EVENT_PORT_ONLINE = 1,
4184 SCNSM_EVENT_PORT_OFFLINE = 2,
4185 SCNSM_EVENT_RSP_OK = 3,
4186 SCNSM_EVENT_RSP_ERROR = 4,
4187 SCNSM_EVENT_TIMEOUT = 5,
4188 SCNSM_EVENT_SCR_SENT = 6,
4189};
4190
4191static void bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn,
4192 enum port_scn_event event);
4193static void bfa_fcs_lport_scn_sm_sending_scr(
4194 struct bfa_fcs_lport_scn_s *scn,
4195 enum port_scn_event event);
4196static void bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn,
4197 enum port_scn_event event);
4198static void bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn,
4199 enum port_scn_event event);
4200static void bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn,
4201 enum port_scn_event event);
4202
Jing Huang5fbe25c2010-10-18 17:17:23 -07004203/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004204 * Starting state - awaiting link up.
4205 */
4206static void
4207bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn,
4208 enum port_scn_event event)
4209{
4210 switch (event) {
4211 case SCNSM_EVENT_PORT_ONLINE:
4212 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr);
4213 bfa_fcs_lport_scn_send_scr(scn, NULL);
4214 break;
4215
4216 case SCNSM_EVENT_PORT_OFFLINE:
4217 break;
4218
4219 default:
4220 bfa_sm_fault(scn->port->fcs, event);
4221 }
4222}
4223
4224static void
4225bfa_fcs_lport_scn_sm_sending_scr(struct bfa_fcs_lport_scn_s *scn,
4226 enum port_scn_event event)
4227{
4228 switch (event) {
4229 case SCNSM_EVENT_SCR_SENT:
4230 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr);
4231 break;
4232
4233 case SCNSM_EVENT_PORT_OFFLINE:
4234 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4235 bfa_fcxp_walloc_cancel(scn->port->fcs->bfa, &scn->fcxp_wqe);
4236 break;
4237
4238 default:
4239 bfa_sm_fault(scn->port->fcs, event);
4240 }
4241}
4242
4243static void
4244bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn,
4245 enum port_scn_event event)
4246{
4247 struct bfa_fcs_lport_s *port = scn->port;
4248
4249 switch (event) {
4250 case SCNSM_EVENT_RSP_OK:
4251 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_online);
4252 break;
4253
4254 case SCNSM_EVENT_RSP_ERROR:
4255 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr_retry);
4256 bfa_timer_start(port->fcs->bfa, &scn->timer,
4257 bfa_fcs_lport_scn_timeout, scn,
4258 BFA_FCS_RETRY_TIMEOUT);
4259 break;
4260
4261 case SCNSM_EVENT_PORT_OFFLINE:
4262 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4263 bfa_fcxp_discard(scn->fcxp);
4264 break;
4265
4266 default:
4267 bfa_sm_fault(port->fcs, event);
4268 }
4269}
4270
4271static void
4272bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn,
4273 enum port_scn_event event)
4274{
4275 switch (event) {
4276 case SCNSM_EVENT_TIMEOUT:
4277 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr);
4278 bfa_fcs_lport_scn_send_scr(scn, NULL);
4279 break;
4280
4281 case SCNSM_EVENT_PORT_OFFLINE:
4282 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4283 bfa_timer_stop(&scn->timer);
4284 break;
4285
4286 default:
4287 bfa_sm_fault(scn->port->fcs, event);
4288 }
4289}
4290
4291static void
4292bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn,
4293 enum port_scn_event event)
4294{
4295 switch (event) {
4296 case SCNSM_EVENT_PORT_OFFLINE:
4297 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4298 break;
4299
4300 default:
4301 bfa_sm_fault(scn->port->fcs, event);
4302 }
4303}
4304
4305
4306
Jing Huang5fbe25c2010-10-18 17:17:23 -07004307/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004308 * fcs_scn_private FCS SCN private functions
4309 */
4310
Jing Huang5fbe25c2010-10-18 17:17:23 -07004311/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004312 * This routine will be called to send a SCR command.
4313 */
4314static void
4315bfa_fcs_lport_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4316{
4317 struct bfa_fcs_lport_scn_s *scn = scn_cbarg;
4318 struct bfa_fcs_lport_s *port = scn->port;
4319 struct fchs_s fchs;
4320 int len;
4321 struct bfa_fcxp_s *fcxp;
4322
4323 bfa_trc(port->fcs, port->pid);
4324 bfa_trc(port->fcs, port->port_cfg.pwwn);
4325
4326 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
4327 if (!fcxp) {
4328 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &scn->fcxp_wqe,
4329 bfa_fcs_lport_scn_send_scr, scn);
4330 return;
4331 }
4332 scn->fcxp = fcxp;
4333
4334 /* Handle VU registrations for Base port only */
4335 if ((!port->vport) && bfa_ioc_get_fcmode(&port->fcs->bfa->ioc)) {
4336 len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
Maggie Zhangf7f738122010-12-09 19:08:43 -08004337 port->fabric->lps->brcd_switch,
4338 port->pid, 0);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004339 } else {
4340 len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4341 BFA_FALSE,
4342 port->pid, 0);
4343 }
4344
4345 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4346 FC_CLASS_3, len, &fchs,
4347 bfa_fcs_lport_scn_scr_response,
4348 (void *)scn, FC_MAX_PDUSZ, FC_ELS_TOV);
4349
4350 bfa_sm_send_event(scn, SCNSM_EVENT_SCR_SENT);
4351}
4352
4353static void
4354bfa_fcs_lport_scn_scr_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4355 void *cbarg, bfa_status_t req_status, u32 rsp_len,
4356 u32 resid_len, struct fchs_s *rsp_fchs)
4357{
4358 struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) cbarg;
4359 struct bfa_fcs_lport_s *port = scn->port;
4360 struct fc_els_cmd_s *els_cmd;
4361 struct fc_ls_rjt_s *ls_rjt;
4362
4363 bfa_trc(port->fcs, port->port_cfg.pwwn);
4364
4365 /*
4366 * Sanity Checks
4367 */
4368 if (req_status != BFA_STATUS_OK) {
4369 bfa_trc(port->fcs, req_status);
4370 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
4371 return;
4372 }
4373
4374 els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
4375
4376 switch (els_cmd->els_code) {
4377
4378 case FC_ELS_ACC:
4379 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_OK);
4380 break;
4381
4382 case FC_ELS_LS_RJT:
4383
4384 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
4385
4386 bfa_trc(port->fcs, ls_rjt->reason_code);
4387 bfa_trc(port->fcs, ls_rjt->reason_code_expl);
4388
4389 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
4390 break;
4391
4392 default:
4393 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
4394 }
4395}
4396
4397/*
4398 * Send a LS Accept
4399 */
4400static void
4401bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
4402 struct fchs_s *rx_fchs)
4403{
4404 struct fchs_s fchs;
4405 struct bfa_fcxp_s *fcxp;
4406 struct bfa_rport_s *bfa_rport = NULL;
4407 int len;
4408
4409 bfa_trc(port->fcs, rx_fchs->s_id);
4410
4411 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
4412 if (!fcxp)
4413 return;
4414
4415 len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4416 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
4417 rx_fchs->ox_id);
4418
4419 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
4420 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
4421 FC_MAX_PDUSZ, 0);
4422}
4423
Jing Huang5fbe25c2010-10-18 17:17:23 -07004424/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004425 * This routine will be called by bfa_timer on timer timeouts.
4426 *
4427 * param[in] vport - pointer to bfa_fcs_lport_t.
4428 * param[out] vport_status - pointer to return vport status in
4429 *
4430 * return
4431 * void
4432 *
4433 * Special Considerations:
4434 *
4435 * note
4436 */
4437static void
4438bfa_fcs_lport_scn_timeout(void *arg)
4439{
4440 struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) arg;
4441
4442 bfa_sm_send_event(scn, SCNSM_EVENT_TIMEOUT);
4443}
4444
4445
4446
Jing Huang5fbe25c2010-10-18 17:17:23 -07004447/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004448 * fcs_scn_public FCS state change notification public interfaces
4449 */
4450
4451/*
4452 * Functions called by port/fab
4453 */
4454void
4455bfa_fcs_lport_scn_init(struct bfa_fcs_lport_s *port)
4456{
4457 struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
4458
4459 scn->port = port;
4460 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4461}
4462
4463void
4464bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *port)
4465{
4466 struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
4467
4468 scn->port = port;
4469 bfa_sm_send_event(scn, SCNSM_EVENT_PORT_OFFLINE);
4470}
4471
4472void
4473bfa_fcs_lport_scn_online(struct bfa_fcs_lport_s *port)
4474{
4475 struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
4476
4477 scn->port = port;
4478 bfa_sm_send_event(scn, SCNSM_EVENT_PORT_ONLINE);
4479}
4480
4481static void
4482bfa_fcs_lport_scn_portid_rscn(struct bfa_fcs_lport_s *port, u32 rpid)
4483{
4484 struct bfa_fcs_rport_s *rport;
4485
4486 bfa_trc(port->fcs, rpid);
4487
Jing Huang5fbe25c2010-10-18 17:17:23 -07004488 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004489 * If this is an unknown device, then it just came online.
4490 * Otherwise let rport handle the RSCN event.
4491 */
4492 rport = bfa_fcs_lport_get_rport_by_pid(port, rpid);
4493 if (rport == NULL) {
4494 /*
4495 * If min cfg mode is enabled, we donot need to
4496 * discover any new rports.
4497 */
4498 if (!__fcs_min_cfg(port->fcs))
4499 rport = bfa_fcs_rport_create(port, rpid);
4500 } else
4501 bfa_fcs_rport_scn(rport);
4502}
4503
Jing Huang5fbe25c2010-10-18 17:17:23 -07004504/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004505 * rscn format based PID comparison
4506 */
4507#define __fc_pid_match(__c0, __c1, __fmt) \
4508 (((__fmt) == FC_RSCN_FORMAT_FABRIC) || \
4509 (((__fmt) == FC_RSCN_FORMAT_DOMAIN) && \
4510 ((__c0)[0] == (__c1)[0])) || \
4511 (((__fmt) == FC_RSCN_FORMAT_AREA) && \
4512 ((__c0)[0] == (__c1)[0]) && \
4513 ((__c0)[1] == (__c1)[1])))
4514
4515static void
4516bfa_fcs_lport_scn_multiport_rscn(struct bfa_fcs_lport_s *port,
4517 enum fc_rscn_format format,
4518 u32 rscn_pid)
4519{
4520 struct bfa_fcs_rport_s *rport;
4521 struct list_head *qe, *qe_next;
4522 u8 *c0, *c1;
4523
4524 bfa_trc(port->fcs, format);
4525 bfa_trc(port->fcs, rscn_pid);
4526
4527 c0 = (u8 *) &rscn_pid;
4528
4529 list_for_each_safe(qe, qe_next, &port->rport_q) {
4530 rport = (struct bfa_fcs_rport_s *) qe;
4531 c1 = (u8 *) &rport->pid;
4532 if (__fc_pid_match(c0, c1, format))
4533 bfa_fcs_rport_scn(rport);
4534 }
4535}
4536
4537
4538void
4539bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s *port,
4540 struct fchs_s *fchs, u32 len)
4541{
4542 struct fc_rscn_pl_s *rscn = (struct fc_rscn_pl_s *) (fchs + 1);
4543 int num_entries;
4544 u32 rscn_pid;
4545 bfa_boolean_t nsquery = BFA_FALSE, found;
4546 int i = 0, j;
4547
4548 num_entries =
Jing Huangba816ea2010-10-18 17:10:50 -07004549 (be16_to_cpu(rscn->payldlen) -
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004550 sizeof(u32)) / sizeof(rscn->event[0]);
4551
4552 bfa_trc(port->fcs, num_entries);
4553
4554 port->stats.num_rscn++;
4555
4556 bfa_fcs_lport_scn_send_ls_acc(port, fchs);
4557
4558 for (i = 0; i < num_entries; i++) {
4559 rscn_pid = rscn->event[i].portid;
4560
4561 bfa_trc(port->fcs, rscn->event[i].format);
4562 bfa_trc(port->fcs, rscn_pid);
4563
4564 /* check for duplicate entries in the list */
4565 found = BFA_FALSE;
4566 for (j = 0; j < i; j++) {
4567 if (rscn->event[j].portid == rscn_pid) {
4568 found = BFA_TRUE;
4569 break;
4570 }
4571 }
4572
4573 /* if found in down the list, pid has been already processed */
4574 if (found) {
4575 bfa_trc(port->fcs, rscn_pid);
4576 continue;
4577 }
4578
4579 switch (rscn->event[i].format) {
4580 case FC_RSCN_FORMAT_PORTID:
4581 if (rscn->event[i].qualifier == FC_QOS_RSCN_EVENT) {
4582 /*
4583 * Ignore this event.
4584 * f/w would have processed it
4585 */
4586 bfa_trc(port->fcs, rscn_pid);
4587 } else {
4588 port->stats.num_portid_rscn++;
4589 bfa_fcs_lport_scn_portid_rscn(port, rscn_pid);
4590 }
4591 break;
4592
4593 case FC_RSCN_FORMAT_FABRIC:
4594 if (rscn->event[i].qualifier ==
4595 FC_FABRIC_NAME_RSCN_EVENT) {
4596 bfa_fcs_lport_ms_fabric_rscn(port);
4597 break;
4598 }
4599 /* !!!!!!!!! Fall Through !!!!!!!!!!!!! */
4600
4601 case FC_RSCN_FORMAT_AREA:
4602 case FC_RSCN_FORMAT_DOMAIN:
4603 nsquery = BFA_TRUE;
4604 bfa_fcs_lport_scn_multiport_rscn(port,
4605 rscn->event[i].format,
4606 rscn_pid);
4607 break;
4608
4609
4610 default:
4611 bfa_assert(0);
4612 nsquery = BFA_TRUE;
4613 }
4614 }
4615
Jing Huang5fbe25c2010-10-18 17:17:23 -07004616 /*
4617 * If any of area, domain or fabric RSCN is received, do a fresh
4618 * discovery to find new devices.
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004619 */
4620 if (nsquery)
4621 bfa_fcs_lport_ns_query(port);
4622}
4623
Jing Huang5fbe25c2010-10-18 17:17:23 -07004624/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004625 * BFA FCS port
4626 */
Jing Huang5fbe25c2010-10-18 17:17:23 -07004627/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004628 * fcs_port_api BFA FCS port API
4629 */
4630struct bfa_fcs_lport_s *
4631bfa_fcs_get_base_port(struct bfa_fcs_s *fcs)
4632{
4633 return &fcs->fabric.bport;
4634}
4635
4636wwn_t
4637bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn, int index,
4638 int nrports, bfa_boolean_t bwwn)
4639{
4640 struct list_head *qh, *qe;
4641 struct bfa_fcs_rport_s *rport = NULL;
4642 int i;
4643 struct bfa_fcs_s *fcs;
4644
4645 if (port == NULL || nrports == 0)
4646 return (wwn_t) 0;
4647
4648 fcs = port->fcs;
4649 bfa_trc(fcs, (u32) nrports);
4650
4651 i = 0;
4652 qh = &port->rport_q;
4653 qe = bfa_q_first(qh);
4654
4655 while ((qe != qh) && (i < nrports)) {
4656 rport = (struct bfa_fcs_rport_s *) qe;
Maggie Zhangf16a1752010-12-09 19:12:32 -08004657 if (bfa_ntoh3b(rport->pid) > 0xFFF000) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004658 qe = bfa_q_next(qe);
4659 bfa_trc(fcs, (u32) rport->pwwn);
4660 bfa_trc(fcs, rport->pid);
4661 bfa_trc(fcs, i);
4662 continue;
4663 }
4664
4665 if (bwwn) {
4666 if (!memcmp(&wwn, &rport->pwwn, 8))
4667 break;
4668 } else {
4669 if (i == index)
4670 break;
4671 }
4672
4673 i++;
4674 qe = bfa_q_next(qe);
4675 }
4676
4677 bfa_trc(fcs, i);
4678 if (rport)
4679 return rport->pwwn;
4680 else
4681 return (wwn_t) 0;
4682}
4683
4684void
4685bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port,
4686 wwn_t rport_wwns[], int *nrports)
4687{
4688 struct list_head *qh, *qe;
4689 struct bfa_fcs_rport_s *rport = NULL;
4690 int i;
4691 struct bfa_fcs_s *fcs;
4692
4693 if (port == NULL || rport_wwns == NULL || *nrports == 0)
4694 return;
4695
4696 fcs = port->fcs;
4697 bfa_trc(fcs, (u32) *nrports);
4698
4699 i = 0;
4700 qh = &port->rport_q;
4701 qe = bfa_q_first(qh);
4702
4703 while ((qe != qh) && (i < *nrports)) {
4704 rport = (struct bfa_fcs_rport_s *) qe;
Maggie Zhangf16a1752010-12-09 19:12:32 -08004705 if (bfa_ntoh3b(rport->pid) > 0xFFF000) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004706 qe = bfa_q_next(qe);
4707 bfa_trc(fcs, (u32) rport->pwwn);
4708 bfa_trc(fcs, rport->pid);
4709 bfa_trc(fcs, i);
4710 continue;
4711 }
4712
4713 rport_wwns[i] = rport->pwwn;
4714
4715 i++;
4716 qe = bfa_q_next(qe);
4717 }
4718
4719 bfa_trc(fcs, i);
4720 *nrports = i;
4721}
4722
4723/*
4724 * Iterate's through all the rport's in the given port to
4725 * determine the maximum operating speed.
4726 *
4727 * !!!! To be used in TRL Functionality only !!!!
4728 */
4729bfa_port_speed_t
4730bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port)
4731{
4732 struct list_head *qh, *qe;
4733 struct bfa_fcs_rport_s *rport = NULL;
4734 struct bfa_fcs_s *fcs;
4735 bfa_port_speed_t max_speed = 0;
4736 struct bfa_port_attr_s port_attr;
4737 bfa_port_speed_t port_speed, rport_speed;
4738 bfa_boolean_t trl_enabled = bfa_fcport_is_ratelim(port->fcs->bfa);
4739
4740
4741 if (port == NULL)
4742 return 0;
4743
4744 fcs = port->fcs;
4745
4746 /* Get Physical port's current speed */
4747 bfa_fcport_get_attr(port->fcs->bfa, &port_attr);
4748 port_speed = port_attr.speed;
4749 bfa_trc(fcs, port_speed);
4750
4751 qh = &port->rport_q;
4752 qe = bfa_q_first(qh);
4753
4754 while (qe != qh) {
4755 rport = (struct bfa_fcs_rport_s *) qe;
Maggie Zhangf16a1752010-12-09 19:12:32 -08004756 if ((bfa_ntoh3b(rport->pid) > 0xFFF000) ||
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004757 (bfa_fcs_rport_get_state(rport) ==
4758 BFA_RPORT_OFFLINE)) {
4759 qe = bfa_q_next(qe);
4760 continue;
4761 }
4762
4763 rport_speed = rport->rpf.rpsc_speed;
4764 if ((trl_enabled) && (rport_speed ==
4765 BFA_PORT_SPEED_UNKNOWN)) {
4766 /* Use default ratelim speed setting */
4767 rport_speed =
4768 bfa_fcport_get_ratelim_speed(port->fcs->bfa);
4769 }
4770
4771 if ((rport_speed == BFA_PORT_SPEED_8GBPS) ||
4772 (rport_speed > port_speed)) {
4773 max_speed = rport_speed;
4774 break;
4775 } else if (rport_speed > max_speed) {
4776 max_speed = rport_speed;
4777 }
4778
4779 qe = bfa_q_next(qe);
4780 }
4781
4782 bfa_trc(fcs, max_speed);
4783 return max_speed;
4784}
4785
4786struct bfa_fcs_lport_s *
4787bfa_fcs_lookup_port(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t lpwwn)
4788{
4789 struct bfa_fcs_vport_s *vport;
4790 bfa_fcs_vf_t *vf;
4791
4792 bfa_assert(fcs != NULL);
4793
4794 vf = bfa_fcs_vf_lookup(fcs, vf_id);
4795 if (vf == NULL) {
4796 bfa_trc(fcs, vf_id);
4797 return NULL;
4798 }
4799
4800 if (!lpwwn || (vf->bport.port_cfg.pwwn == lpwwn))
4801 return &vf->bport;
4802
4803 vport = bfa_fcs_fabric_vport_lookup(vf, lpwwn);
4804 if (vport)
4805 return &vport->lport;
4806
4807 return NULL;
4808}
4809
4810/*
4811 * API corresponding to NPIV_VPORT_GETINFO.
4812 */
4813void
4814bfa_fcs_lport_get_info(struct bfa_fcs_lport_s *port,
4815 struct bfa_lport_info_s *port_info)
4816{
4817
4818 bfa_trc(port->fcs, port->fabric->fabric_name);
4819
4820 if (port->vport == NULL) {
4821 /*
4822 * This is a Physical port
4823 */
4824 port_info->port_type = BFA_LPORT_TYPE_PHYSICAL;
4825
4826 /*
4827 * @todo : need to fix the state & reason
4828 */
4829 port_info->port_state = 0;
4830 port_info->offline_reason = 0;
4831
4832 port_info->port_wwn = bfa_fcs_lport_get_pwwn(port);
4833 port_info->node_wwn = bfa_fcs_lport_get_nwwn(port);
4834
4835 port_info->max_vports_supp =
4836 bfa_lps_get_max_vport(port->fcs->bfa);
4837 port_info->num_vports_inuse =
Maggie Zhangf7f738122010-12-09 19:08:43 -08004838 port->fabric->num_vports;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004839 port_info->max_rports_supp = BFA_FCS_MAX_RPORTS_SUPP;
4840 port_info->num_rports_inuse = port->num_rports;
4841 } else {
4842 /*
4843 * This is a virtual port
4844 */
4845 port_info->port_type = BFA_LPORT_TYPE_VIRTUAL;
4846
4847 /*
4848 * @todo : need to fix the state & reason
4849 */
4850 port_info->port_state = 0;
4851 port_info->offline_reason = 0;
4852
4853 port_info->port_wwn = bfa_fcs_lport_get_pwwn(port);
4854 port_info->node_wwn = bfa_fcs_lport_get_nwwn(port);
4855 }
4856}
4857
4858void
4859bfa_fcs_lport_get_stats(struct bfa_fcs_lport_s *fcs_port,
4860 struct bfa_lport_stats_s *port_stats)
4861{
4862 *port_stats = fcs_port->stats;
4863}
4864
4865void
4866bfa_fcs_lport_clear_stats(struct bfa_fcs_lport_s *fcs_port)
4867{
Jing Huang6a18b162010-10-18 17:08:54 -07004868 memset(&fcs_port->stats, 0, sizeof(struct bfa_lport_stats_s));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004869}
4870
Jing Huang5fbe25c2010-10-18 17:17:23 -07004871/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004872 * FCS virtual port state machine
4873 */
4874
4875#define __vport_fcs(__vp) ((__vp)->lport.fcs)
4876#define __vport_pwwn(__vp) ((__vp)->lport.port_cfg.pwwn)
4877#define __vport_nwwn(__vp) ((__vp)->lport.port_cfg.nwwn)
4878#define __vport_bfa(__vp) ((__vp)->lport.fcs->bfa)
4879#define __vport_fcid(__vp) ((__vp)->lport.pid)
4880#define __vport_fabric(__vp) ((__vp)->lport.fabric)
4881#define __vport_vfid(__vp) ((__vp)->lport.fabric->vf_id)
4882
4883#define BFA_FCS_VPORT_MAX_RETRIES 5
4884/*
4885 * Forward declarations
4886 */
4887static void bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport);
4888static void bfa_fcs_vport_timeout(void *vport_arg);
4889static void bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport);
4890static void bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport);
4891
Jing Huang5fbe25c2010-10-18 17:17:23 -07004892/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004893 * fcs_vport_sm FCS virtual port state machine
4894 */
4895
Jing Huang5fbe25c2010-10-18 17:17:23 -07004896/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004897 * VPort State Machine events
4898 */
4899enum bfa_fcs_vport_event {
4900 BFA_FCS_VPORT_SM_CREATE = 1, /* vport create event */
4901 BFA_FCS_VPORT_SM_DELETE = 2, /* vport delete event */
4902 BFA_FCS_VPORT_SM_START = 3, /* vport start request */
4903 BFA_FCS_VPORT_SM_STOP = 4, /* stop: unsupported */
4904 BFA_FCS_VPORT_SM_ONLINE = 5, /* fabric online */
4905 BFA_FCS_VPORT_SM_OFFLINE = 6, /* fabric offline event */
4906 BFA_FCS_VPORT_SM_FRMSENT = 7, /* fdisc/logo sent events */
4907 BFA_FCS_VPORT_SM_RSP_OK = 8, /* good response */
4908 BFA_FCS_VPORT_SM_RSP_ERROR = 9, /* error/bad response */
4909 BFA_FCS_VPORT_SM_TIMEOUT = 10, /* delay timer event */
4910 BFA_FCS_VPORT_SM_DELCOMP = 11, /* lport delete completion */
4911 BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12, /* Dup wnn error*/
4912 BFA_FCS_VPORT_SM_RSP_FAILED = 13, /* non-retryable failure */
4913};
4914
4915static void bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
4916 enum bfa_fcs_vport_event event);
4917static void bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
4918 enum bfa_fcs_vport_event event);
4919static void bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
4920 enum bfa_fcs_vport_event event);
4921static void bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
4922 enum bfa_fcs_vport_event event);
4923static void bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
4924 enum bfa_fcs_vport_event event);
4925static void bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
4926 enum bfa_fcs_vport_event event);
4927static void bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
4928 enum bfa_fcs_vport_event event);
4929static void bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
4930 enum bfa_fcs_vport_event event);
4931static void bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
4932 enum bfa_fcs_vport_event event);
4933static void bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
4934 enum bfa_fcs_vport_event event);
4935
4936static struct bfa_sm_table_s vport_sm_table[] = {
4937 {BFA_SM(bfa_fcs_vport_sm_uninit), BFA_FCS_VPORT_UNINIT},
4938 {BFA_SM(bfa_fcs_vport_sm_created), BFA_FCS_VPORT_CREATED},
4939 {BFA_SM(bfa_fcs_vport_sm_offline), BFA_FCS_VPORT_OFFLINE},
4940 {BFA_SM(bfa_fcs_vport_sm_fdisc), BFA_FCS_VPORT_FDISC},
4941 {BFA_SM(bfa_fcs_vport_sm_fdisc_retry), BFA_FCS_VPORT_FDISC_RETRY},
4942 {BFA_SM(bfa_fcs_vport_sm_online), BFA_FCS_VPORT_ONLINE},
4943 {BFA_SM(bfa_fcs_vport_sm_deleting), BFA_FCS_VPORT_DELETING},
4944 {BFA_SM(bfa_fcs_vport_sm_cleanup), BFA_FCS_VPORT_CLEANUP},
4945 {BFA_SM(bfa_fcs_vport_sm_logo), BFA_FCS_VPORT_LOGO},
4946 {BFA_SM(bfa_fcs_vport_sm_error), BFA_FCS_VPORT_ERROR}
4947};
4948
Jing Huang5fbe25c2010-10-18 17:17:23 -07004949/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004950 * Beginning state.
4951 */
4952static void
4953bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
4954 enum bfa_fcs_vport_event event)
4955{
4956 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
4957 bfa_trc(__vport_fcs(vport), event);
4958
4959 switch (event) {
4960 case BFA_FCS_VPORT_SM_CREATE:
4961 bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
4962 bfa_fcs_fabric_addvport(__vport_fabric(vport), vport);
4963 break;
4964
4965 default:
4966 bfa_sm_fault(__vport_fcs(vport), event);
4967 }
4968}
4969
Jing Huang5fbe25c2010-10-18 17:17:23 -07004970/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004971 * Created state - a start event is required to start up the state machine.
4972 */
4973static void
4974bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
4975 enum bfa_fcs_vport_event event)
4976{
4977 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
4978 bfa_trc(__vport_fcs(vport), event);
4979
4980 switch (event) {
4981 case BFA_FCS_VPORT_SM_START:
Maggie Zhangf7f738122010-12-09 19:08:43 -08004982 if (bfa_sm_cmp_state(__vport_fabric(vport),
4983 bfa_fcs_fabric_sm_online)
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004984 && bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) {
4985 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
4986 bfa_fcs_vport_do_fdisc(vport);
4987 } else {
Jing Huang5fbe25c2010-10-18 17:17:23 -07004988 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004989 * Fabric is offline or not NPIV capable, stay in
4990 * offline state.
4991 */
4992 vport->vport_stats.fab_no_npiv++;
4993 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
4994 }
4995 break;
4996
4997 case BFA_FCS_VPORT_SM_DELETE:
4998 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
4999 bfa_fcs_lport_delete(&vport->lport);
5000 break;
5001
5002 case BFA_FCS_VPORT_SM_ONLINE:
5003 case BFA_FCS_VPORT_SM_OFFLINE:
Jing Huang5fbe25c2010-10-18 17:17:23 -07005004 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005005 * Ignore ONLINE/OFFLINE events from fabric
5006 * till vport is started.
5007 */
5008 break;
5009
5010 default:
5011 bfa_sm_fault(__vport_fcs(vport), event);
5012 }
5013}
5014
Jing Huang5fbe25c2010-10-18 17:17:23 -07005015/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005016 * Offline state - awaiting ONLINE event from fabric SM.
5017 */
5018static void
5019bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
5020 enum bfa_fcs_vport_event event)
5021{
5022 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5023 bfa_trc(__vport_fcs(vport), event);
5024
5025 switch (event) {
5026 case BFA_FCS_VPORT_SM_DELETE:
5027 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5028 bfa_fcs_lport_delete(&vport->lport);
5029 break;
5030
5031 case BFA_FCS_VPORT_SM_ONLINE:
5032 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
5033 vport->fdisc_retries = 0;
5034 bfa_fcs_vport_do_fdisc(vport);
5035 break;
5036
5037 case BFA_FCS_VPORT_SM_OFFLINE:
5038 /*
5039 * This can happen if the vport couldn't be initialzied
5040 * due the fact that the npiv was not enabled on the switch.
5041 * In that case we will put the vport in offline state.
5042 * However, the link can go down and cause the this event to
5043 * be sent when we are already offline. Ignore it.
5044 */
5045 break;
5046
5047 default:
5048 bfa_sm_fault(__vport_fcs(vport), event);
5049 }
5050}
5051
5052
Jing Huang5fbe25c2010-10-18 17:17:23 -07005053/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005054 * FDISC is sent and awaiting reply from fabric.
5055 */
5056static void
5057bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
5058 enum bfa_fcs_vport_event event)
5059{
5060 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5061 bfa_trc(__vport_fcs(vport), event);
5062
5063 switch (event) {
5064 case BFA_FCS_VPORT_SM_DELETE:
5065 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
Maggie Zhangf7f738122010-12-09 19:08:43 -08005066 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005067 bfa_fcs_lport_delete(&vport->lport);
5068 break;
5069
5070 case BFA_FCS_VPORT_SM_OFFLINE:
5071 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
Maggie Zhangf7f738122010-12-09 19:08:43 -08005072 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005073 break;
5074
5075 case BFA_FCS_VPORT_SM_RSP_OK:
5076 bfa_sm_set_state(vport, bfa_fcs_vport_sm_online);
5077 bfa_fcs_lport_online(&vport->lport);
5078 break;
5079
5080 case BFA_FCS_VPORT_SM_RSP_ERROR:
5081 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_retry);
5082 bfa_timer_start(__vport_bfa(vport), &vport->timer,
5083 bfa_fcs_vport_timeout, vport,
5084 BFA_FCS_RETRY_TIMEOUT);
5085 break;
5086
5087 case BFA_FCS_VPORT_SM_RSP_FAILED:
5088 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5089 break;
5090
5091 case BFA_FCS_VPORT_SM_RSP_DUP_WWN:
5092 bfa_sm_set_state(vport, bfa_fcs_vport_sm_error);
5093 break;
5094
5095 default:
5096 bfa_sm_fault(__vport_fcs(vport), event);
5097 }
5098}
5099
Jing Huang5fbe25c2010-10-18 17:17:23 -07005100/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005101 * FDISC attempt failed - a timer is active to retry FDISC.
5102 */
5103static void
5104bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
5105 enum bfa_fcs_vport_event event)
5106{
5107 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5108 bfa_trc(__vport_fcs(vport), event);
5109
5110 switch (event) {
5111 case BFA_FCS_VPORT_SM_DELETE:
5112 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5113 bfa_timer_stop(&vport->timer);
5114 bfa_fcs_lport_delete(&vport->lport);
5115 break;
5116
5117 case BFA_FCS_VPORT_SM_OFFLINE:
5118 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5119 bfa_timer_stop(&vport->timer);
5120 break;
5121
5122 case BFA_FCS_VPORT_SM_TIMEOUT:
5123 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
5124 vport->vport_stats.fdisc_retries++;
5125 vport->fdisc_retries++;
5126 bfa_fcs_vport_do_fdisc(vport);
5127 break;
5128
5129 default:
5130 bfa_sm_fault(__vport_fcs(vport), event);
5131 }
5132}
5133
Jing Huang5fbe25c2010-10-18 17:17:23 -07005134/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005135 * Vport is online (FDISC is complete).
5136 */
5137static void
5138bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
5139 enum bfa_fcs_vport_event event)
5140{
5141 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5142 bfa_trc(__vport_fcs(vport), event);
5143
5144 switch (event) {
5145 case BFA_FCS_VPORT_SM_DELETE:
5146 bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting);
5147 bfa_fcs_lport_delete(&vport->lport);
5148 break;
5149
5150 case BFA_FCS_VPORT_SM_OFFLINE:
5151 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
Maggie Zhangf7f738122010-12-09 19:08:43 -08005152 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005153 bfa_fcs_lport_offline(&vport->lport);
5154 break;
5155
5156 default:
5157 bfa_sm_fault(__vport_fcs(vport), event);
5158 }
5159}
5160
Jing Huang5fbe25c2010-10-18 17:17:23 -07005161/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005162 * Vport is being deleted - awaiting lport delete completion to send
5163 * LOGO to fabric.
5164 */
5165static void
5166bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
5167 enum bfa_fcs_vport_event event)
5168{
5169 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5170 bfa_trc(__vport_fcs(vport), event);
5171
5172 switch (event) {
5173 case BFA_FCS_VPORT_SM_DELETE:
5174 break;
5175
5176 case BFA_FCS_VPORT_SM_DELCOMP:
5177 bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo);
5178 bfa_fcs_vport_do_logo(vport);
5179 break;
5180
5181 case BFA_FCS_VPORT_SM_OFFLINE:
5182 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5183 break;
5184
5185 default:
5186 bfa_sm_fault(__vport_fcs(vport), event);
5187 }
5188}
5189
Jing Huang5fbe25c2010-10-18 17:17:23 -07005190/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005191 * Error State.
5192 * This state will be set when the Vport Creation fails due
5193 * to errors like Dup WWN. In this state only operation allowed
5194 * is a Vport Delete.
5195 */
5196static void
5197bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
5198 enum bfa_fcs_vport_event event)
5199{
5200 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5201 bfa_trc(__vport_fcs(vport), event);
5202
5203 switch (event) {
5204 case BFA_FCS_VPORT_SM_DELETE:
5205 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5206 bfa_fcs_lport_delete(&vport->lport);
5207 break;
5208
5209 default:
5210 bfa_trc(__vport_fcs(vport), event);
5211 }
5212}
5213
Jing Huang5fbe25c2010-10-18 17:17:23 -07005214/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005215 * Lport cleanup is in progress since vport is being deleted. Fabric is
5216 * offline, so no LOGO is needed to complete vport deletion.
5217 */
5218static void
5219bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
5220 enum bfa_fcs_vport_event event)
5221{
5222 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5223 bfa_trc(__vport_fcs(vport), event);
5224
5225 switch (event) {
5226 case BFA_FCS_VPORT_SM_DELCOMP:
5227 bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
5228 bfa_fcs_vport_free(vport);
5229 break;
5230
5231 case BFA_FCS_VPORT_SM_DELETE:
5232 break;
5233
5234 default:
5235 bfa_sm_fault(__vport_fcs(vport), event);
5236 }
5237}
5238
Jing Huang5fbe25c2010-10-18 17:17:23 -07005239/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005240 * LOGO is sent to fabric. Vport delete is in progress. Lport delete cleanup
5241 * is done.
5242 */
5243static void
5244bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
5245 enum bfa_fcs_vport_event event)
5246{
5247 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5248 bfa_trc(__vport_fcs(vport), event);
5249
5250 switch (event) {
5251 case BFA_FCS_VPORT_SM_OFFLINE:
Maggie Zhangf7f738122010-12-09 19:08:43 -08005252 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005253 /*
5254 * !!! fall through !!!
5255 */
5256
5257 case BFA_FCS_VPORT_SM_RSP_OK:
5258 case BFA_FCS_VPORT_SM_RSP_ERROR:
5259 bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
5260 bfa_fcs_vport_free(vport);
5261 break;
5262
5263 case BFA_FCS_VPORT_SM_DELETE:
5264 break;
5265
5266 default:
5267 bfa_sm_fault(__vport_fcs(vport), event);
5268 }
5269}
5270
5271
5272
Jing Huang5fbe25c2010-10-18 17:17:23 -07005273/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005274 * fcs_vport_private FCS virtual port private functions
5275 */
Jing Huang5fbe25c2010-10-18 17:17:23 -07005276/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005277 * This routine will be called to send a FDISC command.
5278 */
5279static void
5280bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport)
5281{
5282 bfa_lps_fdisc(vport->lps, vport,
5283 bfa_fcport_get_maxfrsize(__vport_bfa(vport)),
5284 __vport_pwwn(vport), __vport_nwwn(vport));
5285 vport->vport_stats.fdisc_sent++;
5286}
5287
5288static void
5289bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport)
5290{
Maggie Zhangf7f738122010-12-09 19:08:43 -08005291 u8 lsrjt_rsn = vport->lps->lsrjt_rsn;
5292 u8 lsrjt_expl = vport->lps->lsrjt_expl;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005293
5294 bfa_trc(__vport_fcs(vport), lsrjt_rsn);
5295 bfa_trc(__vport_fcs(vport), lsrjt_expl);
5296
5297 /* For certain reason codes, we don't want to retry. */
Maggie Zhangf7f738122010-12-09 19:08:43 -08005298 switch (vport->lps->lsrjt_expl) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005299 case FC_LS_RJT_EXP_INV_PORT_NAME: /* by brocade */
5300 case FC_LS_RJT_EXP_INVALID_NPORT_ID: /* by Cisco */
5301 if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
5302 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5303 else
5304 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_DUP_WWN);
5305 break;
5306
5307 case FC_LS_RJT_EXP_INSUFF_RES:
5308 /*
5309 * This means max logins per port/switch setting on the
5310 * switch was exceeded.
5311 */
5312 if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
5313 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5314 else
5315 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED);
5316 break;
5317
5318 default:
5319 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5320 }
5321}
5322
Jing Huang5fbe25c2010-10-18 17:17:23 -07005323/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005324 * Called to send a logout to the fabric. Used when a V-Port is
5325 * deleted/stopped.
5326 */
5327static void
5328bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport)
5329{
5330 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5331
5332 vport->vport_stats.logo_sent++;
5333 bfa_lps_fdisclogo(vport->lps);
5334}
5335
5336
Jing Huang5fbe25c2010-10-18 17:17:23 -07005337/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005338 * This routine will be called by bfa_timer on timer timeouts.
5339 *
5340 * param[in] vport - pointer to bfa_fcs_vport_t.
5341 * param[out] vport_status - pointer to return vport status in
5342 *
5343 * return
5344 * void
5345 *
5346 * Special Considerations:
5347 *
5348 * note
5349 */
5350static void
5351bfa_fcs_vport_timeout(void *vport_arg)
5352{
5353 struct bfa_fcs_vport_s *vport = (struct bfa_fcs_vport_s *) vport_arg;
5354
5355 vport->vport_stats.fdisc_timeouts++;
5356 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_TIMEOUT);
5357}
5358
5359static void
5360bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport)
5361{
5362 struct bfad_vport_s *vport_drv =
5363 (struct bfad_vport_s *)vport->vport_drv;
5364
5365 bfa_fcs_fabric_delvport(__vport_fabric(vport), vport);
5366
5367 if (vport_drv->comp_del)
5368 complete(vport_drv->comp_del);
5369
5370 bfa_lps_delete(vport->lps);
5371}
5372
5373
5374
Jing Huang5fbe25c2010-10-18 17:17:23 -07005375/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005376 * fcs_vport_public FCS virtual port public interfaces
5377 */
5378
Jing Huang5fbe25c2010-10-18 17:17:23 -07005379/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005380 * Online notification from fabric SM.
5381 */
5382void
5383bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport)
5384{
5385 vport->vport_stats.fab_online++;
5386 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
5387}
5388
Jing Huang5fbe25c2010-10-18 17:17:23 -07005389/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005390 * Offline notification from fabric SM.
5391 */
5392void
5393bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport)
5394{
5395 vport->vport_stats.fab_offline++;
5396 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
5397}
5398
Jing Huang5fbe25c2010-10-18 17:17:23 -07005399/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005400 * Cleanup notification from fabric SM on link timer expiry.
5401 */
5402void
5403bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport)
5404{
5405 vport->vport_stats.fab_cleanup++;
5406}
Jing Huang5fbe25c2010-10-18 17:17:23 -07005407/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005408 * delete notification from fabric SM. To be invoked from within FCS.
5409 */
5410void
5411bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport)
5412{
5413 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
5414}
5415
Jing Huang5fbe25c2010-10-18 17:17:23 -07005416/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005417 * Delete completion callback from associated lport
5418 */
5419void
5420bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport)
5421{
5422 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELCOMP);
5423}
5424
5425
5426
Jing Huang5fbe25c2010-10-18 17:17:23 -07005427/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005428 * fcs_vport_api Virtual port API
5429 */
5430
Jing Huang5fbe25c2010-10-18 17:17:23 -07005431/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005432 * Use this function to instantiate a new FCS vport object. This
5433 * function will not trigger any HW initialization process (which will be
5434 * done in vport_start() call)
5435 *
5436 * param[in] vport - pointer to bfa_fcs_vport_t. This space
5437 * needs to be allocated by the driver.
5438 * param[in] fcs - FCS instance
5439 * param[in] vport_cfg - vport configuration
5440 * param[in] vf_id - VF_ID if vport is created within a VF.
5441 * FC_VF_ID_NULL to specify base fabric.
5442 * param[in] vport_drv - Opaque handle back to the driver's vport
5443 * structure
5444 *
5445 * retval BFA_STATUS_OK - on success.
5446 * retval BFA_STATUS_FAILED - on failure.
5447 */
5448bfa_status_t
5449bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
5450 u16 vf_id, struct bfa_lport_cfg_s *vport_cfg,
5451 struct bfad_vport_s *vport_drv)
5452{
5453 if (vport_cfg->pwwn == 0)
5454 return BFA_STATUS_INVALID_WWN;
5455
5456 if (bfa_fcs_lport_get_pwwn(&fcs->fabric.bport) == vport_cfg->pwwn)
5457 return BFA_STATUS_VPORT_WWN_BP;
5458
5459 if (bfa_fcs_vport_lookup(fcs, vf_id, vport_cfg->pwwn) != NULL)
5460 return BFA_STATUS_VPORT_EXISTS;
5461
Maggie Zhangf7f738122010-12-09 19:08:43 -08005462 if (fcs->fabric.num_vports ==
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005463 bfa_lps_get_max_vport(fcs->bfa))
5464 return BFA_STATUS_VPORT_MAX;
5465
5466 vport->lps = bfa_lps_alloc(fcs->bfa);
5467 if (!vport->lps)
5468 return BFA_STATUS_VPORT_MAX;
5469
5470 vport->vport_drv = vport_drv;
5471 vport_cfg->preboot_vp = BFA_FALSE;
5472
5473 bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
5474 bfa_fcs_lport_attach(&vport->lport, fcs, vf_id, vport);
5475 bfa_fcs_lport_init(&vport->lport, vport_cfg);
5476 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_CREATE);
5477
5478 return BFA_STATUS_OK;
5479}
5480
Jing Huang5fbe25c2010-10-18 17:17:23 -07005481/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005482 * Use this function to instantiate a new FCS PBC vport object. This
5483 * function will not trigger any HW initialization process (which will be
5484 * done in vport_start() call)
5485 *
5486 * param[in] vport - pointer to bfa_fcs_vport_t. This space
5487 * needs to be allocated by the driver.
5488 * param[in] fcs - FCS instance
5489 * param[in] vport_cfg - vport configuration
5490 * param[in] vf_id - VF_ID if vport is created within a VF.
5491 * FC_VF_ID_NULL to specify base fabric.
5492 * param[in] vport_drv - Opaque handle back to the driver's vport
5493 * structure
5494 *
5495 * retval BFA_STATUS_OK - on success.
5496 * retval BFA_STATUS_FAILED - on failure.
5497 */
5498bfa_status_t
5499bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
5500 u16 vf_id, struct bfa_lport_cfg_s *vport_cfg,
5501 struct bfad_vport_s *vport_drv)
5502{
5503 bfa_status_t rc;
5504
5505 rc = bfa_fcs_vport_create(vport, fcs, vf_id, vport_cfg, vport_drv);
5506 vport->lport.port_cfg.preboot_vp = BFA_TRUE;
5507
5508 return rc;
5509}
5510
Jing Huang5fbe25c2010-10-18 17:17:23 -07005511/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005512 * Use this function to findout if this is a pbc vport or not.
5513 *
5514 * @param[in] vport - pointer to bfa_fcs_vport_t.
5515 *
5516 * @returns None
5517 */
5518bfa_boolean_t
5519bfa_fcs_is_pbc_vport(struct bfa_fcs_vport_s *vport)
5520{
5521
5522 if (vport && (vport->lport.port_cfg.preboot_vp == BFA_TRUE))
5523 return BFA_TRUE;
5524 else
5525 return BFA_FALSE;
5526
5527}
5528
Jing Huang5fbe25c2010-10-18 17:17:23 -07005529/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005530 * Use this function initialize the vport.
5531 *
5532 * @param[in] vport - pointer to bfa_fcs_vport_t.
5533 *
5534 * @returns None
5535 */
5536bfa_status_t
5537bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport)
5538{
5539 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_START);
5540
5541 return BFA_STATUS_OK;
5542}
5543
Jing Huang5fbe25c2010-10-18 17:17:23 -07005544/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005545 * Use this function quiese the vport object. This function will return
5546 * immediately, when the vport is actually stopped, the
5547 * bfa_drv_vport_stop_cb() will be called.
5548 *
5549 * param[in] vport - pointer to bfa_fcs_vport_t.
5550 *
5551 * return None
5552 */
5553bfa_status_t
5554bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport)
5555{
5556 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP);
5557
5558 return BFA_STATUS_OK;
5559}
5560
Jing Huang5fbe25c2010-10-18 17:17:23 -07005561/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005562 * Use this function to delete a vport object. Fabric object should
5563 * be stopped before this function call.
5564 *
5565 * !!!!!!! Donot invoke this from within FCS !!!!!!!
5566 *
5567 * param[in] vport - pointer to bfa_fcs_vport_t.
5568 *
5569 * return None
5570 */
5571bfa_status_t
5572bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport)
5573{
5574
5575 if (vport->lport.port_cfg.preboot_vp)
5576 return BFA_STATUS_PBC;
5577
5578 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
5579
5580 return BFA_STATUS_OK;
5581}
5582
Jing Huang5fbe25c2010-10-18 17:17:23 -07005583/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005584 * Use this function to get vport's current status info.
5585 *
5586 * param[in] vport pointer to bfa_fcs_vport_t.
5587 * param[out] attr pointer to return vport attributes
5588 *
5589 * return None
5590 */
5591void
5592bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport,
5593 struct bfa_vport_attr_s *attr)
5594{
5595 if (vport == NULL || attr == NULL)
5596 return;
5597
Jing Huang6a18b162010-10-18 17:08:54 -07005598 memset(attr, 0, sizeof(struct bfa_vport_attr_s));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005599
5600 bfa_fcs_lport_get_attr(&vport->lport, &attr->port_attr);
5601 attr->vport_state = bfa_sm_to_state(vport_sm_table, vport->sm);
5602}
5603
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005604
Jing Huang5fbe25c2010-10-18 17:17:23 -07005605/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005606 * Lookup a virtual port. Excludes base port from lookup.
5607 */
5608struct bfa_fcs_vport_s *
5609bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t vpwwn)
5610{
5611 struct bfa_fcs_vport_s *vport;
5612 struct bfa_fcs_fabric_s *fabric;
5613
5614 bfa_trc(fcs, vf_id);
5615 bfa_trc(fcs, vpwwn);
5616
5617 fabric = bfa_fcs_vf_lookup(fcs, vf_id);
5618 if (!fabric) {
5619 bfa_trc(fcs, vf_id);
5620 return NULL;
5621 }
5622
5623 vport = bfa_fcs_fabric_vport_lookup(fabric, vpwwn);
5624 return vport;
5625}
5626
Jing Huang5fbe25c2010-10-18 17:17:23 -07005627/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005628 * FDISC Response
5629 */
5630void
5631bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status)
5632{
5633 struct bfa_fcs_vport_s *vport = uarg;
5634
5635 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5636 bfa_trc(__vport_fcs(vport), status);
5637
5638 switch (status) {
5639 case BFA_STATUS_OK:
5640 /*
5641 * Initialiaze the V-Port fields
5642 */
Maggie Zhangf7f738122010-12-09 19:08:43 -08005643 __vport_fcid(vport) = vport->lps->lp_pid;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005644 vport->vport_stats.fdisc_accepts++;
5645 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
5646 break;
5647
5648 case BFA_STATUS_INVALID_MAC:
5649 /* Only for CNA */
5650 vport->vport_stats.fdisc_acc_bad++;
5651 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5652
5653 break;
5654
5655 case BFA_STATUS_EPROTOCOL:
Maggie Zhangf7f738122010-12-09 19:08:43 -08005656 switch (vport->lps->ext_status) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005657 case BFA_EPROTO_BAD_ACCEPT:
5658 vport->vport_stats.fdisc_acc_bad++;
5659 break;
5660
5661 case BFA_EPROTO_UNKNOWN_RSP:
5662 vport->vport_stats.fdisc_unknown_rsp++;
5663 break;
5664
5665 default:
5666 break;
5667 }
5668
5669 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5670 break;
5671
5672 case BFA_STATUS_FABRIC_RJT:
5673 vport->vport_stats.fdisc_rejects++;
5674 bfa_fcs_vport_fdisc_rejected(vport);
5675 break;
5676
5677 default:
5678 vport->vport_stats.fdisc_rsp_err++;
5679 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5680 }
5681}
5682
Jing Huang5fbe25c2010-10-18 17:17:23 -07005683/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005684 * LOGO response
5685 */
5686void
5687bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg)
5688{
5689 struct bfa_fcs_vport_s *vport = uarg;
5690 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
5691}
5692
Jing Huang5fbe25c2010-10-18 17:17:23 -07005693/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005694 * Received clear virtual link
5695 */
5696void
5697bfa_cb_lps_cvl_event(void *bfad, void *uarg)
5698{
5699 struct bfa_fcs_vport_s *vport = uarg;
5700
5701 /* Send an Offline followed by an ONLINE */
5702 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
5703 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
5704}