blob: 1d6be8c144734a085bb7c90f7a5b5703f876557f [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 Zhangf7f73812010-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 Zhangf7f73812010-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;
Krishna Gudipatib7044952010-12-13 16:17:42 -0800312 bfa_lps_set_n2n_pid(port->fabric->lps, rx_fchs->d_id);
Jing Huang7725ccf2009-09-23 17:46:15 -0700313 }
314
Jing Huang5fbe25c2010-10-18 17:17:23 -0700315 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700316 * First, check if we know the device by pwwn.
317 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700318 rport = bfa_fcs_lport_get_rport_by_pwwn(port, plogi->port_name);
Jing Huang7725ccf2009-09-23 17:46:15 -0700319 if (rport) {
Jing Huang5fbe25c2010-10-18 17:17:23 -0700320 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700321 * Direct Attach P2P mode : handle address assigned by r-port.
Jing Huang7725ccf2009-09-23 17:46:15 -0700322 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700323 if ((!bfa_fcs_fabric_is_switched(port->fabric)) &&
324 (memcmp((void *)&bfa_fcs_lport_get_pwwn(port),
325 (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
326 port->pid = rx_fchs->d_id;
Krishna Gudipatib7044952010-12-13 16:17:42 -0800327 bfa_lps_set_n2n_pid(port->fabric->lps, rx_fchs->d_id);
Jing Huang7725ccf2009-09-23 17:46:15 -0700328 rport->pid = rx_fchs->s_id;
329 }
330 bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
331 return;
332 }
333
Jing Huang5fbe25c2010-10-18 17:17:23 -0700334 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700335 * Next, lookup rport by PID.
336 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700337 rport = bfa_fcs_lport_get_rport_by_pid(port, rx_fchs->s_id);
Jing Huang7725ccf2009-09-23 17:46:15 -0700338 if (!rport) {
Jing Huang5fbe25c2010-10-18 17:17:23 -0700339 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700340 * Inbound PLOGI from a new device.
341 */
342 bfa_fcs_rport_plogi_create(port, rx_fchs, plogi);
343 return;
344 }
345
Jing Huang5fbe25c2010-10-18 17:17:23 -0700346 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700347 * Rport is known only by PID.
348 */
349 if (rport->pwwn) {
Jing Huang5fbe25c2010-10-18 17:17:23 -0700350 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700351 * This is a different device with the same pid. Old device
352 * disappeared. Send implicit LOGO to old device.
353 */
Jing Huangd4b671c2010-12-26 21:46:35 -0800354 WARN_ON(rport->pwwn == plogi->port_name);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800355 bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
Jing Huang7725ccf2009-09-23 17:46:15 -0700356
Jing Huang5fbe25c2010-10-18 17:17:23 -0700357 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700358 * Inbound PLOGI from a new device (with old PID).
359 */
360 bfa_fcs_rport_plogi_create(port, rx_fchs, plogi);
361 return;
362 }
363
Jing Huang5fbe25c2010-10-18 17:17:23 -0700364 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700365 * PLOGI crossing each other.
366 */
Jing Huangd4b671c2010-12-26 21:46:35 -0800367 WARN_ON(rport->pwwn != WWN_NULL);
Jing Huang7725ccf2009-09-23 17:46:15 -0700368 bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
369}
370
371/*
372 * Process incoming ECHO.
373 * Since it does not require a login, it is processed here.
374 */
375static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700376bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
377 struct fc_echo_s *echo, u16 rx_len)
Jing Huang7725ccf2009-09-23 17:46:15 -0700378{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700379 struct fchs_s fchs;
380 struct bfa_fcxp_s *fcxp;
381 struct bfa_rport_s *bfa_rport = NULL;
382 int len, pyld_len;
Jing Huang7725ccf2009-09-23 17:46:15 -0700383
384 bfa_trc(port->fcs, rx_fchs->s_id);
385 bfa_trc(port->fcs, rx_fchs->d_id);
Jing Huang7725ccf2009-09-23 17:46:15 -0700386
387 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
388 if (!fcxp)
389 return;
390
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700391 len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
392 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
393 rx_fchs->ox_id);
Jing Huang7725ccf2009-09-23 17:46:15 -0700394
395 /*
396 * Copy the payload (if any) from the echo frame
397 */
398 pyld_len = rx_len - sizeof(struct fchs_s);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700399 bfa_trc(port->fcs, rx_len);
Jing Huang7725ccf2009-09-23 17:46:15 -0700400 bfa_trc(port->fcs, pyld_len);
401
402 if (pyld_len > len)
403 memcpy(((u8 *) bfa_fcxp_get_reqbuf(fcxp)) +
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700404 sizeof(struct fc_echo_s), (echo + 1),
405 (pyld_len - sizeof(struct fc_echo_s)));
Jing Huang7725ccf2009-09-23 17:46:15 -0700406
407 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700408 BFA_FALSE, FC_CLASS_3, pyld_len, &fchs, NULL, NULL,
409 FC_MAX_PDUSZ, 0);
Jing Huang7725ccf2009-09-23 17:46:15 -0700410}
411
412/*
413 * Process incoming RNID.
414 * Since it does not require a login, it is processed here.
415 */
416static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700417bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
418 struct fc_rnid_cmd_s *rnid, u16 rx_len)
Jing Huang7725ccf2009-09-23 17:46:15 -0700419{
420 struct fc_rnid_common_id_data_s common_id_data;
421 struct fc_rnid_general_topology_data_s gen_topo_data;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700422 struct fchs_s fchs;
Jing Huang7725ccf2009-09-23 17:46:15 -0700423 struct bfa_fcxp_s *fcxp;
424 struct bfa_rport_s *bfa_rport = NULL;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700425 u16 len;
426 u32 data_format;
Jing Huang7725ccf2009-09-23 17:46:15 -0700427
428 bfa_trc(port->fcs, rx_fchs->s_id);
429 bfa_trc(port->fcs, rx_fchs->d_id);
430 bfa_trc(port->fcs, rx_len);
431
432 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
433 if (!fcxp)
434 return;
435
436 /*
437 * Check Node Indentification Data Format
438 * We only support General Topology Discovery Format.
439 * For any other requested Data Formats, we return Common Node Id Data
440 * only, as per FC-LS.
441 */
442 bfa_trc(port->fcs, rnid->node_id_data_format);
443 if (rnid->node_id_data_format == RNID_NODEID_DATA_FORMAT_DISCOVERY) {
444 data_format = RNID_NODEID_DATA_FORMAT_DISCOVERY;
445 /*
446 * Get General topology data for this port
447 */
448 bfa_fs_port_get_gen_topo_data(port, &gen_topo_data);
449 } else {
450 data_format = RNID_NODEID_DATA_FORMAT_COMMON;
451 }
452
453 /*
454 * Copy the Node Id Info
455 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700456 common_id_data.port_name = bfa_fcs_lport_get_pwwn(port);
457 common_id_data.node_name = bfa_fcs_lport_get_nwwn(port);
Jing Huang7725ccf2009-09-23 17:46:15 -0700458
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700459 len = fc_rnid_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
460 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
461 rx_fchs->ox_id, data_format, &common_id_data,
462 &gen_topo_data);
Jing Huang7725ccf2009-09-23 17:46:15 -0700463
464 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700465 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
466 FC_MAX_PDUSZ, 0);
Jing Huang7725ccf2009-09-23 17:46:15 -0700467}
468
469/*
470 * Fill out General Topolpgy Discovery Data for RNID ELS.
471 */
472static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700473bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port,
Jing Huang7725ccf2009-09-23 17:46:15 -0700474 struct fc_rnid_general_topology_data_s *gen_topo_data)
475{
Jing Huang6a18b162010-10-18 17:08:54 -0700476 memset(gen_topo_data, 0,
Jing Huang7725ccf2009-09-23 17:46:15 -0700477 sizeof(struct fc_rnid_general_topology_data_s));
478
Jing Huangba816ea2010-10-18 17:10:50 -0700479 gen_topo_data->asso_type = cpu_to_be32(RNID_ASSOCIATED_TYPE_HOST);
Jing Huang7725ccf2009-09-23 17:46:15 -0700480 gen_topo_data->phy_port_num = 0; /* @todo */
Jing Huangba816ea2010-10-18 17:10:50 -0700481 gen_topo_data->num_attached_nodes = cpu_to_be32(1);
Jing Huang7725ccf2009-09-23 17:46:15 -0700482}
483
484static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700485bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port)
Jing Huang7725ccf2009-09-23 17:46:15 -0700486{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700487 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
488 char lpwwn_buf[BFA_STRING_32];
489
Jing Huang7725ccf2009-09-23 17:46:15 -0700490 bfa_trc(port->fcs, port->fabric->oper_type);
491
492 __port_action[port->fabric->fab_type].init(port);
493 __port_action[port->fabric->fab_type].online(port);
494
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700495 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
Jing Huang88166242010-12-09 17:11:53 -0800496 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700497 "Logical port online: WWN = %s Role = %s\n",
498 lpwwn_buf, "Initiator");
499
500 bfad->bfad_flags |= BFAD_PORT_ONLINE;
Jing Huang7725ccf2009-09-23 17:46:15 -0700501}
502
503static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700504bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port)
Jing Huang7725ccf2009-09-23 17:46:15 -0700505{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700506 struct list_head *qe, *qen;
Jing Huang7725ccf2009-09-23 17:46:15 -0700507 struct bfa_fcs_rport_s *rport;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700508 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
509 char lpwwn_buf[BFA_STRING_32];
Jing Huang7725ccf2009-09-23 17:46:15 -0700510
511 bfa_trc(port->fcs, port->fabric->oper_type);
512
513 __port_action[port->fabric->fab_type].offline(port);
514
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700515 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
Maggie Zhangf7f73812010-12-09 19:08:43 -0800516 if (bfa_sm_cmp_state(port->fabric,
517 bfa_fcs_fabric_sm_online) == BFA_TRUE)
Jing Huang88166242010-12-09 17:11:53 -0800518 BFA_LOG(KERN_ERR, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700519 "Logical port lost fabric connectivity: WWN = %s Role = %s\n",
520 lpwwn_buf, "Initiator");
Jing Huangf8ceafd2009-09-25 12:29:54 -0700521 else
Jing Huang88166242010-12-09 17:11:53 -0800522 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700523 "Logical port taken offline: WWN = %s Role = %s\n",
524 lpwwn_buf, "Initiator");
Jing Huang7725ccf2009-09-23 17:46:15 -0700525
526 list_for_each_safe(qe, qen, &port->rport_q) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700527 rport = (struct bfa_fcs_rport_s *) qe;
Maggie Zhangf7f73812010-12-09 19:08:43 -0800528 bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
Jing Huang7725ccf2009-09-23 17:46:15 -0700529 }
530}
531
532static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700533bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port)
Jing Huang7725ccf2009-09-23 17:46:15 -0700534{
Jing Huangd4b671c2010-12-26 21:46:35 -0800535 WARN_ON(1);
Jing Huang7725ccf2009-09-23 17:46:15 -0700536}
537
538static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700539bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port)
Jing Huang7725ccf2009-09-23 17:46:15 -0700540{
Jing Huangd4b671c2010-12-26 21:46:35 -0800541 WARN_ON(1);
Jing Huang7725ccf2009-09-23 17:46:15 -0700542}
543
544static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700545bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port)
Jing Huang7725ccf2009-09-23 17:46:15 -0700546{
Jing Huangd4b671c2010-12-26 21:46:35 -0800547 WARN_ON(1);
Jing Huang7725ccf2009-09-23 17:46:15 -0700548}
549
550static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700551bfa_fcs_lport_abts_acc(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs)
Jing Huang7725ccf2009-09-23 17:46:15 -0700552{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700553 struct fchs_s fchs;
554 struct bfa_fcxp_s *fcxp;
555 int len;
Jing Huang7725ccf2009-09-23 17:46:15 -0700556
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700557 bfa_trc(port->fcs, rx_fchs->d_id);
558 bfa_trc(port->fcs, rx_fchs->s_id);
559
560 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
561 if (!fcxp)
562 return;
563
564 len = fc_ba_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
565 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
566 rx_fchs->ox_id, 0);
567
568 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
569 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
570 FC_MAX_PDUSZ, 0);
571}
572static void
573bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port)
574{
575 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
576 char lpwwn_buf[BFA_STRING_32];
577
578 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
Jing Huang88166242010-12-09 17:11:53 -0800579 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700580 "Logical port deleted: WWN = %s Role = %s\n",
581 lpwwn_buf, "Initiator");
582
583 /* Base port will be deleted by the OS driver */
Jing Huang7725ccf2009-09-23 17:46:15 -0700584 if (port->vport) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700585 bfa_fcb_lport_delete(port->fcs->bfad, port->port_cfg.roles,
586 port->fabric->vf_drv,
587 port->vport ? port->vport->vport_drv : NULL);
Jing Huang7725ccf2009-09-23 17:46:15 -0700588 bfa_fcs_vport_delete_comp(port->vport);
589 } else {
Maggie Zhangf7f73812010-12-09 19:08:43 -0800590 bfa_wc_down(&port->fabric->wc);
Jing Huang7725ccf2009-09-23 17:46:15 -0700591 }
592}
593
594
Jing Huang5fbe25c2010-10-18 17:17:23 -0700595/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700596 * Unsolicited frame receive handling.
Jing Huang7725ccf2009-09-23 17:46:15 -0700597 */
598void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700599bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport,
600 struct fchs_s *fchs, u16 len)
Jing Huang7725ccf2009-09-23 17:46:15 -0700601{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700602 u32 pid = fchs->s_id;
Jing Huang7725ccf2009-09-23 17:46:15 -0700603 struct bfa_fcs_rport_s *rport = NULL;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700604 struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
Jing Huang7725ccf2009-09-23 17:46:15 -0700605
606 bfa_stats(lport, uf_recvs);
Krishna Gudipati15821f02010-12-13 16:23:27 -0800607 bfa_trc(lport->fcs, fchs->type);
Jing Huang7725ccf2009-09-23 17:46:15 -0700608
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700609 if (!bfa_fcs_lport_is_online(lport)) {
Jing Huang7725ccf2009-09-23 17:46:15 -0700610 bfa_stats(lport, uf_recv_drops);
611 return;
612 }
613
Jing Huang5fbe25c2010-10-18 17:17:23 -0700614 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700615 * First, handle ELSs that donot require a login.
616 */
617 /*
618 * Handle PLOGI first
619 */
620 if ((fchs->type == FC_TYPE_ELS) &&
621 (els_cmd->els_code == FC_ELS_PLOGI)) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700622 bfa_fcs_lport_plogi(lport, fchs, (struct fc_logi_s *) els_cmd);
Jing Huang7725ccf2009-09-23 17:46:15 -0700623 return;
624 }
625
626 /*
627 * Handle ECHO separately.
628 */
629 if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_ECHO)) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700630 bfa_fcs_lport_echo(lport, fchs,
631 (struct fc_echo_s *)els_cmd, len);
Jing Huang7725ccf2009-09-23 17:46:15 -0700632 return;
633 }
634
635 /*
636 * Handle RNID separately.
637 */
638 if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_RNID)) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700639 bfa_fcs_lport_rnid(lport, fchs,
Jing Huang7725ccf2009-09-23 17:46:15 -0700640 (struct fc_rnid_cmd_s *) els_cmd, len);
641 return;
642 }
643
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700644 if (fchs->type == FC_TYPE_BLS) {
645 if ((fchs->routing == FC_RTG_BASIC_LINK) &&
646 (fchs->cat_info == FC_CAT_ABTS))
647 bfa_fcs_lport_abts_acc(lport, fchs);
648 return;
649 }
Jing Huang5fbe25c2010-10-18 17:17:23 -0700650 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700651 * look for a matching remote port ID
652 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700653 rport = bfa_fcs_lport_get_rport_by_pid(lport, pid);
Jing Huang7725ccf2009-09-23 17:46:15 -0700654 if (rport) {
655 bfa_trc(rport->fcs, fchs->s_id);
656 bfa_trc(rport->fcs, fchs->d_id);
657 bfa_trc(rport->fcs, fchs->type);
658
659 bfa_fcs_rport_uf_recv(rport, fchs, len);
660 return;
661 }
662
Jing Huang5fbe25c2010-10-18 17:17:23 -0700663 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700664 * Only handles ELS frames for now.
665 */
666 if (fchs->type != FC_TYPE_ELS) {
Krishna Gudipati15821f02010-12-13 16:23:27 -0800667 bfa_trc(lport->fcs, fchs->s_id);
668 bfa_trc(lport->fcs, fchs->d_id);
669 /* ignore type FC_TYPE_FC_FSS */
670 if (fchs->type != FC_TYPE_FC_FSS)
671 bfa_sm_fault(lport->fcs, fchs->type);
Jing Huang7725ccf2009-09-23 17:46:15 -0700672 return;
673 }
674
675 bfa_trc(lport->fcs, els_cmd->els_code);
676 if (els_cmd->els_code == FC_ELS_RSCN) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700677 bfa_fcs_lport_scn_process_rscn(lport, fchs, len);
Jing Huang7725ccf2009-09-23 17:46:15 -0700678 return;
679 }
680
681 if (els_cmd->els_code == FC_ELS_LOGO) {
Jing Huang5fbe25c2010-10-18 17:17:23 -0700682 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700683 * @todo Handle LOGO frames received.
684 */
Jing Huang7725ccf2009-09-23 17:46:15 -0700685 return;
686 }
687
688 if (els_cmd->els_code == FC_ELS_PRLI) {
Jing Huang5fbe25c2010-10-18 17:17:23 -0700689 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700690 * @todo Handle PRLI frames received.
691 */
Jing Huang7725ccf2009-09-23 17:46:15 -0700692 return;
693 }
694
Jing Huang5fbe25c2010-10-18 17:17:23 -0700695 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700696 * Unhandled ELS frames. Send a LS_RJT.
697 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700698 bfa_fcs_lport_send_ls_rjt(lport, fchs, FC_LS_RJT_RSN_CMD_NOT_SUPP,
Jing Huang7725ccf2009-09-23 17:46:15 -0700699 FC_LS_RJT_EXP_NO_ADDL_INFO);
700
701}
702
Jing Huang5fbe25c2010-10-18 17:17:23 -0700703/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700704 * PID based Lookup for a R-Port in the Port R-Port Queue
705 */
706struct bfa_fcs_rport_s *
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700707bfa_fcs_lport_get_rport_by_pid(struct bfa_fcs_lport_s *port, u32 pid)
Jing Huang7725ccf2009-09-23 17:46:15 -0700708{
709 struct bfa_fcs_rport_s *rport;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700710 struct list_head *qe;
Jing Huang7725ccf2009-09-23 17:46:15 -0700711
712 list_for_each(qe, &port->rport_q) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700713 rport = (struct bfa_fcs_rport_s *) qe;
Jing Huang7725ccf2009-09-23 17:46:15 -0700714 if (rport->pid == pid)
715 return rport;
716 }
717
718 bfa_trc(port->fcs, pid);
719 return NULL;
720}
721
Jing Huang5fbe25c2010-10-18 17:17:23 -0700722/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700723 * PWWN based Lookup for a R-Port in the Port R-Port Queue
724 */
725struct bfa_fcs_rport_s *
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700726bfa_fcs_lport_get_rport_by_pwwn(struct bfa_fcs_lport_s *port, wwn_t pwwn)
Jing Huang7725ccf2009-09-23 17:46:15 -0700727{
728 struct bfa_fcs_rport_s *rport;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700729 struct list_head *qe;
Jing Huang7725ccf2009-09-23 17:46:15 -0700730
731 list_for_each(qe, &port->rport_q) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700732 rport = (struct bfa_fcs_rport_s *) qe;
Jing Huang7725ccf2009-09-23 17:46:15 -0700733 if (wwn_is_equal(rport->pwwn, pwwn))
734 return rport;
735 }
736
737 bfa_trc(port->fcs, pwwn);
Jing Huangf8ceafd2009-09-25 12:29:54 -0700738 return NULL;
Jing Huang7725ccf2009-09-23 17:46:15 -0700739}
740
Jing Huang5fbe25c2010-10-18 17:17:23 -0700741/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700742 * NWWN based Lookup for a R-Port in the Port R-Port Queue
743 */
744struct bfa_fcs_rport_s *
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700745bfa_fcs_lport_get_rport_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t nwwn)
Jing Huang7725ccf2009-09-23 17:46:15 -0700746{
747 struct bfa_fcs_rport_s *rport;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700748 struct list_head *qe;
Jing Huang7725ccf2009-09-23 17:46:15 -0700749
750 list_for_each(qe, &port->rport_q) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700751 rport = (struct bfa_fcs_rport_s *) qe;
Jing Huang7725ccf2009-09-23 17:46:15 -0700752 if (wwn_is_equal(rport->nwwn, nwwn))
753 return rport;
754 }
755
756 bfa_trc(port->fcs, nwwn);
Jing Huangf8ceafd2009-09-25 12:29:54 -0700757 return NULL;
Jing Huang7725ccf2009-09-23 17:46:15 -0700758}
759
Jing Huang5fbe25c2010-10-18 17:17:23 -0700760/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700761 * Called by rport module when new rports are discovered.
762 */
763void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700764bfa_fcs_lport_add_rport(
765 struct bfa_fcs_lport_s *port,
766 struct bfa_fcs_rport_s *rport)
Jing Huang7725ccf2009-09-23 17:46:15 -0700767{
768 list_add_tail(&rport->qe, &port->rport_q);
769 port->num_rports++;
770}
771
Jing Huang5fbe25c2010-10-18 17:17:23 -0700772/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700773 * Called by rport module to when rports are deleted.
774 */
775void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700776bfa_fcs_lport_del_rport(
777 struct bfa_fcs_lport_s *port,
778 struct bfa_fcs_rport_s *rport)
Jing Huang7725ccf2009-09-23 17:46:15 -0700779{
Jing Huangd4b671c2010-12-26 21:46:35 -0800780 WARN_ON(!bfa_q_is_on_q(&port->rport_q, rport));
Jing Huang7725ccf2009-09-23 17:46:15 -0700781 list_del(&rport->qe);
782 port->num_rports--;
783
784 bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELRPORT);
785}
786
Jing Huang5fbe25c2010-10-18 17:17:23 -0700787/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700788 * Called by fabric for base port when fabric login is complete.
789 * Called by vport for virtual ports when FDISC is complete.
790 */
791void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700792bfa_fcs_lport_online(struct bfa_fcs_lport_s *port)
Jing Huang7725ccf2009-09-23 17:46:15 -0700793{
794 bfa_sm_send_event(port, BFA_FCS_PORT_SM_ONLINE);
795}
796
Jing Huang5fbe25c2010-10-18 17:17:23 -0700797/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700798 * Called by fabric for base port when fabric goes offline.
799 * Called by vport for virtual ports when virtual port becomes offline.
800 */
801void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700802bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port)
Jing Huang7725ccf2009-09-23 17:46:15 -0700803{
804 bfa_sm_send_event(port, BFA_FCS_PORT_SM_OFFLINE);
805}
806
Jing Huang5fbe25c2010-10-18 17:17:23 -0700807/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700808 * Called by fabric to delete base lport and associated resources.
809 *
810 * Called by vport to delete lport and associated resources. Should call
811 * bfa_fcs_vport_delete_comp() for vports on completion.
812 */
813void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700814bfa_fcs_lport_delete(struct bfa_fcs_lport_s *port)
Jing Huang7725ccf2009-09-23 17:46:15 -0700815{
816 bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELETE);
817}
818
Jing Huang5fbe25c2010-10-18 17:17:23 -0700819/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700820 * Return TRUE if port is online, else return FALSE
821 */
822bfa_boolean_t
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700823bfa_fcs_lport_is_online(struct bfa_fcs_lport_s *port)
Jing Huang7725ccf2009-09-23 17:46:15 -0700824{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700825 return bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online);
Jing Huang7725ccf2009-09-23 17:46:15 -0700826}
827
Jing Huang5fbe25c2010-10-18 17:17:23 -0700828/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700829 * Attach time initialization of logical ports.
Jing Huang7725ccf2009-09-23 17:46:15 -0700830 */
831void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700832bfa_fcs_lport_attach(struct bfa_fcs_lport_s *lport, struct bfa_fcs_s *fcs,
833 u16 vf_id, struct bfa_fcs_vport_s *vport)
Jing Huang7725ccf2009-09-23 17:46:15 -0700834{
835 lport->fcs = fcs;
836 lport->fabric = bfa_fcs_vf_lookup(fcs, vf_id);
Jing Huang7725ccf2009-09-23 17:46:15 -0700837 lport->vport = vport;
Maggie Zhangf7f73812010-12-09 19:08:43 -0800838 lport->lp_tag = (vport) ? vport->lps->lp_tag :
839 lport->fabric->lps->lp_tag;
Jing Huang7725ccf2009-09-23 17:46:15 -0700840
841 INIT_LIST_HEAD(&lport->rport_q);
842 lport->num_rports = 0;
Krishna Gudipatie6714322010-03-03 17:44:02 -0800843}
Jing Huang7725ccf2009-09-23 17:46:15 -0700844
Jing Huang5fbe25c2010-10-18 17:17:23 -0700845/*
Krishna Gudipatie6714322010-03-03 17:44:02 -0800846 * Logical port initialization of base or virtual port.
847 * Called by fabric for base port or by vport for virtual ports.
848 */
849
850void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700851bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport,
852 struct bfa_lport_cfg_s *port_cfg)
Krishna Gudipatie6714322010-03-03 17:44:02 -0800853{
854 struct bfa_fcs_vport_s *vport = lport->vport;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700855 struct bfad_s *bfad = (struct bfad_s *)lport->fcs->bfad;
856 char lpwwn_buf[BFA_STRING_32];
Krishna Gudipatie6714322010-03-03 17:44:02 -0800857
Jing Huang6a18b162010-10-18 17:08:54 -0700858 lport->port_cfg = *port_cfg;
Krishna Gudipatie6714322010-03-03 17:44:02 -0800859
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700860 lport->bfad_port = bfa_fcb_lport_new(lport->fcs->bfad, lport,
861 lport->port_cfg.roles,
862 lport->fabric->vf_drv,
863 vport ? vport->vport_drv : NULL);
Krishna Gudipatie6714322010-03-03 17:44:02 -0800864
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700865 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(lport));
Jing Huang88166242010-12-09 17:11:53 -0800866 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700867 "New logical port created: WWN = %s Role = %s\n",
868 lpwwn_buf, "Initiator");
Jing Huang7725ccf2009-09-23 17:46:15 -0700869
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700870 bfa_sm_set_state(lport, bfa_fcs_lport_sm_uninit);
Jing Huang7725ccf2009-09-23 17:46:15 -0700871 bfa_sm_send_event(lport, BFA_FCS_PORT_SM_CREATE);
872}
873
Jing Huang5fbe25c2010-10-18 17:17:23 -0700874/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700875 * fcs_lport_api
876 */
877
878void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700879bfa_fcs_lport_get_attr(
880 struct bfa_fcs_lport_s *port,
881 struct bfa_lport_attr_s *port_attr)
Jing Huang7725ccf2009-09-23 17:46:15 -0700882{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700883 if (bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online))
Jing Huang7725ccf2009-09-23 17:46:15 -0700884 port_attr->pid = port->pid;
885 else
886 port_attr->pid = 0;
887
888 port_attr->port_cfg = port->port_cfg;
889
890 if (port->fabric) {
Maggie Zhangf7f73812010-12-09 19:08:43 -0800891 port_attr->port_type = port->fabric->oper_type;
Maggie Zhangda99dcc2010-12-09 19:13:20 -0800892 port_attr->loopback = bfa_sm_cmp_state(port->fabric,
893 bfa_fcs_fabric_sm_loopback);
Krishna Gudipatif926a052010-03-05 19:36:00 -0800894 port_attr->authfail =
Maggie Zhangf7f73812010-12-09 19:08:43 -0800895 bfa_sm_cmp_state(port->fabric,
896 bfa_fcs_fabric_sm_auth_failed);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700897 port_attr->fabric_name = bfa_fcs_lport_get_fabric_name(port);
Jing Huang7725ccf2009-09-23 17:46:15 -0700898 memcpy(port_attr->fabric_ip_addr,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700899 bfa_fcs_lport_get_fabric_ipaddr(port),
900 BFA_FCS_FABRIC_IPADDR_SZ);
Jing Huang7725ccf2009-09-23 17:46:15 -0700901
Krishna Gudipati86e32da2010-03-05 19:35:33 -0800902 if (port->vport != NULL) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700903 port_attr->port_type = BFA_PORT_TYPE_VPORT;
Krishna Gudipati86e32da2010-03-05 19:35:33 -0800904 port_attr->fpma_mac =
Maggie Zhangf7f73812010-12-09 19:08:43 -0800905 port->vport->lps->lp_mac;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700906 } else {
Krishna Gudipati86e32da2010-03-05 19:35:33 -0800907 port_attr->fpma_mac =
Maggie Zhangf7f73812010-12-09 19:08:43 -0800908 port->fabric->lps->lp_mac;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700909 }
Jing Huang7725ccf2009-09-23 17:46:15 -0700910 } else {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700911 port_attr->port_type = BFA_PORT_TYPE_UNKNOWN;
912 port_attr->state = BFA_LPORT_UNINIT;
Jing Huang7725ccf2009-09-23 17:46:15 -0700913 }
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700914}
915
Jing Huang5fbe25c2010-10-18 17:17:23 -0700916/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700917 * bfa_fcs_lport_fab port fab functions
918 */
919
Jing Huang5fbe25c2010-10-18 17:17:23 -0700920/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700921 * Called by port to initialize fabric services of the base port.
922 */
923static void
924bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port)
925{
926 bfa_fcs_lport_ns_init(port);
927 bfa_fcs_lport_scn_init(port);
928 bfa_fcs_lport_ms_init(port);
929}
930
Jing Huang5fbe25c2010-10-18 17:17:23 -0700931/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700932 * Called by port to notify transition to online state.
933 */
934static void
935bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port)
936{
937 bfa_fcs_lport_ns_online(port);
938 bfa_fcs_lport_scn_online(port);
939}
940
Jing Huang5fbe25c2010-10-18 17:17:23 -0700941/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700942 * Called by port to notify transition to offline state.
943 */
944static void
945bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port)
946{
947 bfa_fcs_lport_ns_offline(port);
948 bfa_fcs_lport_scn_offline(port);
949 bfa_fcs_lport_ms_offline(port);
950}
951
Jing Huang5fbe25c2010-10-18 17:17:23 -0700952/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700953 * bfa_fcs_lport_n2n functions
954 */
955
Jing Huang5fbe25c2010-10-18 17:17:23 -0700956/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700957 * Called by fcs/port to initialize N2N topology.
958 */
959static void
960bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port)
961{
962}
963
Jing Huang5fbe25c2010-10-18 17:17:23 -0700964/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700965 * Called by fcs/port to notify transition to online state.
966 */
967static void
968bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port)
969{
970 struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n;
971 struct bfa_lport_cfg_s *pcfg = &port->port_cfg;
972 struct bfa_fcs_rport_s *rport;
973
974 bfa_trc(port->fcs, pcfg->pwwn);
975
976 /*
977 * If our PWWN is > than that of the r-port, we have to initiate PLOGI
978 * and assign an Address. if not, we need to wait for its PLOGI.
979 *
980 * If our PWWN is < than that of the remote port, it will send a PLOGI
981 * with the PIDs assigned. The rport state machine take care of this
982 * incoming PLOGI.
983 */
984 if (memcmp
985 ((void *)&pcfg->pwwn, (void *)&n2n_port->rem_port_wwn,
986 sizeof(wwn_t)) > 0) {
987 port->pid = N2N_LOCAL_PID;
Krishna Gudipatib7044952010-12-13 16:17:42 -0800988 bfa_lps_set_n2n_pid(port->fabric->lps, N2N_LOCAL_PID);
Jing Huang5fbe25c2010-10-18 17:17:23 -0700989 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700990 * First, check if we know the device by pwwn.
991 */
992 rport = bfa_fcs_lport_get_rport_by_pwwn(port,
993 n2n_port->rem_port_wwn);
994 if (rport) {
995 bfa_trc(port->fcs, rport->pid);
996 bfa_trc(port->fcs, rport->pwwn);
997 rport->pid = N2N_REMOTE_PID;
Maggie Zhangf7f73812010-12-09 19:08:43 -0800998 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700999 return;
1000 }
1001
1002 /*
1003 * In n2n there can be only one rport. Delete the old one
1004 * whose pid should be zero, because it is offline.
1005 */
1006 if (port->num_rports > 0) {
1007 rport = bfa_fcs_lport_get_rport_by_pid(port, 0);
Jing Huangd4b671c2010-12-26 21:46:35 -08001008 WARN_ON(rport == NULL);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001009 if (rport) {
1010 bfa_trc(port->fcs, rport->pwwn);
Maggie Zhangf7f73812010-12-09 19:08:43 -08001011 bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001012 }
1013 }
1014 bfa_fcs_rport_create(port, N2N_REMOTE_PID);
1015 }
1016}
1017
Jing Huang5fbe25c2010-10-18 17:17:23 -07001018/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001019 * Called by fcs/port to notify transition to offline state.
1020 */
1021static void
1022bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port)
1023{
1024 struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n;
1025
1026 bfa_trc(port->fcs, port->pid);
1027 port->pid = 0;
1028 n2n_port->rem_port_wwn = 0;
1029 n2n_port->reply_oxid = 0;
1030}
1031
1032#define BFA_FCS_FDMI_CMD_MAX_RETRIES 2
1033
1034/*
1035 * forward declarations
1036 */
1037static void bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg,
1038 struct bfa_fcxp_s *fcxp_alloced);
1039static void bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg,
1040 struct bfa_fcxp_s *fcxp_alloced);
1041static void bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg,
1042 struct bfa_fcxp_s *fcxp_alloced);
1043static void bfa_fcs_lport_fdmi_rhba_response(void *fcsarg,
1044 struct bfa_fcxp_s *fcxp,
1045 void *cbarg,
1046 bfa_status_t req_status,
1047 u32 rsp_len,
1048 u32 resid_len,
1049 struct fchs_s *rsp_fchs);
1050static void bfa_fcs_lport_fdmi_rprt_response(void *fcsarg,
1051 struct bfa_fcxp_s *fcxp,
1052 void *cbarg,
1053 bfa_status_t req_status,
1054 u32 rsp_len,
1055 u32 resid_len,
1056 struct fchs_s *rsp_fchs);
1057static void bfa_fcs_lport_fdmi_rpa_response(void *fcsarg,
1058 struct bfa_fcxp_s *fcxp,
1059 void *cbarg,
1060 bfa_status_t req_status,
1061 u32 rsp_len,
1062 u32 resid_len,
1063 struct fchs_s *rsp_fchs);
1064static void bfa_fcs_lport_fdmi_timeout(void *arg);
1065static u16 bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1066 u8 *pyld);
1067static u16 bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1068 u8 *pyld);
1069static u16 bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1070 u8 *pyld);
1071static u16 bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *
1072 fdmi, u8 *pyld);
1073static void bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
1074 struct bfa_fcs_fdmi_hba_attr_s *hba_attr);
1075static void bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
1076 struct bfa_fcs_fdmi_port_attr_s *port_attr);
Jing Huang5fbe25c2010-10-18 17:17:23 -07001077/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001078 * fcs_fdmi_sm FCS FDMI state machine
1079 */
1080
Jing Huang5fbe25c2010-10-18 17:17:23 -07001081/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001082 * FDMI State Machine events
1083 */
1084enum port_fdmi_event {
1085 FDMISM_EVENT_PORT_ONLINE = 1,
1086 FDMISM_EVENT_PORT_OFFLINE = 2,
1087 FDMISM_EVENT_RSP_OK = 4,
1088 FDMISM_EVENT_RSP_ERROR = 5,
1089 FDMISM_EVENT_TIMEOUT = 6,
1090 FDMISM_EVENT_RHBA_SENT = 7,
1091 FDMISM_EVENT_RPRT_SENT = 8,
1092 FDMISM_EVENT_RPA_SENT = 9,
1093};
1094
1095static void bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi,
1096 enum port_fdmi_event event);
1097static void bfa_fcs_lport_fdmi_sm_sending_rhba(
1098 struct bfa_fcs_lport_fdmi_s *fdmi,
1099 enum port_fdmi_event event);
1100static void bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1101 enum port_fdmi_event event);
1102static void bfa_fcs_lport_fdmi_sm_rhba_retry(
1103 struct bfa_fcs_lport_fdmi_s *fdmi,
1104 enum port_fdmi_event event);
1105static void bfa_fcs_lport_fdmi_sm_sending_rprt(
1106 struct bfa_fcs_lport_fdmi_s *fdmi,
1107 enum port_fdmi_event event);
1108static void bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1109 enum port_fdmi_event event);
1110static void bfa_fcs_lport_fdmi_sm_rprt_retry(
1111 struct bfa_fcs_lport_fdmi_s *fdmi,
1112 enum port_fdmi_event event);
1113static void bfa_fcs_lport_fdmi_sm_sending_rpa(
1114 struct bfa_fcs_lport_fdmi_s *fdmi,
1115 enum port_fdmi_event event);
1116static void bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1117 enum port_fdmi_event event);
1118static void bfa_fcs_lport_fdmi_sm_rpa_retry(
1119 struct bfa_fcs_lport_fdmi_s *fdmi,
1120 enum port_fdmi_event event);
1121static void bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi,
1122 enum port_fdmi_event event);
1123static void bfa_fcs_lport_fdmi_sm_disabled(
1124 struct bfa_fcs_lport_fdmi_s *fdmi,
1125 enum port_fdmi_event event);
Jing Huang5fbe25c2010-10-18 17:17:23 -07001126/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001127 * Start in offline state - awaiting MS to send start.
1128 */
1129static void
1130bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi,
1131 enum port_fdmi_event event)
1132{
1133 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1134
1135 bfa_trc(port->fcs, port->port_cfg.pwwn);
1136 bfa_trc(port->fcs, event);
1137
1138 fdmi->retry_cnt = 0;
1139
1140 switch (event) {
1141 case FDMISM_EVENT_PORT_ONLINE:
1142 if (port->vport) {
1143 /*
1144 * For Vports, register a new port.
1145 */
1146 bfa_sm_set_state(fdmi,
1147 bfa_fcs_lport_fdmi_sm_sending_rprt);
1148 bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL);
1149 } else {
1150 /*
1151 * For a base port, we should first register the HBA
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001152 * attribute. The HBA attribute also contains the base
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001153 * port registration.
1154 */
1155 bfa_sm_set_state(fdmi,
1156 bfa_fcs_lport_fdmi_sm_sending_rhba);
1157 bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL);
1158 }
1159 break;
1160
1161 case FDMISM_EVENT_PORT_OFFLINE:
1162 break;
1163
1164 default:
1165 bfa_sm_fault(port->fcs, event);
1166 }
1167}
1168
1169static void
1170bfa_fcs_lport_fdmi_sm_sending_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1171 enum port_fdmi_event event)
1172{
1173 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1174
1175 bfa_trc(port->fcs, port->port_cfg.pwwn);
1176 bfa_trc(port->fcs, event);
1177
1178 switch (event) {
1179 case FDMISM_EVENT_RHBA_SENT:
1180 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rhba);
1181 break;
1182
1183 case FDMISM_EVENT_PORT_OFFLINE:
1184 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1185 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1186 &fdmi->fcxp_wqe);
1187 break;
1188
1189 default:
1190 bfa_sm_fault(port->fcs, event);
1191 }
1192}
1193
1194static void
1195bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1196 enum port_fdmi_event event)
1197{
1198 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1199
1200 bfa_trc(port->fcs, port->port_cfg.pwwn);
1201 bfa_trc(port->fcs, event);
1202
1203 switch (event) {
1204 case FDMISM_EVENT_RSP_ERROR:
1205 /*
1206 * if max retries have not been reached, start timer for a
1207 * delayed retry
1208 */
1209 if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1210 bfa_sm_set_state(fdmi,
1211 bfa_fcs_lport_fdmi_sm_rhba_retry);
1212 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1213 &fdmi->timer,
1214 bfa_fcs_lport_fdmi_timeout, fdmi,
1215 BFA_FCS_RETRY_TIMEOUT);
1216 } else {
1217 /*
1218 * set state to offline
1219 */
1220 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1221 }
1222 break;
1223
1224 case FDMISM_EVENT_RSP_OK:
1225 /*
1226 * Initiate Register Port Attributes
1227 */
1228 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa);
1229 fdmi->retry_cnt = 0;
1230 bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL);
1231 break;
1232
1233 case FDMISM_EVENT_PORT_OFFLINE:
1234 bfa_fcxp_discard(fdmi->fcxp);
1235 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1236 break;
1237
1238 default:
1239 bfa_sm_fault(port->fcs, event);
1240 }
1241}
1242
1243static void
1244bfa_fcs_lport_fdmi_sm_rhba_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1245 enum port_fdmi_event event)
1246{
1247 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1248
1249 bfa_trc(port->fcs, port->port_cfg.pwwn);
1250 bfa_trc(port->fcs, event);
1251
1252 switch (event) {
1253 case FDMISM_EVENT_TIMEOUT:
1254 /*
1255 * Retry Timer Expired. Re-send
1256 */
1257 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rhba);
1258 bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL);
1259 break;
1260
1261 case FDMISM_EVENT_PORT_OFFLINE:
1262 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1263 bfa_timer_stop(&fdmi->timer);
1264 break;
1265
1266 default:
1267 bfa_sm_fault(port->fcs, event);
1268 }
1269}
1270
1271/*
1272* RPRT : Register Port
1273 */
1274static void
1275bfa_fcs_lport_fdmi_sm_sending_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1276 enum port_fdmi_event event)
1277{
1278 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1279
1280 bfa_trc(port->fcs, port->port_cfg.pwwn);
1281 bfa_trc(port->fcs, event);
1282
1283 switch (event) {
1284 case FDMISM_EVENT_RPRT_SENT:
1285 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rprt);
1286 break;
1287
1288 case FDMISM_EVENT_PORT_OFFLINE:
1289 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1290 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1291 &fdmi->fcxp_wqe);
1292 break;
1293
1294 default:
1295 bfa_sm_fault(port->fcs, event);
1296 }
1297}
1298
1299static void
1300bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1301 enum port_fdmi_event event)
1302{
1303 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1304
1305 bfa_trc(port->fcs, port->port_cfg.pwwn);
1306 bfa_trc(port->fcs, event);
1307
1308 switch (event) {
1309 case FDMISM_EVENT_RSP_ERROR:
1310 /*
1311 * if max retries have not been reached, start timer for a
1312 * delayed retry
1313 */
1314 if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1315 bfa_sm_set_state(fdmi,
1316 bfa_fcs_lport_fdmi_sm_rprt_retry);
1317 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1318 &fdmi->timer,
1319 bfa_fcs_lport_fdmi_timeout, fdmi,
1320 BFA_FCS_RETRY_TIMEOUT);
1321
1322 } else {
1323 /*
1324 * set state to offline
1325 */
1326 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1327 fdmi->retry_cnt = 0;
1328 }
1329 break;
1330
1331 case FDMISM_EVENT_RSP_OK:
1332 fdmi->retry_cnt = 0;
1333 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online);
1334 break;
1335
1336 case FDMISM_EVENT_PORT_OFFLINE:
1337 bfa_fcxp_discard(fdmi->fcxp);
1338 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1339 break;
1340
1341 default:
1342 bfa_sm_fault(port->fcs, event);
1343 }
1344}
1345
1346static void
1347bfa_fcs_lport_fdmi_sm_rprt_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1348 enum port_fdmi_event event)
1349{
1350 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1351
1352 bfa_trc(port->fcs, port->port_cfg.pwwn);
1353 bfa_trc(port->fcs, event);
1354
1355 switch (event) {
1356 case FDMISM_EVENT_TIMEOUT:
1357 /*
1358 * Retry Timer Expired. Re-send
1359 */
1360 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rprt);
1361 bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL);
1362 break;
1363
1364 case FDMISM_EVENT_PORT_OFFLINE:
1365 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1366 bfa_timer_stop(&fdmi->timer);
1367 break;
1368
1369 default:
1370 bfa_sm_fault(port->fcs, event);
1371 }
1372}
1373
1374/*
1375 * Register Port Attributes
1376 */
1377static void
1378bfa_fcs_lport_fdmi_sm_sending_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1379 enum port_fdmi_event event)
1380{
1381 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1382
1383 bfa_trc(port->fcs, port->port_cfg.pwwn);
1384 bfa_trc(port->fcs, event);
1385
1386 switch (event) {
1387 case FDMISM_EVENT_RPA_SENT:
1388 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa);
1389 break;
1390
1391 case FDMISM_EVENT_PORT_OFFLINE:
1392 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1393 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1394 &fdmi->fcxp_wqe);
1395 break;
1396
1397 default:
1398 bfa_sm_fault(port->fcs, event);
1399 }
1400}
1401
1402static void
1403bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1404 enum port_fdmi_event event)
1405{
1406 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1407
1408 bfa_trc(port->fcs, port->port_cfg.pwwn);
1409 bfa_trc(port->fcs, event);
1410
1411 switch (event) {
1412 case FDMISM_EVENT_RSP_ERROR:
1413 /*
1414 * if max retries have not been reached, start timer for a
1415 * delayed retry
1416 */
1417 if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1418 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa_retry);
1419 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1420 &fdmi->timer,
1421 bfa_fcs_lport_fdmi_timeout, fdmi,
1422 BFA_FCS_RETRY_TIMEOUT);
1423 } else {
1424 /*
1425 * set state to offline
1426 */
1427 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1428 fdmi->retry_cnt = 0;
1429 }
1430 break;
1431
1432 case FDMISM_EVENT_RSP_OK:
1433 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online);
1434 fdmi->retry_cnt = 0;
1435 break;
1436
1437 case FDMISM_EVENT_PORT_OFFLINE:
1438 bfa_fcxp_discard(fdmi->fcxp);
1439 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1440 break;
1441
1442 default:
1443 bfa_sm_fault(port->fcs, event);
1444 }
1445}
1446
1447static void
1448bfa_fcs_lport_fdmi_sm_rpa_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1449 enum port_fdmi_event event)
1450{
1451 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1452
1453 bfa_trc(port->fcs, port->port_cfg.pwwn);
1454 bfa_trc(port->fcs, event);
1455
1456 switch (event) {
1457 case FDMISM_EVENT_TIMEOUT:
1458 /*
1459 * Retry Timer Expired. Re-send
1460 */
1461 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa);
1462 bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL);
1463 break;
1464
1465 case FDMISM_EVENT_PORT_OFFLINE:
1466 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1467 bfa_timer_stop(&fdmi->timer);
1468 break;
1469
1470 default:
1471 bfa_sm_fault(port->fcs, event);
1472 }
1473}
1474
1475static void
1476bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi,
1477 enum port_fdmi_event event)
1478{
1479 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1480
1481 bfa_trc(port->fcs, port->port_cfg.pwwn);
1482 bfa_trc(port->fcs, event);
1483
1484 switch (event) {
1485 case FDMISM_EVENT_PORT_OFFLINE:
1486 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1487 break;
1488
1489 default:
1490 bfa_sm_fault(port->fcs, event);
1491 }
1492}
Jing Huang5fbe25c2010-10-18 17:17:23 -07001493/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001494 * FDMI is disabled state.
1495 */
1496static void
1497bfa_fcs_lport_fdmi_sm_disabled(struct bfa_fcs_lport_fdmi_s *fdmi,
1498 enum port_fdmi_event event)
1499{
1500 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1501
1502 bfa_trc(port->fcs, port->port_cfg.pwwn);
1503 bfa_trc(port->fcs, event);
1504
1505 /* No op State. It can only be enabled at Driver Init. */
1506}
1507
Jing Huang5fbe25c2010-10-18 17:17:23 -07001508/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001509* RHBA : Register HBA Attributes.
1510 */
1511static void
1512bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1513{
1514 struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
1515 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1516 struct fchs_s fchs;
1517 int len, attr_len;
1518 struct bfa_fcxp_s *fcxp;
1519 u8 *pyld;
1520
1521 bfa_trc(port->fcs, port->port_cfg.pwwn);
1522
1523 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1524 if (!fcxp) {
1525 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
1526 bfa_fcs_lport_fdmi_send_rhba, fdmi);
1527 return;
1528 }
1529 fdmi->fcxp = fcxp;
1530
1531 pyld = bfa_fcxp_get_reqbuf(fcxp);
Jing Huang6a18b162010-10-18 17:08:54 -07001532 memset(pyld, 0, FC_MAX_PDUSZ);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001533
1534 len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
1535 FDMI_RHBA);
1536
1537 attr_len =
1538 bfa_fcs_lport_fdmi_build_rhba_pyld(fdmi,
1539 (u8 *) ((struct ct_hdr_s *) pyld
1540 + 1));
1541
1542 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1543 FC_CLASS_3, (len + attr_len), &fchs,
1544 bfa_fcs_lport_fdmi_rhba_response, (void *)fdmi,
1545 FC_MAX_PDUSZ, FC_FCCT_TOV);
1546
1547 bfa_sm_send_event(fdmi, FDMISM_EVENT_RHBA_SENT);
1548}
1549
1550static u16
1551bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
1552{
1553 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1554 struct bfa_fcs_fdmi_hba_attr_s hba_attr;
1555 struct bfa_fcs_fdmi_hba_attr_s *fcs_hba_attr = &hba_attr;
1556 struct fdmi_rhba_s *rhba = (struct fdmi_rhba_s *) pyld;
1557 struct fdmi_attr_s *attr;
1558 u8 *curr_ptr;
1559 u16 len, count;
Maggie50444a32010-11-29 18:26:32 -08001560 u16 templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001561
1562 /*
1563 * get hba attributes
1564 */
1565 bfa_fcs_fdmi_get_hbaattr(fdmi, fcs_hba_attr);
1566
1567 rhba->hba_id = bfa_fcs_lport_get_pwwn(port);
Jing Huangba816ea2010-10-18 17:10:50 -07001568 rhba->port_list.num_ports = cpu_to_be32(1);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001569 rhba->port_list.port_entry = bfa_fcs_lport_get_pwwn(port);
1570
1571 len = sizeof(rhba->hba_id) + sizeof(rhba->port_list);
1572
1573 count = 0;
1574 len += sizeof(rhba->hba_attr_blk.attr_count);
1575
1576 /*
1577 * fill out the invididual entries of the HBA attrib Block
1578 */
1579 curr_ptr = (u8 *) &rhba->hba_attr_blk.hba_attr;
1580
1581 /*
1582 * Node Name
1583 */
1584 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001585 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NODENAME);
Maggie50444a32010-11-29 18:26:32 -08001586 templen = sizeof(wwn_t);
1587 memcpy(attr->value, &bfa_fcs_lport_get_nwwn(port), templen);
1588 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1589 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001590 count++;
Maggie50444a32010-11-29 18:26:32 -08001591 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1592 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001593
1594 /*
1595 * Manufacturer
1596 */
1597 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001598 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MANUFACTURER);
Maggie50444a32010-11-29 18:26:32 -08001599 templen = (u16) strlen(fcs_hba_attr->manufacturer);
1600 memcpy(attr->value, fcs_hba_attr->manufacturer, templen);
1601 templen = fc_roundup(templen, sizeof(u32));
1602 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1603 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001604 count++;
Maggie50444a32010-11-29 18:26:32 -08001605 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1606 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001607
1608 /*
1609 * Serial Number
1610 */
1611 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001612 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_SERIALNUM);
Maggie50444a32010-11-29 18:26:32 -08001613 templen = (u16) strlen(fcs_hba_attr->serial_num);
1614 memcpy(attr->value, fcs_hba_attr->serial_num, templen);
1615 templen = fc_roundup(templen, sizeof(u32));
1616 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1617 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001618 count++;
Maggie50444a32010-11-29 18:26:32 -08001619 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1620 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001621
1622 /*
1623 * Model
1624 */
1625 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001626 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL);
Maggie50444a32010-11-29 18:26:32 -08001627 templen = (u16) strlen(fcs_hba_attr->model);
1628 memcpy(attr->value, fcs_hba_attr->model, templen);
1629 templen = fc_roundup(templen, sizeof(u32));
1630 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1631 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001632 count++;
Maggie50444a32010-11-29 18:26:32 -08001633 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1634 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001635
1636 /*
1637 * Model Desc
1638 */
1639 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001640 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL_DESC);
Maggie50444a32010-11-29 18:26:32 -08001641 templen = (u16) strlen(fcs_hba_attr->model_desc);
1642 memcpy(attr->value, fcs_hba_attr->model_desc, templen);
1643 templen = fc_roundup(templen, sizeof(u32));
1644 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1645 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001646 count++;
Maggie50444a32010-11-29 18:26:32 -08001647 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1648 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001649
1650 /*
1651 * H/W Version
1652 */
1653 if (fcs_hba_attr->hw_version[0] != '\0') {
1654 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001655 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_HW_VERSION);
Maggie50444a32010-11-29 18:26:32 -08001656 templen = (u16) strlen(fcs_hba_attr->hw_version);
1657 memcpy(attr->value, fcs_hba_attr->hw_version, templen);
1658 templen = fc_roundup(templen, sizeof(u32));
1659 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1660 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001661 count++;
Maggie50444a32010-11-29 18:26:32 -08001662 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1663 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001664 }
1665
1666 /*
1667 * Driver Version
1668 */
1669 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001670 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_DRIVER_VERSION);
Maggie50444a32010-11-29 18:26:32 -08001671 templen = (u16) strlen(fcs_hba_attr->driver_version);
1672 memcpy(attr->value, fcs_hba_attr->driver_version, templen);
1673 templen = fc_roundup(templen, sizeof(u32));
1674 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1675 len += templen;;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001676 count++;
Maggie50444a32010-11-29 18:26:32 -08001677 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1678 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001679
1680 /*
1681 * Option Rom Version
1682 */
1683 if (fcs_hba_attr->option_rom_ver[0] != '\0') {
1684 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001685 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_ROM_VERSION);
Maggie50444a32010-11-29 18:26:32 -08001686 templen = (u16) strlen(fcs_hba_attr->option_rom_ver);
1687 memcpy(attr->value, fcs_hba_attr->option_rom_ver, templen);
1688 templen = fc_roundup(templen, sizeof(u32));
1689 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1690 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001691 count++;
Maggie50444a32010-11-29 18:26:32 -08001692 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1693 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001694 }
1695
1696 /*
1697 * f/w Version = driver version
1698 */
1699 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001700 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_FW_VERSION);
Maggie50444a32010-11-29 18:26:32 -08001701 templen = (u16) strlen(fcs_hba_attr->driver_version);
1702 memcpy(attr->value, fcs_hba_attr->driver_version, templen);
1703 templen = fc_roundup(templen, sizeof(u32));
1704 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1705 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001706 count++;
Maggie50444a32010-11-29 18:26:32 -08001707 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1708 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001709
1710 /*
1711 * OS Name
1712 */
1713 if (fcs_hba_attr->os_name[0] != '\0') {
1714 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001715 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_OS_NAME);
Maggie50444a32010-11-29 18:26:32 -08001716 templen = (u16) strlen(fcs_hba_attr->os_name);
1717 memcpy(attr->value, fcs_hba_attr->os_name, templen);
1718 templen = fc_roundup(templen, sizeof(u32));
1719 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1720 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001721 count++;
Maggie50444a32010-11-29 18:26:32 -08001722 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1723 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001724 }
1725
1726 /*
1727 * MAX_CT_PAYLOAD
1728 */
1729 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001730 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MAX_CT);
Maggie50444a32010-11-29 18:26:32 -08001731 templen = sizeof(fcs_hba_attr->max_ct_pyld);
1732 memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, templen);
1733 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001734 count++;
Maggie50444a32010-11-29 18:26:32 -08001735 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1736 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001737
1738 /*
1739 * Update size of payload
1740 */
Jing Huang5fbe25c2010-10-18 17:17:23 -07001741 len += ((sizeof(attr->type) + sizeof(attr->len)) * count);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001742
Jing Huangba816ea2010-10-18 17:10:50 -07001743 rhba->hba_attr_blk.attr_count = cpu_to_be32(count);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001744 return len;
1745}
1746
1747static void
1748bfa_fcs_lport_fdmi_rhba_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
1749 void *cbarg, bfa_status_t req_status,
1750 u32 rsp_len, u32 resid_len,
1751 struct fchs_s *rsp_fchs)
1752{
1753 struct bfa_fcs_lport_fdmi_s *fdmi =
1754 (struct bfa_fcs_lport_fdmi_s *) cbarg;
1755 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1756 struct ct_hdr_s *cthdr = NULL;
1757
1758 bfa_trc(port->fcs, port->port_cfg.pwwn);
1759
1760 /*
1761 * Sanity Checks
1762 */
1763 if (req_status != BFA_STATUS_OK) {
1764 bfa_trc(port->fcs, req_status);
1765 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
1766 return;
1767 }
1768
1769 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
Jing Huangba816ea2010-10-18 17:10:50 -07001770 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001771
1772 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
1773 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
1774 return;
1775 }
1776
1777 bfa_trc(port->fcs, cthdr->reason_code);
1778 bfa_trc(port->fcs, cthdr->exp_code);
1779 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
1780}
1781
Jing Huang5fbe25c2010-10-18 17:17:23 -07001782/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001783* RPRT : Register Port
1784 */
1785static void
1786bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1787{
1788 struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
1789 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1790 struct fchs_s fchs;
1791 u16 len, attr_len;
1792 struct bfa_fcxp_s *fcxp;
1793 u8 *pyld;
1794
1795 bfa_trc(port->fcs, port->port_cfg.pwwn);
1796
1797 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1798 if (!fcxp) {
1799 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
1800 bfa_fcs_lport_fdmi_send_rprt, fdmi);
1801 return;
1802 }
1803 fdmi->fcxp = fcxp;
1804
1805 pyld = bfa_fcxp_get_reqbuf(fcxp);
Jing Huang6a18b162010-10-18 17:08:54 -07001806 memset(pyld, 0, FC_MAX_PDUSZ);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001807
1808 len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
1809 FDMI_RPRT);
1810
1811 attr_len =
1812 bfa_fcs_lport_fdmi_build_rprt_pyld(fdmi,
1813 (u8 *) ((struct ct_hdr_s *) pyld
1814 + 1));
1815
1816 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1817 FC_CLASS_3, len + attr_len, &fchs,
1818 bfa_fcs_lport_fdmi_rprt_response, (void *)fdmi,
1819 FC_MAX_PDUSZ, FC_FCCT_TOV);
1820
1821 bfa_sm_send_event(fdmi, FDMISM_EVENT_RPRT_SENT);
1822}
1823
Jing Huang5fbe25c2010-10-18 17:17:23 -07001824/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001825 * This routine builds Port Attribute Block that used in RPA, RPRT commands.
1826 */
1827static u16
1828bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi,
1829 u8 *pyld)
1830{
1831 struct bfa_fcs_fdmi_port_attr_s fcs_port_attr;
1832 struct fdmi_port_attr_s *port_attrib = (struct fdmi_port_attr_s *) pyld;
1833 struct fdmi_attr_s *attr;
1834 u8 *curr_ptr;
1835 u16 len;
1836 u8 count = 0;
Maggie50444a32010-11-29 18:26:32 -08001837 u16 templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001838
1839 /*
1840 * get port attributes
1841 */
1842 bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr);
1843
1844 len = sizeof(port_attrib->attr_count);
1845
1846 /*
1847 * fill out the invididual entries
1848 */
1849 curr_ptr = (u8 *) &port_attrib->port_attr;
1850
1851 /*
1852 * FC4 Types
1853 */
1854 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001855 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FC4_TYPES);
Maggie50444a32010-11-29 18:26:32 -08001856 templen = sizeof(fcs_port_attr.supp_fc4_types);
1857 memcpy(attr->value, fcs_port_attr.supp_fc4_types, templen);
1858 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1859 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001860 ++count;
1861 attr->len =
Maggie50444a32010-11-29 18:26:32 -08001862 cpu_to_be16(templen + sizeof(attr->type) +
1863 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001864
1865 /*
1866 * Supported Speed
1867 */
1868 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001869 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_SUPP_SPEED);
Maggie50444a32010-11-29 18:26:32 -08001870 templen = sizeof(fcs_port_attr.supp_speed);
1871 memcpy(attr->value, &fcs_port_attr.supp_speed, templen);
1872 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1873 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001874 ++count;
1875 attr->len =
Maggie50444a32010-11-29 18:26:32 -08001876 cpu_to_be16(templen + sizeof(attr->type) +
1877 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001878
1879 /*
1880 * current Port Speed
1881 */
1882 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001883 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_SPEED);
Maggie50444a32010-11-29 18:26:32 -08001884 templen = sizeof(fcs_port_attr.curr_speed);
1885 memcpy(attr->value, &fcs_port_attr.curr_speed, templen);
1886 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1887 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001888 ++count;
Maggie50444a32010-11-29 18:26:32 -08001889 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1890 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001891
1892 /*
1893 * max frame size
1894 */
1895 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001896 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FRAME_SIZE);
Maggie50444a32010-11-29 18:26:32 -08001897 templen = sizeof(fcs_port_attr.max_frm_size);
1898 memcpy(attr->value, &fcs_port_attr.max_frm_size, templen);
1899 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1900 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001901 ++count;
Maggie50444a32010-11-29 18:26:32 -08001902 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1903 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001904
1905 /*
1906 * OS Device Name
1907 */
1908 if (fcs_port_attr.os_device_name[0] != '\0') {
1909 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001910 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_DEV_NAME);
Maggie50444a32010-11-29 18:26:32 -08001911 templen = (u16) strlen(fcs_port_attr.os_device_name);
1912 memcpy(attr->value, fcs_port_attr.os_device_name, templen);
1913 templen = fc_roundup(templen, sizeof(u32));
1914 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1915 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001916 ++count;
Maggie50444a32010-11-29 18:26:32 -08001917 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1918 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001919 }
1920 /*
1921 * Host Name
1922 */
1923 if (fcs_port_attr.host_name[0] != '\0') {
1924 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001925 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_HOST_NAME);
Maggie50444a32010-11-29 18:26:32 -08001926 templen = (u16) strlen(fcs_port_attr.host_name);
1927 memcpy(attr->value, fcs_port_attr.host_name, templen);
1928 templen = fc_roundup(templen, sizeof(u32));
1929 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1930 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001931 ++count;
Maggie50444a32010-11-29 18:26:32 -08001932 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1933 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001934 }
1935
1936 /*
1937 * Update size of payload
1938 */
Jing Huangba816ea2010-10-18 17:10:50 -07001939 port_attrib->attr_count = cpu_to_be32(count);
Jing Huang5fbe25c2010-10-18 17:17:23 -07001940 len += ((sizeof(attr->type) + sizeof(attr->len)) * count);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001941 return len;
1942}
1943
1944static u16
1945bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
1946{
1947 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1948 struct fdmi_rprt_s *rprt = (struct fdmi_rprt_s *) pyld;
1949 u16 len;
1950
1951 rprt->hba_id = bfa_fcs_lport_get_pwwn(bfa_fcs_get_base_port(port->fcs));
1952 rprt->port_name = bfa_fcs_lport_get_pwwn(port);
1953
1954 len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
1955 (u8 *) &rprt->port_attr_blk);
1956
1957 len += sizeof(rprt->hba_id) + sizeof(rprt->port_name);
1958
1959 return len;
1960}
1961
1962static void
1963bfa_fcs_lport_fdmi_rprt_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
1964 void *cbarg, bfa_status_t req_status,
1965 u32 rsp_len, u32 resid_len,
1966 struct fchs_s *rsp_fchs)
1967{
1968 struct bfa_fcs_lport_fdmi_s *fdmi =
1969 (struct bfa_fcs_lport_fdmi_s *) cbarg;
1970 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1971 struct ct_hdr_s *cthdr = NULL;
1972
1973 bfa_trc(port->fcs, port->port_cfg.pwwn);
1974
1975 /*
1976 * Sanity Checks
1977 */
1978 if (req_status != BFA_STATUS_OK) {
1979 bfa_trc(port->fcs, req_status);
1980 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
1981 return;
1982 }
1983
1984 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
Jing Huangba816ea2010-10-18 17:10:50 -07001985 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001986
1987 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
1988 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
1989 return;
1990 }
1991
1992 bfa_trc(port->fcs, cthdr->reason_code);
1993 bfa_trc(port->fcs, cthdr->exp_code);
1994 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
1995}
1996
Jing Huang5fbe25c2010-10-18 17:17:23 -07001997/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001998* RPA : Register Port Attributes.
1999 */
2000static void
2001bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2002{
2003 struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
2004 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2005 struct fchs_s fchs;
2006 u16 len, attr_len;
2007 struct bfa_fcxp_s *fcxp;
2008 u8 *pyld;
2009
2010 bfa_trc(port->fcs, port->port_cfg.pwwn);
2011
2012 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2013 if (!fcxp) {
2014 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
2015 bfa_fcs_lport_fdmi_send_rpa, fdmi);
2016 return;
2017 }
2018 fdmi->fcxp = fcxp;
2019
2020 pyld = bfa_fcxp_get_reqbuf(fcxp);
Jing Huang6a18b162010-10-18 17:08:54 -07002021 memset(pyld, 0, FC_MAX_PDUSZ);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002022
2023 len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
2024 FDMI_RPA);
2025
Jing Huang5fbe25c2010-10-18 17:17:23 -07002026 attr_len = bfa_fcs_lport_fdmi_build_rpa_pyld(fdmi,
2027 (u8 *) ((struct ct_hdr_s *) pyld + 1));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002028
2029 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2030 FC_CLASS_3, len + attr_len, &fchs,
2031 bfa_fcs_lport_fdmi_rpa_response, (void *)fdmi,
2032 FC_MAX_PDUSZ, FC_FCCT_TOV);
2033
2034 bfa_sm_send_event(fdmi, FDMISM_EVENT_RPA_SENT);
2035}
2036
2037static u16
2038bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
2039{
2040 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2041 struct fdmi_rpa_s *rpa = (struct fdmi_rpa_s *) pyld;
2042 u16 len;
2043
2044 rpa->port_name = bfa_fcs_lport_get_pwwn(port);
2045
2046 len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
2047 (u8 *) &rpa->port_attr_blk);
2048
2049 len += sizeof(rpa->port_name);
2050
2051 return len;
2052}
2053
2054static void
2055bfa_fcs_lport_fdmi_rpa_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2056 void *cbarg, bfa_status_t req_status, u32 rsp_len,
2057 u32 resid_len, struct fchs_s *rsp_fchs)
2058{
2059 struct bfa_fcs_lport_fdmi_s *fdmi =
2060 (struct bfa_fcs_lport_fdmi_s *) cbarg;
2061 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2062 struct ct_hdr_s *cthdr = NULL;
2063
2064 bfa_trc(port->fcs, port->port_cfg.pwwn);
2065
2066 /*
2067 * Sanity Checks
2068 */
2069 if (req_status != BFA_STATUS_OK) {
2070 bfa_trc(port->fcs, req_status);
2071 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2072 return;
2073 }
2074
2075 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
Jing Huangba816ea2010-10-18 17:10:50 -07002076 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002077
2078 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2079 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
2080 return;
2081 }
2082
2083 bfa_trc(port->fcs, cthdr->reason_code);
2084 bfa_trc(port->fcs, cthdr->exp_code);
2085 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2086}
2087
2088static void
2089bfa_fcs_lport_fdmi_timeout(void *arg)
2090{
2091 struct bfa_fcs_lport_fdmi_s *fdmi = (struct bfa_fcs_lport_fdmi_s *) arg;
2092
2093 bfa_sm_send_event(fdmi, FDMISM_EVENT_TIMEOUT);
2094}
2095
Maggie52f94b62010-11-29 18:21:32 -08002096static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002097bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
2098 struct bfa_fcs_fdmi_hba_attr_s *hba_attr)
2099{
2100 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2101 struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info;
2102
Jing Huang6a18b162010-10-18 17:08:54 -07002103 memset(hba_attr, 0, sizeof(struct bfa_fcs_fdmi_hba_attr_s));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002104
2105 bfa_ioc_get_adapter_manufacturer(&port->fcs->bfa->ioc,
2106 hba_attr->manufacturer);
2107 bfa_ioc_get_adapter_serial_num(&port->fcs->bfa->ioc,
2108 hba_attr->serial_num);
2109 bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc,
2110 hba_attr->model);
2111 bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc,
2112 hba_attr->model_desc);
2113 bfa_ioc_get_pci_chip_rev(&port->fcs->bfa->ioc,
2114 hba_attr->hw_version);
2115 bfa_ioc_get_adapter_optrom_ver(&port->fcs->bfa->ioc,
2116 hba_attr->option_rom_ver);
2117 bfa_ioc_get_adapter_fw_ver(&port->fcs->bfa->ioc,
2118 hba_attr->fw_version);
2119
2120 strncpy(hba_attr->driver_version, (char *)driver_info->version,
2121 sizeof(hba_attr->driver_version));
2122
2123 strncpy(hba_attr->os_name, driver_info->host_os_name,
2124 sizeof(hba_attr->os_name));
2125
2126 /*
2127 * If there is a patch level, append it
2128 * to the os name along with a separator
2129 */
2130 if (driver_info->host_os_patch[0] != '\0') {
2131 strncat(hba_attr->os_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
2132 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
2133 strncat(hba_attr->os_name, driver_info->host_os_patch,
2134 sizeof(driver_info->host_os_patch));
2135 }
2136
Jing Huangba816ea2010-10-18 17:10:50 -07002137 hba_attr->max_ct_pyld = cpu_to_be32(FC_MAX_PDUSZ);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002138}
2139
Maggie52f94b62010-11-29 18:21:32 -08002140static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002141bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
2142 struct bfa_fcs_fdmi_port_attr_s *port_attr)
2143{
2144 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2145 struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info;
2146 struct bfa_port_attr_s pport_attr;
2147
Jing Huang6a18b162010-10-18 17:08:54 -07002148 memset(port_attr, 0, sizeof(struct bfa_fcs_fdmi_port_attr_s));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002149
2150 /*
2151 * get pport attributes from hal
2152 */
2153 bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
2154
2155 /*
2156 * get FC4 type Bitmask
2157 */
2158 fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->supp_fc4_types);
2159
2160 /*
2161 * Supported Speeds
2162 */
Jing Huangba816ea2010-10-18 17:10:50 -07002163 port_attr->supp_speed = cpu_to_be32(BFA_FCS_FDMI_SUPORTED_SPEEDS);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002164
2165 /*
2166 * Current Speed
2167 */
Jing Huangba816ea2010-10-18 17:10:50 -07002168 port_attr->curr_speed = cpu_to_be32(pport_attr.speed);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002169
2170 /*
2171 * Max PDU Size.
2172 */
Jing Huangba816ea2010-10-18 17:10:50 -07002173 port_attr->max_frm_size = cpu_to_be32(FC_MAX_PDUSZ);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002174
2175 /*
2176 * OS device Name
2177 */
2178 strncpy(port_attr->os_device_name, (char *)driver_info->os_device_name,
2179 sizeof(port_attr->os_device_name));
2180
2181 /*
2182 * Host name
2183 */
2184 strncpy(port_attr->host_name, (char *)driver_info->host_machine_name,
2185 sizeof(port_attr->host_name));
Jing Huang7725ccf2009-09-23 17:46:15 -07002186
2187}
2188
2189
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002190void
2191bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s *ms)
2192{
2193 struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2194
2195 fdmi->ms = ms;
2196 if (ms->port->fcs->fdmi_enabled)
2197 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
2198 else
2199 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_disabled);
2200}
2201
2202void
2203bfa_fcs_lport_fdmi_offline(struct bfa_fcs_lport_ms_s *ms)
2204{
2205 struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2206
2207 fdmi->ms = ms;
2208 bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_OFFLINE);
2209}
2210
2211void
2212bfa_fcs_lport_fdmi_online(struct bfa_fcs_lport_ms_s *ms)
2213{
2214 struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2215
2216 fdmi->ms = ms;
2217 bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_ONLINE);
2218}
2219
2220#define BFA_FCS_MS_CMD_MAX_RETRIES 2
2221
2222/*
2223 * forward declarations
2224 */
2225static void bfa_fcs_lport_ms_send_plogi(void *ms_cbarg,
2226 struct bfa_fcxp_s *fcxp_alloced);
2227static void bfa_fcs_lport_ms_timeout(void *arg);
2228static void bfa_fcs_lport_ms_plogi_response(void *fcsarg,
2229 struct bfa_fcxp_s *fcxp,
2230 void *cbarg,
2231 bfa_status_t req_status,
2232 u32 rsp_len,
2233 u32 resid_len,
2234 struct fchs_s *rsp_fchs);
2235
2236static void bfa_fcs_lport_ms_send_gmal(void *ms_cbarg,
2237 struct bfa_fcxp_s *fcxp_alloced);
2238static void bfa_fcs_lport_ms_gmal_response(void *fcsarg,
2239 struct bfa_fcxp_s *fcxp,
2240 void *cbarg,
2241 bfa_status_t req_status,
2242 u32 rsp_len,
2243 u32 resid_len,
2244 struct fchs_s *rsp_fchs);
2245static void bfa_fcs_lport_ms_send_gfn(void *ms_cbarg,
2246 struct bfa_fcxp_s *fcxp_alloced);
2247static void bfa_fcs_lport_ms_gfn_response(void *fcsarg,
2248 struct bfa_fcxp_s *fcxp,
2249 void *cbarg,
2250 bfa_status_t req_status,
2251 u32 rsp_len,
2252 u32 resid_len,
2253 struct fchs_s *rsp_fchs);
Jing Huang5fbe25c2010-10-18 17:17:23 -07002254/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002255 * fcs_ms_sm FCS MS state machine
2256 */
2257
Jing Huang5fbe25c2010-10-18 17:17:23 -07002258/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002259 * MS State Machine events
2260 */
2261enum port_ms_event {
2262 MSSM_EVENT_PORT_ONLINE = 1,
2263 MSSM_EVENT_PORT_OFFLINE = 2,
2264 MSSM_EVENT_RSP_OK = 3,
2265 MSSM_EVENT_RSP_ERROR = 4,
2266 MSSM_EVENT_TIMEOUT = 5,
2267 MSSM_EVENT_FCXP_SENT = 6,
2268 MSSM_EVENT_PORT_FABRIC_RSCN = 7
2269};
2270
2271static void bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
2272 enum port_ms_event event);
2273static void bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
2274 enum port_ms_event event);
2275static void bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
2276 enum port_ms_event event);
2277static void bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
2278 enum port_ms_event event);
2279static void bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
2280 enum port_ms_event event);
2281static void bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
2282 enum port_ms_event event);
2283static void bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
2284 enum port_ms_event event);
2285static void bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
2286 enum port_ms_event event);
2287static void bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
2288 enum port_ms_event event);
2289static void bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
2290 enum port_ms_event event);
2291static void bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
2292 enum port_ms_event event);
Jing Huang5fbe25c2010-10-18 17:17:23 -07002293/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002294 * Start in offline state - awaiting NS to send start.
2295 */
2296static void
2297bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
2298 enum port_ms_event event)
2299{
2300 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2301 bfa_trc(ms->port->fcs, event);
2302
2303 switch (event) {
2304 case MSSM_EVENT_PORT_ONLINE:
2305 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
2306 bfa_fcs_lport_ms_send_plogi(ms, NULL);
2307 break;
2308
2309 case MSSM_EVENT_PORT_OFFLINE:
2310 break;
2311
2312 default:
2313 bfa_sm_fault(ms->port->fcs, event);
2314 }
2315}
2316
2317static void
2318bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
2319 enum port_ms_event event)
2320{
2321 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2322 bfa_trc(ms->port->fcs, event);
2323
2324 switch (event) {
2325 case MSSM_EVENT_FCXP_SENT:
2326 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi);
2327 break;
2328
2329 case MSSM_EVENT_PORT_OFFLINE:
2330 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2331 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2332 &ms->fcxp_wqe);
2333 break;
2334
2335 default:
2336 bfa_sm_fault(ms->port->fcs, event);
2337 }
2338}
2339
2340static void
2341bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
2342 enum port_ms_event event)
2343{
2344 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2345 bfa_trc(ms->port->fcs, event);
2346
2347 switch (event) {
2348 case MSSM_EVENT_RSP_ERROR:
2349 /*
2350 * Start timer for a delayed retry
2351 */
2352 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_retry);
2353 ms->port->stats.ms_retries++;
2354 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2355 &ms->timer, bfa_fcs_lport_ms_timeout, ms,
2356 BFA_FCS_RETRY_TIMEOUT);
2357 break;
2358
2359 case MSSM_EVENT_RSP_OK:
2360 /*
2361 * since plogi is done, now invoke MS related sub-modules
2362 */
2363 bfa_fcs_lport_fdmi_online(ms);
2364
Jing Huang5fbe25c2010-10-18 17:17:23 -07002365 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002366 * if this is a Vport, go to online state.
2367 */
2368 if (ms->port->vport) {
2369 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2370 break;
2371 }
2372
2373 /*
2374 * For a base port we need to get the
2375 * switch's IP address.
2376 */
2377 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
2378 bfa_fcs_lport_ms_send_gmal(ms, NULL);
2379 break;
2380
2381 case MSSM_EVENT_PORT_OFFLINE:
2382 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2383 bfa_fcxp_discard(ms->fcxp);
2384 break;
2385
2386 default:
2387 bfa_sm_fault(ms->port->fcs, event);
2388 }
2389}
2390
2391static void
2392bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
2393 enum port_ms_event event)
2394{
2395 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2396 bfa_trc(ms->port->fcs, event);
2397
2398 switch (event) {
2399 case MSSM_EVENT_TIMEOUT:
2400 /*
2401 * Retry Timer Expired. Re-send
2402 */
2403 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
2404 bfa_fcs_lport_ms_send_plogi(ms, NULL);
2405 break;
2406
2407 case MSSM_EVENT_PORT_OFFLINE:
2408 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2409 bfa_timer_stop(&ms->timer);
2410 break;
2411
2412 default:
2413 bfa_sm_fault(ms->port->fcs, event);
2414 }
2415}
2416
2417static void
2418bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
2419 enum port_ms_event event)
2420{
2421 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2422 bfa_trc(ms->port->fcs, event);
2423
2424 switch (event) {
2425 case MSSM_EVENT_PORT_OFFLINE:
2426 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2427 break;
2428
2429 case MSSM_EVENT_PORT_FABRIC_RSCN:
2430 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2431 ms->retry_cnt = 0;
2432 bfa_fcs_lport_ms_send_gfn(ms, NULL);
2433 break;
2434
2435 default:
2436 bfa_sm_fault(ms->port->fcs, event);
2437 }
2438}
2439
2440static void
2441bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
2442 enum port_ms_event event)
2443{
2444 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2445 bfa_trc(ms->port->fcs, event);
2446
2447 switch (event) {
2448 case MSSM_EVENT_FCXP_SENT:
2449 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal);
2450 break;
2451
2452 case MSSM_EVENT_PORT_OFFLINE:
2453 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2454 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2455 &ms->fcxp_wqe);
2456 break;
2457
2458 default:
2459 bfa_sm_fault(ms->port->fcs, event);
2460 }
2461}
2462
2463static void
2464bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
2465 enum port_ms_event event)
2466{
2467 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2468 bfa_trc(ms->port->fcs, event);
2469
2470 switch (event) {
2471 case MSSM_EVENT_RSP_ERROR:
2472 /*
2473 * Start timer for a delayed retry
2474 */
2475 if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
2476 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_retry);
2477 ms->port->stats.ms_retries++;
2478 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2479 &ms->timer, bfa_fcs_lport_ms_timeout, ms,
2480 BFA_FCS_RETRY_TIMEOUT);
2481 } else {
2482 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2483 bfa_fcs_lport_ms_send_gfn(ms, NULL);
2484 ms->retry_cnt = 0;
2485 }
2486 break;
2487
2488 case MSSM_EVENT_RSP_OK:
2489 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2490 bfa_fcs_lport_ms_send_gfn(ms, NULL);
2491 break;
2492
2493 case MSSM_EVENT_PORT_OFFLINE:
2494 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2495 bfa_fcxp_discard(ms->fcxp);
2496 break;
2497
2498 default:
2499 bfa_sm_fault(ms->port->fcs, event);
2500 }
2501}
2502
2503static void
2504bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
2505 enum port_ms_event event)
2506{
2507 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2508 bfa_trc(ms->port->fcs, event);
2509
2510 switch (event) {
2511 case MSSM_EVENT_TIMEOUT:
2512 /*
2513 * Retry Timer Expired. Re-send
2514 */
2515 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
2516 bfa_fcs_lport_ms_send_gmal(ms, NULL);
2517 break;
2518
2519 case MSSM_EVENT_PORT_OFFLINE:
2520 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2521 bfa_timer_stop(&ms->timer);
2522 break;
2523
2524 default:
2525 bfa_sm_fault(ms->port->fcs, event);
2526 }
2527}
Jing Huang5fbe25c2010-10-18 17:17:23 -07002528/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002529 * ms_pvt MS local functions
2530 */
2531
2532static void
2533bfa_fcs_lport_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2534{
2535 struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
2536 bfa_fcs_lport_t *port = ms->port;
2537 struct fchs_s fchs;
2538 int len;
2539 struct bfa_fcxp_s *fcxp;
2540
2541 bfa_trc(port->fcs, port->pid);
2542
2543 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2544 if (!fcxp) {
2545 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
2546 bfa_fcs_lport_ms_send_gmal, ms);
2547 return;
2548 }
2549 ms->fcxp = fcxp;
2550
2551 len = fc_gmal_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2552 bfa_fcs_lport_get_fcid(port),
Maggie Zhangf7f73812010-12-09 19:08:43 -08002553 port->fabric->lps->pr_nwwn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002554
2555 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2556 FC_CLASS_3, len, &fchs,
2557 bfa_fcs_lport_ms_gmal_response, (void *)ms,
2558 FC_MAX_PDUSZ, FC_FCCT_TOV);
2559
2560 bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
2561}
2562
2563static void
2564bfa_fcs_lport_ms_gmal_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2565 void *cbarg, bfa_status_t req_status,
2566 u32 rsp_len, u32 resid_len,
2567 struct fchs_s *rsp_fchs)
2568{
2569 struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
2570 bfa_fcs_lport_t *port = ms->port;
2571 struct ct_hdr_s *cthdr = NULL;
2572 struct fcgs_gmal_resp_s *gmal_resp;
2573 struct fcgs_gmal_entry_s *gmal_entry;
2574 u32 num_entries;
2575 u8 *rsp_str;
2576
2577 bfa_trc(port->fcs, req_status);
2578 bfa_trc(port->fcs, port->port_cfg.pwwn);
2579
2580 /*
2581 * Sanity Checks
2582 */
2583 if (req_status != BFA_STATUS_OK) {
2584 bfa_trc(port->fcs, req_status);
2585 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2586 return;
2587 }
2588
2589 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
Jing Huangba816ea2010-10-18 17:10:50 -07002590 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002591
2592 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2593 gmal_resp = (struct fcgs_gmal_resp_s *)(cthdr + 1);
2594
Jing Huangba816ea2010-10-18 17:10:50 -07002595 num_entries = be32_to_cpu(gmal_resp->ms_len);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002596 if (num_entries == 0) {
2597 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2598 return;
2599 }
2600 /*
2601 * The response could contain multiple Entries.
2602 * Entries for SNMP interface, etc.
2603 * We look for the entry with a telnet prefix.
2604 * First "http://" entry refers to IP addr
2605 */
2606
2607 gmal_entry = (struct fcgs_gmal_entry_s *)gmal_resp->ms_ma;
2608 while (num_entries > 0) {
2609 if (strncmp(gmal_entry->prefix,
2610 CT_GMAL_RESP_PREFIX_HTTP,
2611 sizeof(gmal_entry->prefix)) == 0) {
2612
2613 /*
2614 * if the IP address is terminating with a '/',
2615 * remove it.
2616 * Byte 0 consists of the length of the string.
2617 */
2618 rsp_str = &(gmal_entry->prefix[0]);
2619 if (rsp_str[gmal_entry->len-1] == '/')
2620 rsp_str[gmal_entry->len-1] = 0;
2621
2622 /* copy IP Address to fabric */
2623 strncpy(bfa_fcs_lport_get_fabric_ipaddr(port),
2624 gmal_entry->ip_addr,
2625 BFA_FCS_FABRIC_IPADDR_SZ);
2626 break;
2627 } else {
2628 --num_entries;
2629 ++gmal_entry;
2630 }
2631 }
2632
2633 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
2634 return;
2635 }
2636
2637 bfa_trc(port->fcs, cthdr->reason_code);
2638 bfa_trc(port->fcs, cthdr->exp_code);
2639 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2640}
2641
2642static void
2643bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
2644 enum port_ms_event event)
2645{
2646 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2647 bfa_trc(ms->port->fcs, event);
2648
2649 switch (event) {
2650 case MSSM_EVENT_FCXP_SENT:
2651 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn);
2652 break;
2653
2654 case MSSM_EVENT_PORT_OFFLINE:
2655 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2656 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2657 &ms->fcxp_wqe);
2658 break;
2659
2660 default:
2661 bfa_sm_fault(ms->port->fcs, event);
2662 }
2663}
2664
2665static void
2666bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
2667 enum port_ms_event event)
2668{
2669 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2670 bfa_trc(ms->port->fcs, event);
2671
2672 switch (event) {
2673 case MSSM_EVENT_RSP_ERROR:
2674 /*
2675 * Start timer for a delayed retry
2676 */
2677 if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
2678 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_retry);
2679 ms->port->stats.ms_retries++;
2680 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2681 &ms->timer, bfa_fcs_lport_ms_timeout, ms,
2682 BFA_FCS_RETRY_TIMEOUT);
2683 } else {
2684 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2685 ms->retry_cnt = 0;
2686 }
2687 break;
2688
2689 case MSSM_EVENT_RSP_OK:
2690 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2691 break;
2692
2693 case MSSM_EVENT_PORT_OFFLINE:
2694 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2695 bfa_fcxp_discard(ms->fcxp);
2696 break;
2697
2698 default:
2699 bfa_sm_fault(ms->port->fcs, event);
2700 }
2701}
2702
2703static void
2704bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
2705 enum port_ms_event event)
2706{
2707 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2708 bfa_trc(ms->port->fcs, event);
2709
2710 switch (event) {
2711 case MSSM_EVENT_TIMEOUT:
2712 /*
2713 * Retry Timer Expired. Re-send
2714 */
2715 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2716 bfa_fcs_lport_ms_send_gfn(ms, NULL);
2717 break;
2718
2719 case MSSM_EVENT_PORT_OFFLINE:
2720 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2721 bfa_timer_stop(&ms->timer);
2722 break;
2723
2724 default:
2725 bfa_sm_fault(ms->port->fcs, event);
2726 }
2727}
Jing Huang5fbe25c2010-10-18 17:17:23 -07002728/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002729 * ms_pvt MS local functions
2730 */
2731
2732static void
2733bfa_fcs_lport_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2734{
2735 struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
2736 bfa_fcs_lport_t *port = ms->port;
2737 struct fchs_s fchs;
2738 int len;
2739 struct bfa_fcxp_s *fcxp;
2740
2741 bfa_trc(port->fcs, port->pid);
2742
2743 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2744 if (!fcxp) {
2745 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
2746 bfa_fcs_lport_ms_send_gfn, ms);
2747 return;
2748 }
2749 ms->fcxp = fcxp;
2750
2751 len = fc_gfn_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2752 bfa_fcs_lport_get_fcid(port),
Maggie Zhangf7f73812010-12-09 19:08:43 -08002753 port->fabric->lps->pr_nwwn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002754
2755 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2756 FC_CLASS_3, len, &fchs,
2757 bfa_fcs_lport_ms_gfn_response, (void *)ms,
2758 FC_MAX_PDUSZ, FC_FCCT_TOV);
2759
2760 bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
2761}
2762
2763static void
2764bfa_fcs_lport_ms_gfn_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2765 void *cbarg, bfa_status_t req_status, u32 rsp_len,
2766 u32 resid_len, struct fchs_s *rsp_fchs)
2767{
2768 struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
2769 bfa_fcs_lport_t *port = ms->port;
2770 struct ct_hdr_s *cthdr = NULL;
2771 wwn_t *gfn_resp;
2772
2773 bfa_trc(port->fcs, req_status);
2774 bfa_trc(port->fcs, port->port_cfg.pwwn);
2775
2776 /*
2777 * Sanity Checks
2778 */
2779 if (req_status != BFA_STATUS_OK) {
2780 bfa_trc(port->fcs, req_status);
2781 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2782 return;
2783 }
2784
2785 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
Jing Huangba816ea2010-10-18 17:10:50 -07002786 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002787
2788 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2789 gfn_resp = (wwn_t *)(cthdr + 1);
2790 /* check if it has actually changed */
2791 if ((memcmp((void *)&bfa_fcs_lport_get_fabric_name(port),
2792 gfn_resp, sizeof(wwn_t)) != 0)) {
2793 bfa_fcs_fabric_set_fabric_name(port->fabric, *gfn_resp);
2794 }
2795 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
2796 return;
2797 }
2798
2799 bfa_trc(port->fcs, cthdr->reason_code);
2800 bfa_trc(port->fcs, cthdr->exp_code);
2801 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2802}
2803
Jing Huang5fbe25c2010-10-18 17:17:23 -07002804/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002805 * ms_pvt MS local functions
2806 */
2807
2808static void
2809bfa_fcs_lport_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2810{
2811 struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
2812 struct bfa_fcs_lport_s *port = ms->port;
2813 struct fchs_s fchs;
2814 int len;
2815 struct bfa_fcxp_s *fcxp;
2816
2817 bfa_trc(port->fcs, port->pid);
2818
2819 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2820 if (!fcxp) {
2821 port->stats.ms_plogi_alloc_wait++;
2822 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
2823 bfa_fcs_lport_ms_send_plogi, ms);
2824 return;
2825 }
2826 ms->fcxp = fcxp;
2827
2828 len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
Maggie Zhangf16a1752010-12-09 19:12:32 -08002829 bfa_hton3b(FC_MGMT_SERVER),
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002830 bfa_fcs_lport_get_fcid(port), 0,
2831 port->port_cfg.pwwn, port->port_cfg.nwwn,
2832 bfa_fcport_get_maxfrsize(port->fcs->bfa));
2833
2834 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2835 FC_CLASS_3, len, &fchs,
2836 bfa_fcs_lport_ms_plogi_response, (void *)ms,
2837 FC_MAX_PDUSZ, FC_ELS_TOV);
2838
2839 port->stats.ms_plogi_sent++;
2840 bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
2841}
2842
2843static void
2844bfa_fcs_lport_ms_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2845 void *cbarg, bfa_status_t req_status,
2846 u32 rsp_len, u32 resid_len, struct fchs_s *rsp_fchs)
2847{
2848 struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
2849 struct bfa_fcs_lport_s *port = ms->port;
2850 struct fc_els_cmd_s *els_cmd;
2851 struct fc_ls_rjt_s *ls_rjt;
2852
2853 bfa_trc(port->fcs, req_status);
2854 bfa_trc(port->fcs, port->port_cfg.pwwn);
2855
2856 /*
2857 * Sanity Checks
2858 */
2859 if (req_status != BFA_STATUS_OK) {
2860 port->stats.ms_plogi_rsp_err++;
2861 bfa_trc(port->fcs, req_status);
2862 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2863 return;
2864 }
2865
2866 els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
2867
2868 switch (els_cmd->els_code) {
2869
2870 case FC_ELS_ACC:
2871 if (rsp_len < sizeof(struct fc_logi_s)) {
2872 bfa_trc(port->fcs, rsp_len);
2873 port->stats.ms_plogi_acc_err++;
2874 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2875 break;
2876 }
2877 port->stats.ms_plogi_accepts++;
2878 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
2879 break;
2880
2881 case FC_ELS_LS_RJT:
2882 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
2883
2884 bfa_trc(port->fcs, ls_rjt->reason_code);
2885 bfa_trc(port->fcs, ls_rjt->reason_code_expl);
2886
2887 port->stats.ms_rejects++;
2888 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2889 break;
2890
2891 default:
2892 port->stats.ms_plogi_unknown_rsp++;
2893 bfa_trc(port->fcs, els_cmd->els_code);
2894 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2895 }
2896}
2897
2898static void
2899bfa_fcs_lport_ms_timeout(void *arg)
2900{
2901 struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) arg;
2902
2903 ms->port->stats.ms_timeouts++;
2904 bfa_sm_send_event(ms, MSSM_EVENT_TIMEOUT);
2905}
2906
2907
2908void
2909bfa_fcs_lport_ms_init(struct bfa_fcs_lport_s *port)
2910{
2911 struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
2912
2913 ms->port = port;
2914 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2915
2916 /*
2917 * Invoke init routines of sub modules.
2918 */
2919 bfa_fcs_lport_fdmi_init(ms);
2920}
2921
2922void
2923bfa_fcs_lport_ms_offline(struct bfa_fcs_lport_s *port)
2924{
2925 struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
2926
2927 ms->port = port;
2928 bfa_sm_send_event(ms, MSSM_EVENT_PORT_OFFLINE);
2929 bfa_fcs_lport_fdmi_offline(ms);
2930}
2931
2932void
2933bfa_fcs_lport_ms_online(struct bfa_fcs_lport_s *port)
2934{
2935 struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
2936
2937 ms->port = port;
2938 bfa_sm_send_event(ms, MSSM_EVENT_PORT_ONLINE);
2939}
2940void
2941bfa_fcs_lport_ms_fabric_rscn(struct bfa_fcs_lport_s *port)
2942{
2943 struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
2944
2945 /* todo. Handle this only when in Online state */
2946 if (bfa_sm_cmp_state(ms, bfa_fcs_lport_ms_sm_online))
2947 bfa_sm_send_event(ms, MSSM_EVENT_PORT_FABRIC_RSCN);
2948}
2949
Jing Huang5fbe25c2010-10-18 17:17:23 -07002950/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002951 * @page ns_sm_info VPORT NS State Machine
2952 *
2953 * @section ns_sm_interactions VPORT NS State Machine Interactions
2954 *
2955 * @section ns_sm VPORT NS State Machine
2956 * img ns_sm.jpg
2957 */
2958
2959/*
2960 * forward declarations
2961 */
2962static void bfa_fcs_lport_ns_send_plogi(void *ns_cbarg,
2963 struct bfa_fcxp_s *fcxp_alloced);
2964static void bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg,
2965 struct bfa_fcxp_s *fcxp_alloced);
2966static void bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg,
2967 struct bfa_fcxp_s *fcxp_alloced);
2968static void bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg,
2969 struct bfa_fcxp_s *fcxp_alloced);
2970static void bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg,
2971 struct bfa_fcxp_s *fcxp_alloced);
2972static void bfa_fcs_lport_ns_timeout(void *arg);
2973static void bfa_fcs_lport_ns_plogi_response(void *fcsarg,
2974 struct bfa_fcxp_s *fcxp,
2975 void *cbarg,
2976 bfa_status_t req_status,
2977 u32 rsp_len,
2978 u32 resid_len,
2979 struct fchs_s *rsp_fchs);
2980static void bfa_fcs_lport_ns_rspn_id_response(void *fcsarg,
2981 struct bfa_fcxp_s *fcxp,
2982 void *cbarg,
2983 bfa_status_t req_status,
2984 u32 rsp_len,
2985 u32 resid_len,
2986 struct fchs_s *rsp_fchs);
2987static void bfa_fcs_lport_ns_rft_id_response(void *fcsarg,
2988 struct bfa_fcxp_s *fcxp,
2989 void *cbarg,
2990 bfa_status_t req_status,
2991 u32 rsp_len,
2992 u32 resid_len,
2993 struct fchs_s *rsp_fchs);
2994static void bfa_fcs_lport_ns_rff_id_response(void *fcsarg,
2995 struct bfa_fcxp_s *fcxp,
2996 void *cbarg,
2997 bfa_status_t req_status,
2998 u32 rsp_len,
2999 u32 resid_len,
3000 struct fchs_s *rsp_fchs);
3001static void bfa_fcs_lport_ns_gid_ft_response(void *fcsarg,
3002 struct bfa_fcxp_s *fcxp,
3003 void *cbarg,
3004 bfa_status_t req_status,
3005 u32 rsp_len,
3006 u32 resid_len,
3007 struct fchs_s *rsp_fchs);
3008static void bfa_fcs_lport_ns_process_gidft_pids(
3009 struct bfa_fcs_lport_s *port,
3010 u32 *pid_buf, u32 n_pids);
3011
3012static void bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port);
Jing Huang5fbe25c2010-10-18 17:17:23 -07003013/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003014 * fcs_ns_sm FCS nameserver interface state machine
3015 */
3016
Jing Huang5fbe25c2010-10-18 17:17:23 -07003017/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003018 * VPort NS State Machine events
3019 */
3020enum vport_ns_event {
3021 NSSM_EVENT_PORT_ONLINE = 1,
3022 NSSM_EVENT_PORT_OFFLINE = 2,
3023 NSSM_EVENT_PLOGI_SENT = 3,
3024 NSSM_EVENT_RSP_OK = 4,
3025 NSSM_EVENT_RSP_ERROR = 5,
3026 NSSM_EVENT_TIMEOUT = 6,
3027 NSSM_EVENT_NS_QUERY = 7,
3028 NSSM_EVENT_RSPNID_SENT = 8,
3029 NSSM_EVENT_RFTID_SENT = 9,
3030 NSSM_EVENT_RFFID_SENT = 10,
3031 NSSM_EVENT_GIDFT_SENT = 11,
3032};
3033
3034static void bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
3035 enum vport_ns_event event);
3036static void bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns,
3037 enum vport_ns_event event);
3038static void bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
3039 enum vport_ns_event event);
3040static void bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
3041 enum vport_ns_event event);
3042static void bfa_fcs_lport_ns_sm_sending_rspn_id(
3043 struct bfa_fcs_lport_ns_s *ns,
3044 enum vport_ns_event event);
3045static void bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3046 enum vport_ns_event event);
3047static void bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3048 enum vport_ns_event event);
3049static void bfa_fcs_lport_ns_sm_sending_rft_id(
3050 struct bfa_fcs_lport_ns_s *ns,
3051 enum vport_ns_event event);
3052static void bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns,
3053 enum vport_ns_event event);
3054static void bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns,
3055 enum vport_ns_event event);
3056static void bfa_fcs_lport_ns_sm_sending_rff_id(
3057 struct bfa_fcs_lport_ns_s *ns,
3058 enum vport_ns_event event);
3059static void bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns,
3060 enum vport_ns_event event);
3061static void bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns,
3062 enum vport_ns_event event);
3063static void bfa_fcs_lport_ns_sm_sending_gid_ft(
3064 struct bfa_fcs_lport_ns_s *ns,
3065 enum vport_ns_event event);
3066static void bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3067 enum vport_ns_event event);
3068static void bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
3069 enum vport_ns_event event);
3070static void bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
3071 enum vport_ns_event event);
Jing Huang5fbe25c2010-10-18 17:17:23 -07003072/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003073 * Start in offline state - awaiting linkup
3074 */
3075static void
3076bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
3077 enum vport_ns_event event)
3078{
3079 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3080 bfa_trc(ns->port->fcs, event);
3081
3082 switch (event) {
3083 case NSSM_EVENT_PORT_ONLINE:
3084 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending);
3085 bfa_fcs_lport_ns_send_plogi(ns, NULL);
3086 break;
3087
3088 case NSSM_EVENT_PORT_OFFLINE:
3089 break;
3090
3091 default:
3092 bfa_sm_fault(ns->port->fcs, event);
3093 }
3094}
3095
3096static void
3097bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns,
3098 enum vport_ns_event event)
3099{
3100 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3101 bfa_trc(ns->port->fcs, event);
3102
3103 switch (event) {
3104 case NSSM_EVENT_PLOGI_SENT:
3105 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi);
3106 break;
3107
3108 case NSSM_EVENT_PORT_OFFLINE:
3109 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3110 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3111 &ns->fcxp_wqe);
3112 break;
3113
3114 default:
3115 bfa_sm_fault(ns->port->fcs, event);
3116 }
3117}
3118
3119static void
3120bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
3121 enum vport_ns_event event)
3122{
3123 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3124 bfa_trc(ns->port->fcs, event);
3125
3126 switch (event) {
3127 case NSSM_EVENT_RSP_ERROR:
3128 /*
3129 * Start timer for a delayed retry
3130 */
3131 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_retry);
3132 ns->port->stats.ns_retries++;
3133 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3134 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3135 BFA_FCS_RETRY_TIMEOUT);
3136 break;
3137
3138 case NSSM_EVENT_RSP_OK:
3139 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
3140 bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
3141 break;
3142
3143 case NSSM_EVENT_PORT_OFFLINE:
3144 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3145 bfa_fcxp_discard(ns->fcxp);
3146 break;
3147
3148 default:
3149 bfa_sm_fault(ns->port->fcs, event);
3150 }
3151}
3152
3153static void
3154bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
3155 enum vport_ns_event event)
3156{
3157 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3158 bfa_trc(ns->port->fcs, event);
3159
3160 switch (event) {
3161 case NSSM_EVENT_TIMEOUT:
3162 /*
3163 * Retry Timer Expired. Re-send
3164 */
3165 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending);
3166 bfa_fcs_lport_ns_send_plogi(ns, NULL);
3167 break;
3168
3169 case NSSM_EVENT_PORT_OFFLINE:
3170 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3171 bfa_timer_stop(&ns->timer);
3172 break;
3173
3174 default:
3175 bfa_sm_fault(ns->port->fcs, event);
3176 }
3177}
3178
3179static void
3180bfa_fcs_lport_ns_sm_sending_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3181 enum vport_ns_event event)
3182{
3183 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3184 bfa_trc(ns->port->fcs, event);
3185
3186 switch (event) {
3187 case NSSM_EVENT_RSPNID_SENT:
3188 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id);
3189 break;
3190
3191 case NSSM_EVENT_PORT_OFFLINE:
3192 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3193 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3194 &ns->fcxp_wqe);
3195 break;
3196
3197 default:
3198 bfa_sm_fault(ns->port->fcs, event);
3199 }
3200}
3201
3202static void
3203bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3204 enum vport_ns_event event)
3205{
3206 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3207 bfa_trc(ns->port->fcs, event);
3208
3209 switch (event) {
3210 case NSSM_EVENT_RSP_ERROR:
3211 /*
3212 * Start timer for a delayed retry
3213 */
3214 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id_retry);
3215 ns->port->stats.ns_retries++;
3216 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3217 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3218 BFA_FCS_RETRY_TIMEOUT);
3219 break;
3220
3221 case NSSM_EVENT_RSP_OK:
3222 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id);
3223 bfa_fcs_lport_ns_send_rft_id(ns, NULL);
3224 break;
3225
3226 case NSSM_EVENT_PORT_OFFLINE:
3227 bfa_fcxp_discard(ns->fcxp);
3228 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3229 break;
3230
3231 default:
3232 bfa_sm_fault(ns->port->fcs, event);
3233 }
3234}
3235
3236static void
3237bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3238 enum vport_ns_event event)
3239{
3240 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3241 bfa_trc(ns->port->fcs, event);
3242
3243 switch (event) {
3244 case NSSM_EVENT_TIMEOUT:
3245 /*
3246 * Retry Timer Expired. Re-send
3247 */
3248 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
3249 bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
3250 break;
3251
3252 case NSSM_EVENT_PORT_OFFLINE:
3253 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3254 bfa_timer_stop(&ns->timer);
3255 break;
3256
3257 default:
3258 bfa_sm_fault(ns->port->fcs, event);
3259 }
3260}
3261
3262static void
3263bfa_fcs_lport_ns_sm_sending_rft_id(struct bfa_fcs_lport_ns_s *ns,
3264 enum vport_ns_event event)
3265{
3266 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3267 bfa_trc(ns->port->fcs, event);
3268
3269 switch (event) {
3270 case NSSM_EVENT_RFTID_SENT:
3271 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id);
3272 break;
3273
3274 case NSSM_EVENT_PORT_OFFLINE:
3275 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3276 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3277 &ns->fcxp_wqe);
3278 break;
3279
3280 default:
3281 bfa_sm_fault(ns->port->fcs, event);
3282 }
3283}
3284
3285static void
3286bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns,
3287 enum vport_ns_event event)
3288{
3289 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3290 bfa_trc(ns->port->fcs, event);
3291
3292 switch (event) {
3293 case NSSM_EVENT_RSP_OK:
3294 /* Now move to register FC4 Features */
3295 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id);
3296 bfa_fcs_lport_ns_send_rff_id(ns, NULL);
3297 break;
3298
3299 case NSSM_EVENT_RSP_ERROR:
3300 /*
3301 * Start timer for a delayed retry
3302 */
3303 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id_retry);
3304 ns->port->stats.ns_retries++;
3305 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3306 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3307 BFA_FCS_RETRY_TIMEOUT);
3308 break;
3309
3310 case NSSM_EVENT_PORT_OFFLINE:
3311 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3312 bfa_fcxp_discard(ns->fcxp);
3313 break;
3314
3315 default:
3316 bfa_sm_fault(ns->port->fcs, event);
3317 }
3318}
3319
3320static void
3321bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns,
3322 enum vport_ns_event event)
3323{
3324 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3325 bfa_trc(ns->port->fcs, event);
3326
3327 switch (event) {
3328 case NSSM_EVENT_TIMEOUT:
3329 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id);
3330 bfa_fcs_lport_ns_send_rft_id(ns, NULL);
3331 break;
3332
3333 case NSSM_EVENT_PORT_OFFLINE:
3334 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3335 bfa_timer_stop(&ns->timer);
3336 break;
3337
3338 default:
3339 bfa_sm_fault(ns->port->fcs, event);
3340 }
3341}
3342
3343static void
3344bfa_fcs_lport_ns_sm_sending_rff_id(struct bfa_fcs_lport_ns_s *ns,
3345 enum vport_ns_event event)
3346{
3347 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3348 bfa_trc(ns->port->fcs, event);
3349
3350 switch (event) {
3351 case NSSM_EVENT_RFFID_SENT:
3352 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id);
3353 break;
3354
3355 case NSSM_EVENT_PORT_OFFLINE:
3356 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3357 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3358 &ns->fcxp_wqe);
3359 break;
3360
3361 default:
3362 bfa_sm_fault(ns->port->fcs, event);
3363 }
3364}
3365
3366static void
3367bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns,
3368 enum vport_ns_event event)
3369{
3370 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3371 bfa_trc(ns->port->fcs, event);
3372
3373 switch (event) {
3374 case NSSM_EVENT_RSP_OK:
3375
3376 /*
3377 * If min cfg mode is enabled, we donot initiate rport
3378 * discovery with the fabric. Instead, we will retrieve the
3379 * boot targets from HAL/FW.
3380 */
3381 if (__fcs_min_cfg(ns->port->fcs)) {
3382 bfa_fcs_lport_ns_boot_target_disc(ns->port);
3383 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online);
3384 return;
3385 }
3386
3387 /*
3388 * If the port role is Initiator Mode issue NS query.
3389 * If it is Target Mode, skip this and go to online.
3390 */
3391 if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
3392 bfa_sm_set_state(ns,
3393 bfa_fcs_lport_ns_sm_sending_gid_ft);
3394 bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
3395 }
3396 /*
3397 * kick off mgmt srvr state machine
3398 */
3399 bfa_fcs_lport_ms_online(ns->port);
3400 break;
3401
3402 case NSSM_EVENT_RSP_ERROR:
3403 /*
3404 * Start timer for a delayed retry
3405 */
3406 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id_retry);
3407 ns->port->stats.ns_retries++;
3408 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3409 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3410 BFA_FCS_RETRY_TIMEOUT);
3411 break;
3412
3413 case NSSM_EVENT_PORT_OFFLINE:
3414 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3415 bfa_fcxp_discard(ns->fcxp);
3416 break;
3417
3418 default:
3419 bfa_sm_fault(ns->port->fcs, event);
3420 }
3421}
3422
3423static void
3424bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns,
3425 enum vport_ns_event event)
3426{
3427 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3428 bfa_trc(ns->port->fcs, event);
3429
3430 switch (event) {
3431 case NSSM_EVENT_TIMEOUT:
3432 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id);
3433 bfa_fcs_lport_ns_send_rff_id(ns, NULL);
3434 break;
3435
3436 case NSSM_EVENT_PORT_OFFLINE:
3437 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3438 bfa_timer_stop(&ns->timer);
3439 break;
3440
3441 default:
3442 bfa_sm_fault(ns->port->fcs, event);
3443 }
3444}
3445static void
3446bfa_fcs_lport_ns_sm_sending_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3447 enum vport_ns_event event)
3448{
3449 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3450 bfa_trc(ns->port->fcs, event);
3451
3452 switch (event) {
3453 case NSSM_EVENT_GIDFT_SENT:
3454 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft);
3455 break;
3456
3457 case NSSM_EVENT_PORT_OFFLINE:
3458 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3459 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3460 &ns->fcxp_wqe);
3461 break;
3462
3463 default:
3464 bfa_sm_fault(ns->port->fcs, event);
3465 }
3466}
3467
3468static void
3469bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3470 enum vport_ns_event event)
3471{
3472 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3473 bfa_trc(ns->port->fcs, event);
3474
3475 switch (event) {
3476 case NSSM_EVENT_RSP_OK:
3477 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online);
3478 break;
3479
3480 case NSSM_EVENT_RSP_ERROR:
3481 /*
3482 * TBD: for certain reject codes, we don't need to retry
3483 */
3484 /*
3485 * Start timer for a delayed retry
3486 */
3487 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft_retry);
3488 ns->port->stats.ns_retries++;
3489 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3490 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3491 BFA_FCS_RETRY_TIMEOUT);
3492 break;
3493
3494 case NSSM_EVENT_PORT_OFFLINE:
3495 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3496 bfa_fcxp_discard(ns->fcxp);
3497 break;
3498
3499 case NSSM_EVENT_NS_QUERY:
3500 break;
3501
3502 default:
3503 bfa_sm_fault(ns->port->fcs, event);
3504 }
3505}
3506
3507static void
3508bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
3509 enum vport_ns_event event)
3510{
3511 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3512 bfa_trc(ns->port->fcs, event);
3513
3514 switch (event) {
3515 case NSSM_EVENT_TIMEOUT:
3516 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_gid_ft);
3517 bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
3518 break;
3519
3520 case NSSM_EVENT_PORT_OFFLINE:
3521 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3522 bfa_timer_stop(&ns->timer);
3523 break;
3524
3525 default:
3526 bfa_sm_fault(ns->port->fcs, event);
3527 }
3528}
3529
3530static void
3531bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
3532 enum vport_ns_event event)
3533{
3534 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3535 bfa_trc(ns->port->fcs, event);
3536
3537 switch (event) {
3538 case NSSM_EVENT_PORT_OFFLINE:
3539 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3540 break;
3541
3542 case NSSM_EVENT_NS_QUERY:
3543 /*
3544 * If the port role is Initiator Mode issue NS query.
3545 * If it is Target Mode, skip this and go to online.
3546 */
3547 if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
3548 bfa_sm_set_state(ns,
3549 bfa_fcs_lport_ns_sm_sending_gid_ft);
3550 bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
3551 };
3552 break;
3553
3554 default:
3555 bfa_sm_fault(ns->port->fcs, event);
3556 }
3557}
3558
3559
3560
Jing Huang5fbe25c2010-10-18 17:17:23 -07003561/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003562 * ns_pvt Nameserver local functions
3563 */
3564
3565static void
3566bfa_fcs_lport_ns_send_plogi(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3567{
3568 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3569 struct bfa_fcs_lport_s *port = ns->port;
3570 struct fchs_s fchs;
3571 int len;
3572 struct bfa_fcxp_s *fcxp;
3573
3574 bfa_trc(port->fcs, port->pid);
3575
3576fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3577 if (!fcxp) {
3578 port->stats.ns_plogi_alloc_wait++;
3579 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3580 bfa_fcs_lport_ns_send_plogi, ns);
3581 return;
3582 }
3583 ns->fcxp = fcxp;
3584
3585 len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
Maggie Zhangf16a1752010-12-09 19:12:32 -08003586 bfa_hton3b(FC_NAME_SERVER),
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003587 bfa_fcs_lport_get_fcid(port), 0,
3588 port->port_cfg.pwwn, port->port_cfg.nwwn,
3589 bfa_fcport_get_maxfrsize(port->fcs->bfa));
3590
3591 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3592 FC_CLASS_3, len, &fchs,
3593 bfa_fcs_lport_ns_plogi_response, (void *)ns,
3594 FC_MAX_PDUSZ, FC_ELS_TOV);
3595 port->stats.ns_plogi_sent++;
3596
3597 bfa_sm_send_event(ns, NSSM_EVENT_PLOGI_SENT);
3598}
3599
3600static void
3601bfa_fcs_lport_ns_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3602 void *cbarg, bfa_status_t req_status, u32 rsp_len,
3603 u32 resid_len, struct fchs_s *rsp_fchs)
3604{
3605 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3606 struct bfa_fcs_lport_s *port = ns->port;
3607 /* struct fc_logi_s *plogi_resp; */
3608 struct fc_els_cmd_s *els_cmd;
3609 struct fc_ls_rjt_s *ls_rjt;
3610
3611 bfa_trc(port->fcs, req_status);
3612 bfa_trc(port->fcs, port->port_cfg.pwwn);
3613
3614 /*
3615 * Sanity Checks
3616 */
3617 if (req_status != BFA_STATUS_OK) {
3618 bfa_trc(port->fcs, req_status);
3619 port->stats.ns_plogi_rsp_err++;
3620 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3621 return;
3622 }
3623
3624 els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
3625
3626 switch (els_cmd->els_code) {
3627
3628 case FC_ELS_ACC:
3629 if (rsp_len < sizeof(struct fc_logi_s)) {
3630 bfa_trc(port->fcs, rsp_len);
3631 port->stats.ns_plogi_acc_err++;
3632 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3633 break;
3634 }
3635 port->stats.ns_plogi_accepts++;
3636 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3637 break;
3638
3639 case FC_ELS_LS_RJT:
3640 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
3641
3642 bfa_trc(port->fcs, ls_rjt->reason_code);
3643 bfa_trc(port->fcs, ls_rjt->reason_code_expl);
3644
3645 port->stats.ns_rejects++;
3646
3647 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3648 break;
3649
3650 default:
3651 port->stats.ns_plogi_unknown_rsp++;
3652 bfa_trc(port->fcs, els_cmd->els_code);
3653 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3654 }
3655}
3656
Jing Huang5fbe25c2010-10-18 17:17:23 -07003657/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003658 * Register the symbolic port name.
3659 */
3660static void
3661bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3662{
3663 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3664 struct bfa_fcs_lport_s *port = ns->port;
3665 struct fchs_s fchs;
3666 int len;
3667 struct bfa_fcxp_s *fcxp;
3668 u8 symbl[256];
3669 u8 *psymbl = &symbl[0];
3670
Jing Huang6a18b162010-10-18 17:08:54 -07003671 memset(symbl, 0, sizeof(symbl));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003672
3673 bfa_trc(port->fcs, port->port_cfg.pwwn);
3674
3675 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3676 if (!fcxp) {
3677 port->stats.ns_rspnid_alloc_wait++;
3678 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3679 bfa_fcs_lport_ns_send_rspn_id, ns);
3680 return;
3681 }
3682 ns->fcxp = fcxp;
3683
3684 /*
3685 * for V-Port, form a Port Symbolic Name
3686 */
3687 if (port->vport) {
Jing Huang5fbe25c2010-10-18 17:17:23 -07003688 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003689 * For Vports, we append the vport's port symbolic name
3690 * to that of the base port.
3691 */
3692
3693 strncpy((char *)psymbl,
3694 (char *) &
3695 (bfa_fcs_lport_get_psym_name
3696 (bfa_fcs_get_base_port(port->fcs))),
3697 strlen((char *) &
3698 bfa_fcs_lport_get_psym_name(bfa_fcs_get_base_port
3699 (port->fcs))));
3700
3701 /* Ensure we have a null terminating string. */
3702 ((char *)psymbl)[strlen((char *) &
3703 bfa_fcs_lport_get_psym_name(bfa_fcs_get_base_port
3704 (port->fcs)))] = 0;
3705 strncat((char *)psymbl,
3706 (char *) &(bfa_fcs_lport_get_psym_name(port)),
3707 strlen((char *) &bfa_fcs_lport_get_psym_name(port)));
3708 } else {
3709 psymbl = (u8 *) &(bfa_fcs_lport_get_psym_name(port));
3710 }
3711
3712 len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3713 bfa_fcs_lport_get_fcid(port), 0, psymbl);
3714
3715 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3716 FC_CLASS_3, len, &fchs,
3717 bfa_fcs_lport_ns_rspn_id_response, (void *)ns,
3718 FC_MAX_PDUSZ, FC_FCCT_TOV);
3719
3720 port->stats.ns_rspnid_sent++;
3721
3722 bfa_sm_send_event(ns, NSSM_EVENT_RSPNID_SENT);
3723}
3724
3725static void
3726bfa_fcs_lport_ns_rspn_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3727 void *cbarg, bfa_status_t req_status,
3728 u32 rsp_len, u32 resid_len,
3729 struct fchs_s *rsp_fchs)
3730{
3731 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3732 struct bfa_fcs_lport_s *port = ns->port;
3733 struct ct_hdr_s *cthdr = NULL;
3734
3735 bfa_trc(port->fcs, port->port_cfg.pwwn);
3736
3737 /*
3738 * Sanity Checks
3739 */
3740 if (req_status != BFA_STATUS_OK) {
3741 bfa_trc(port->fcs, req_status);
3742 port->stats.ns_rspnid_rsp_err++;
3743 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3744 return;
3745 }
3746
3747 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
Jing Huangba816ea2010-10-18 17:10:50 -07003748 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003749
3750 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
3751 port->stats.ns_rspnid_accepts++;
3752 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3753 return;
3754 }
3755
3756 port->stats.ns_rspnid_rejects++;
3757 bfa_trc(port->fcs, cthdr->reason_code);
3758 bfa_trc(port->fcs, cthdr->exp_code);
3759 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3760}
3761
Jing Huang5fbe25c2010-10-18 17:17:23 -07003762/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003763 * Register FC4-Types
3764 */
3765static void
3766bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3767{
3768 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3769 struct bfa_fcs_lport_s *port = ns->port;
3770 struct fchs_s fchs;
3771 int len;
3772 struct bfa_fcxp_s *fcxp;
3773
3774 bfa_trc(port->fcs, port->port_cfg.pwwn);
3775
3776 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3777 if (!fcxp) {
3778 port->stats.ns_rftid_alloc_wait++;
3779 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3780 bfa_fcs_lport_ns_send_rft_id, ns);
3781 return;
3782 }
3783 ns->fcxp = fcxp;
3784
3785 len = fc_rftid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3786 bfa_fcs_lport_get_fcid(port), 0, port->port_cfg.roles);
3787
3788 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3789 FC_CLASS_3, len, &fchs,
3790 bfa_fcs_lport_ns_rft_id_response, (void *)ns,
3791 FC_MAX_PDUSZ, FC_FCCT_TOV);
3792
3793 port->stats.ns_rftid_sent++;
3794 bfa_sm_send_event(ns, NSSM_EVENT_RFTID_SENT);
3795}
3796
3797static void
3798bfa_fcs_lport_ns_rft_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3799 void *cbarg, bfa_status_t req_status,
3800 u32 rsp_len, u32 resid_len,
3801 struct fchs_s *rsp_fchs)
3802{
3803 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3804 struct bfa_fcs_lport_s *port = ns->port;
3805 struct ct_hdr_s *cthdr = NULL;
3806
3807 bfa_trc(port->fcs, port->port_cfg.pwwn);
3808
3809 /*
3810 * Sanity Checks
3811 */
3812 if (req_status != BFA_STATUS_OK) {
3813 bfa_trc(port->fcs, req_status);
3814 port->stats.ns_rftid_rsp_err++;
3815 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3816 return;
3817 }
3818
3819 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
Jing Huangba816ea2010-10-18 17:10:50 -07003820 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003821
3822 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
3823 port->stats.ns_rftid_accepts++;
3824 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3825 return;
3826 }
3827
3828 port->stats.ns_rftid_rejects++;
3829 bfa_trc(port->fcs, cthdr->reason_code);
3830 bfa_trc(port->fcs, cthdr->exp_code);
3831 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3832}
3833
Jing Huang5fbe25c2010-10-18 17:17:23 -07003834/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003835 * Register FC4-Features : Should be done after RFT_ID
3836 */
3837static void
3838bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3839{
3840 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3841 struct bfa_fcs_lport_s *port = ns->port;
3842 struct fchs_s fchs;
3843 int len;
3844 struct bfa_fcxp_s *fcxp;
3845 u8 fc4_ftrs = 0;
3846
3847 bfa_trc(port->fcs, port->port_cfg.pwwn);
3848
3849 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3850 if (!fcxp) {
3851 port->stats.ns_rffid_alloc_wait++;
3852 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3853 bfa_fcs_lport_ns_send_rff_id, ns);
3854 return;
3855 }
3856 ns->fcxp = fcxp;
3857
3858 if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port))
3859 fc4_ftrs = FC_GS_FCP_FC4_FEATURE_INITIATOR;
3860
3861 len = fc_rffid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3862 bfa_fcs_lport_get_fcid(port), 0,
3863 FC_TYPE_FCP, fc4_ftrs);
3864
3865 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3866 FC_CLASS_3, len, &fchs,
3867 bfa_fcs_lport_ns_rff_id_response, (void *)ns,
3868 FC_MAX_PDUSZ, FC_FCCT_TOV);
3869
3870 port->stats.ns_rffid_sent++;
3871 bfa_sm_send_event(ns, NSSM_EVENT_RFFID_SENT);
3872}
3873
3874static void
3875bfa_fcs_lport_ns_rff_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3876 void *cbarg, bfa_status_t req_status,
3877 u32 rsp_len, u32 resid_len,
3878 struct fchs_s *rsp_fchs)
3879{
3880 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3881 struct bfa_fcs_lport_s *port = ns->port;
3882 struct ct_hdr_s *cthdr = NULL;
3883
3884 bfa_trc(port->fcs, port->port_cfg.pwwn);
3885
3886 /*
3887 * Sanity Checks
3888 */
3889 if (req_status != BFA_STATUS_OK) {
3890 bfa_trc(port->fcs, req_status);
3891 port->stats.ns_rffid_rsp_err++;
3892 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3893 return;
3894 }
3895
3896 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
Jing Huangba816ea2010-10-18 17:10:50 -07003897 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003898
3899 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
3900 port->stats.ns_rffid_accepts++;
3901 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3902 return;
3903 }
3904
3905 port->stats.ns_rffid_rejects++;
3906 bfa_trc(port->fcs, cthdr->reason_code);
3907 bfa_trc(port->fcs, cthdr->exp_code);
3908
3909 if (cthdr->reason_code == CT_RSN_NOT_SUPP) {
3910 /* if this command is not supported, we don't retry */
3911 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3912 } else
3913 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3914}
Jing Huang5fbe25c2010-10-18 17:17:23 -07003915/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003916 * Query Fabric for FC4-Types Devices.
3917 *
3918* TBD : Need to use a local (FCS private) response buffer, since the response
3919 * can be larger than 2K.
3920 */
3921static void
3922bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3923{
3924 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3925 struct bfa_fcs_lport_s *port = ns->port;
3926 struct fchs_s fchs;
3927 int len;
3928 struct bfa_fcxp_s *fcxp;
3929
3930 bfa_trc(port->fcs, port->pid);
3931
3932 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3933 if (!fcxp) {
3934 port->stats.ns_gidft_alloc_wait++;
3935 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3936 bfa_fcs_lport_ns_send_gid_ft, ns);
3937 return;
3938 }
3939 ns->fcxp = fcxp;
3940
3941 /*
3942 * This query is only initiated for FCP initiator mode.
3943 */
3944 len = fc_gid_ft_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3945 ns->port->pid, FC_TYPE_FCP);
3946
3947 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3948 FC_CLASS_3, len, &fchs,
3949 bfa_fcs_lport_ns_gid_ft_response, (void *)ns,
3950 bfa_fcxp_get_maxrsp(port->fcs->bfa), FC_FCCT_TOV);
3951
3952 port->stats.ns_gidft_sent++;
3953
3954 bfa_sm_send_event(ns, NSSM_EVENT_GIDFT_SENT);
3955}
3956
3957static void
3958bfa_fcs_lport_ns_gid_ft_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3959 void *cbarg, bfa_status_t req_status,
3960 u32 rsp_len, u32 resid_len,
3961 struct fchs_s *rsp_fchs)
3962{
3963 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3964 struct bfa_fcs_lport_s *port = ns->port;
3965 struct ct_hdr_s *cthdr = NULL;
3966 u32 n_pids;
3967
3968 bfa_trc(port->fcs, port->port_cfg.pwwn);
3969
3970 /*
3971 * Sanity Checks
3972 */
3973 if (req_status != BFA_STATUS_OK) {
3974 bfa_trc(port->fcs, req_status);
3975 port->stats.ns_gidft_rsp_err++;
3976 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3977 return;
3978 }
3979
3980 if (resid_len != 0) {
3981 /*
3982 * TBD : we will need to allocate a larger buffer & retry the
3983 * command
3984 */
3985 bfa_trc(port->fcs, rsp_len);
3986 bfa_trc(port->fcs, resid_len);
3987 return;
3988 }
3989
3990 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
Jing Huangba816ea2010-10-18 17:10:50 -07003991 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003992
3993 switch (cthdr->cmd_rsp_code) {
3994
3995 case CT_RSP_ACCEPT:
3996
3997 port->stats.ns_gidft_accepts++;
3998 n_pids = (fc_get_ctresp_pyld_len(rsp_len) / sizeof(u32));
3999 bfa_trc(port->fcs, n_pids);
4000 bfa_fcs_lport_ns_process_gidft_pids(port,
4001 (u32 *) (cthdr + 1),
4002 n_pids);
4003 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4004 break;
4005
4006 case CT_RSP_REJECT:
4007
4008 /*
4009 * Check the reason code & explanation.
4010 * There may not have been any FC4 devices in the fabric
4011 */
4012 port->stats.ns_gidft_rejects++;
4013 bfa_trc(port->fcs, cthdr->reason_code);
4014 bfa_trc(port->fcs, cthdr->exp_code);
4015
4016 if ((cthdr->reason_code == CT_RSN_UNABLE_TO_PERF)
4017 && (cthdr->exp_code == CT_NS_EXP_FT_NOT_REG)) {
4018
4019 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4020 } else {
4021 /*
4022 * for all other errors, retry
4023 */
4024 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4025 }
4026 break;
4027
4028 default:
4029 port->stats.ns_gidft_unknown_rsp++;
4030 bfa_trc(port->fcs, cthdr->cmd_rsp_code);
4031 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4032 }
4033}
4034
Jing Huang5fbe25c2010-10-18 17:17:23 -07004035/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004036 * This routine will be called by bfa_timer on timer timeouts.
4037 *
4038 * param[in] port - pointer to bfa_fcs_lport_t.
4039 *
4040 * return
4041 * void
4042 *
4043 * Special Considerations:
4044 *
4045 * note
4046 */
4047static void
4048bfa_fcs_lport_ns_timeout(void *arg)
4049{
4050 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) arg;
4051
4052 ns->port->stats.ns_timeouts++;
4053 bfa_sm_send_event(ns, NSSM_EVENT_TIMEOUT);
4054}
4055
4056/*
4057 * Process the PID list in GID_FT response
4058 */
4059static void
4060bfa_fcs_lport_ns_process_gidft_pids(struct bfa_fcs_lport_s *port, u32 *pid_buf,
4061 u32 n_pids)
4062{
4063 struct fcgs_gidft_resp_s *gidft_entry;
4064 struct bfa_fcs_rport_s *rport;
4065 u32 ii;
4066
4067 for (ii = 0; ii < n_pids; ii++) {
4068 gidft_entry = (struct fcgs_gidft_resp_s *) &pid_buf[ii];
4069
4070 if (gidft_entry->pid == port->pid)
4071 continue;
4072
4073 /*
4074 * Check if this rport already exists
4075 */
4076 rport = bfa_fcs_lport_get_rport_by_pid(port, gidft_entry->pid);
4077 if (rport == NULL) {
4078 /*
4079 * this is a new device. create rport
4080 */
4081 rport = bfa_fcs_rport_create(port, gidft_entry->pid);
4082 } else {
4083 /*
4084 * this rport already exists
4085 */
4086 bfa_fcs_rport_scn(rport);
4087 }
4088
4089 bfa_trc(port->fcs, gidft_entry->pid);
4090
4091 /*
4092 * if the last entry bit is set, bail out.
4093 */
4094 if (gidft_entry->last)
4095 return;
4096 }
4097}
4098
Jing Huang5fbe25c2010-10-18 17:17:23 -07004099/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004100 * fcs_ns_public FCS nameserver public interfaces
4101 */
4102
4103/*
4104 * Functions called by port/fab.
4105 * These will send relevant Events to the ns state machine.
4106 */
4107void
4108bfa_fcs_lport_ns_init(struct bfa_fcs_lport_s *port)
4109{
4110 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4111
4112 ns->port = port;
4113 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4114}
4115
4116void
4117bfa_fcs_lport_ns_offline(struct bfa_fcs_lport_s *port)
4118{
4119 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4120
4121 ns->port = port;
4122 bfa_sm_send_event(ns, NSSM_EVENT_PORT_OFFLINE);
4123}
4124
4125void
4126bfa_fcs_lport_ns_online(struct bfa_fcs_lport_s *port)
4127{
4128 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4129
4130 ns->port = port;
4131 bfa_sm_send_event(ns, NSSM_EVENT_PORT_ONLINE);
4132}
4133
4134void
4135bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s *port)
4136{
4137 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4138
4139 bfa_trc(port->fcs, port->pid);
4140 bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY);
4141}
4142
Maggie52f94b62010-11-29 18:21:32 -08004143static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004144bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port)
4145{
4146
4147 struct bfa_fcs_rport_s *rport;
4148 u8 nwwns;
4149 wwn_t wwns[BFA_PREBOOT_BOOTLUN_MAX];
4150 int ii;
4151
4152 bfa_iocfc_get_bootwwns(port->fcs->bfa, &nwwns, wwns);
4153
4154 for (ii = 0 ; ii < nwwns; ++ii) {
4155 rport = bfa_fcs_rport_create_by_wwn(port, wwns[ii]);
Jing Huangd4b671c2010-12-26 21:46:35 -08004156 WARN_ON(!rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004157 }
4158}
4159
Jing Huang5fbe25c2010-10-18 17:17:23 -07004160/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004161 * FCS SCN
4162 */
4163
4164#define FC_QOS_RSCN_EVENT 0x0c
4165#define FC_FABRIC_NAME_RSCN_EVENT 0x0d
4166
4167/*
4168 * forward declarations
4169 */
4170static void bfa_fcs_lport_scn_send_scr(void *scn_cbarg,
4171 struct bfa_fcxp_s *fcxp_alloced);
4172static void bfa_fcs_lport_scn_scr_response(void *fcsarg,
4173 struct bfa_fcxp_s *fcxp,
4174 void *cbarg,
4175 bfa_status_t req_status,
4176 u32 rsp_len,
4177 u32 resid_len,
4178 struct fchs_s *rsp_fchs);
4179static void bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
4180 struct fchs_s *rx_fchs);
4181static void bfa_fcs_lport_scn_timeout(void *arg);
4182
Jing Huang5fbe25c2010-10-18 17:17:23 -07004183/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004184 * fcs_scm_sm FCS SCN state machine
4185 */
4186
Jing Huang5fbe25c2010-10-18 17:17:23 -07004187/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004188 * VPort SCN State Machine events
4189 */
4190enum port_scn_event {
4191 SCNSM_EVENT_PORT_ONLINE = 1,
4192 SCNSM_EVENT_PORT_OFFLINE = 2,
4193 SCNSM_EVENT_RSP_OK = 3,
4194 SCNSM_EVENT_RSP_ERROR = 4,
4195 SCNSM_EVENT_TIMEOUT = 5,
4196 SCNSM_EVENT_SCR_SENT = 6,
4197};
4198
4199static void bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn,
4200 enum port_scn_event event);
4201static void bfa_fcs_lport_scn_sm_sending_scr(
4202 struct bfa_fcs_lport_scn_s *scn,
4203 enum port_scn_event event);
4204static void bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn,
4205 enum port_scn_event event);
4206static void bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn,
4207 enum port_scn_event event);
4208static void bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn,
4209 enum port_scn_event event);
4210
Jing Huang5fbe25c2010-10-18 17:17:23 -07004211/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004212 * Starting state - awaiting link up.
4213 */
4214static void
4215bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn,
4216 enum port_scn_event event)
4217{
4218 switch (event) {
4219 case SCNSM_EVENT_PORT_ONLINE:
4220 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr);
4221 bfa_fcs_lport_scn_send_scr(scn, NULL);
4222 break;
4223
4224 case SCNSM_EVENT_PORT_OFFLINE:
4225 break;
4226
4227 default:
4228 bfa_sm_fault(scn->port->fcs, event);
4229 }
4230}
4231
4232static void
4233bfa_fcs_lport_scn_sm_sending_scr(struct bfa_fcs_lport_scn_s *scn,
4234 enum port_scn_event event)
4235{
4236 switch (event) {
4237 case SCNSM_EVENT_SCR_SENT:
4238 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr);
4239 break;
4240
4241 case SCNSM_EVENT_PORT_OFFLINE:
4242 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4243 bfa_fcxp_walloc_cancel(scn->port->fcs->bfa, &scn->fcxp_wqe);
4244 break;
4245
4246 default:
4247 bfa_sm_fault(scn->port->fcs, event);
4248 }
4249}
4250
4251static void
4252bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn,
4253 enum port_scn_event event)
4254{
4255 struct bfa_fcs_lport_s *port = scn->port;
4256
4257 switch (event) {
4258 case SCNSM_EVENT_RSP_OK:
4259 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_online);
4260 break;
4261
4262 case SCNSM_EVENT_RSP_ERROR:
4263 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr_retry);
4264 bfa_timer_start(port->fcs->bfa, &scn->timer,
4265 bfa_fcs_lport_scn_timeout, scn,
4266 BFA_FCS_RETRY_TIMEOUT);
4267 break;
4268
4269 case SCNSM_EVENT_PORT_OFFLINE:
4270 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4271 bfa_fcxp_discard(scn->fcxp);
4272 break;
4273
4274 default:
4275 bfa_sm_fault(port->fcs, event);
4276 }
4277}
4278
4279static void
4280bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn,
4281 enum port_scn_event event)
4282{
4283 switch (event) {
4284 case SCNSM_EVENT_TIMEOUT:
4285 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr);
4286 bfa_fcs_lport_scn_send_scr(scn, NULL);
4287 break;
4288
4289 case SCNSM_EVENT_PORT_OFFLINE:
4290 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4291 bfa_timer_stop(&scn->timer);
4292 break;
4293
4294 default:
4295 bfa_sm_fault(scn->port->fcs, event);
4296 }
4297}
4298
4299static void
4300bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn,
4301 enum port_scn_event event)
4302{
4303 switch (event) {
4304 case SCNSM_EVENT_PORT_OFFLINE:
4305 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4306 break;
4307
4308 default:
4309 bfa_sm_fault(scn->port->fcs, event);
4310 }
4311}
4312
4313
4314
Jing Huang5fbe25c2010-10-18 17:17:23 -07004315/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004316 * fcs_scn_private FCS SCN private functions
4317 */
4318
Jing Huang5fbe25c2010-10-18 17:17:23 -07004319/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004320 * This routine will be called to send a SCR command.
4321 */
4322static void
4323bfa_fcs_lport_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4324{
4325 struct bfa_fcs_lport_scn_s *scn = scn_cbarg;
4326 struct bfa_fcs_lport_s *port = scn->port;
4327 struct fchs_s fchs;
4328 int len;
4329 struct bfa_fcxp_s *fcxp;
4330
4331 bfa_trc(port->fcs, port->pid);
4332 bfa_trc(port->fcs, port->port_cfg.pwwn);
4333
4334 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
4335 if (!fcxp) {
4336 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &scn->fcxp_wqe,
4337 bfa_fcs_lport_scn_send_scr, scn);
4338 return;
4339 }
4340 scn->fcxp = fcxp;
4341
4342 /* Handle VU registrations for Base port only */
4343 if ((!port->vport) && bfa_ioc_get_fcmode(&port->fcs->bfa->ioc)) {
4344 len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
Maggie Zhangf7f73812010-12-09 19:08:43 -08004345 port->fabric->lps->brcd_switch,
4346 port->pid, 0);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004347 } else {
4348 len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4349 BFA_FALSE,
4350 port->pid, 0);
4351 }
4352
4353 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4354 FC_CLASS_3, len, &fchs,
4355 bfa_fcs_lport_scn_scr_response,
4356 (void *)scn, FC_MAX_PDUSZ, FC_ELS_TOV);
4357
4358 bfa_sm_send_event(scn, SCNSM_EVENT_SCR_SENT);
4359}
4360
4361static void
4362bfa_fcs_lport_scn_scr_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4363 void *cbarg, bfa_status_t req_status, u32 rsp_len,
4364 u32 resid_len, struct fchs_s *rsp_fchs)
4365{
4366 struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) cbarg;
4367 struct bfa_fcs_lport_s *port = scn->port;
4368 struct fc_els_cmd_s *els_cmd;
4369 struct fc_ls_rjt_s *ls_rjt;
4370
4371 bfa_trc(port->fcs, port->port_cfg.pwwn);
4372
4373 /*
4374 * Sanity Checks
4375 */
4376 if (req_status != BFA_STATUS_OK) {
4377 bfa_trc(port->fcs, req_status);
4378 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
4379 return;
4380 }
4381
4382 els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
4383
4384 switch (els_cmd->els_code) {
4385
4386 case FC_ELS_ACC:
4387 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_OK);
4388 break;
4389
4390 case FC_ELS_LS_RJT:
4391
4392 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
4393
4394 bfa_trc(port->fcs, ls_rjt->reason_code);
4395 bfa_trc(port->fcs, ls_rjt->reason_code_expl);
4396
4397 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
4398 break;
4399
4400 default:
4401 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
4402 }
4403}
4404
4405/*
4406 * Send a LS Accept
4407 */
4408static void
4409bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
4410 struct fchs_s *rx_fchs)
4411{
4412 struct fchs_s fchs;
4413 struct bfa_fcxp_s *fcxp;
4414 struct bfa_rport_s *bfa_rport = NULL;
4415 int len;
4416
4417 bfa_trc(port->fcs, rx_fchs->s_id);
4418
4419 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
4420 if (!fcxp)
4421 return;
4422
4423 len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4424 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
4425 rx_fchs->ox_id);
4426
4427 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
4428 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
4429 FC_MAX_PDUSZ, 0);
4430}
4431
Jing Huang5fbe25c2010-10-18 17:17:23 -07004432/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004433 * This routine will be called by bfa_timer on timer timeouts.
4434 *
4435 * param[in] vport - pointer to bfa_fcs_lport_t.
4436 * param[out] vport_status - pointer to return vport status in
4437 *
4438 * return
4439 * void
4440 *
4441 * Special Considerations:
4442 *
4443 * note
4444 */
4445static void
4446bfa_fcs_lport_scn_timeout(void *arg)
4447{
4448 struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) arg;
4449
4450 bfa_sm_send_event(scn, SCNSM_EVENT_TIMEOUT);
4451}
4452
4453
4454
Jing Huang5fbe25c2010-10-18 17:17:23 -07004455/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004456 * fcs_scn_public FCS state change notification public interfaces
4457 */
4458
4459/*
4460 * Functions called by port/fab
4461 */
4462void
4463bfa_fcs_lport_scn_init(struct bfa_fcs_lport_s *port)
4464{
4465 struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
4466
4467 scn->port = port;
4468 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4469}
4470
4471void
4472bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *port)
4473{
4474 struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
4475
4476 scn->port = port;
4477 bfa_sm_send_event(scn, SCNSM_EVENT_PORT_OFFLINE);
4478}
4479
4480void
4481bfa_fcs_lport_scn_online(struct bfa_fcs_lport_s *port)
4482{
4483 struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
4484
4485 scn->port = port;
4486 bfa_sm_send_event(scn, SCNSM_EVENT_PORT_ONLINE);
4487}
4488
4489static void
4490bfa_fcs_lport_scn_portid_rscn(struct bfa_fcs_lport_s *port, u32 rpid)
4491{
4492 struct bfa_fcs_rport_s *rport;
4493
4494 bfa_trc(port->fcs, rpid);
4495
Jing Huang5fbe25c2010-10-18 17:17:23 -07004496 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004497 * If this is an unknown device, then it just came online.
4498 * Otherwise let rport handle the RSCN event.
4499 */
4500 rport = bfa_fcs_lport_get_rport_by_pid(port, rpid);
4501 if (rport == NULL) {
4502 /*
4503 * If min cfg mode is enabled, we donot need to
4504 * discover any new rports.
4505 */
4506 if (!__fcs_min_cfg(port->fcs))
4507 rport = bfa_fcs_rport_create(port, rpid);
4508 } else
4509 bfa_fcs_rport_scn(rport);
4510}
4511
Jing Huang5fbe25c2010-10-18 17:17:23 -07004512/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004513 * rscn format based PID comparison
4514 */
4515#define __fc_pid_match(__c0, __c1, __fmt) \
4516 (((__fmt) == FC_RSCN_FORMAT_FABRIC) || \
4517 (((__fmt) == FC_RSCN_FORMAT_DOMAIN) && \
4518 ((__c0)[0] == (__c1)[0])) || \
4519 (((__fmt) == FC_RSCN_FORMAT_AREA) && \
4520 ((__c0)[0] == (__c1)[0]) && \
4521 ((__c0)[1] == (__c1)[1])))
4522
4523static void
4524bfa_fcs_lport_scn_multiport_rscn(struct bfa_fcs_lport_s *port,
4525 enum fc_rscn_format format,
4526 u32 rscn_pid)
4527{
4528 struct bfa_fcs_rport_s *rport;
4529 struct list_head *qe, *qe_next;
4530 u8 *c0, *c1;
4531
4532 bfa_trc(port->fcs, format);
4533 bfa_trc(port->fcs, rscn_pid);
4534
4535 c0 = (u8 *) &rscn_pid;
4536
4537 list_for_each_safe(qe, qe_next, &port->rport_q) {
4538 rport = (struct bfa_fcs_rport_s *) qe;
4539 c1 = (u8 *) &rport->pid;
4540 if (__fc_pid_match(c0, c1, format))
4541 bfa_fcs_rport_scn(rport);
4542 }
4543}
4544
4545
4546void
4547bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s *port,
4548 struct fchs_s *fchs, u32 len)
4549{
4550 struct fc_rscn_pl_s *rscn = (struct fc_rscn_pl_s *) (fchs + 1);
4551 int num_entries;
4552 u32 rscn_pid;
4553 bfa_boolean_t nsquery = BFA_FALSE, found;
4554 int i = 0, j;
4555
4556 num_entries =
Jing Huangba816ea2010-10-18 17:10:50 -07004557 (be16_to_cpu(rscn->payldlen) -
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004558 sizeof(u32)) / sizeof(rscn->event[0]);
4559
4560 bfa_trc(port->fcs, num_entries);
4561
4562 port->stats.num_rscn++;
4563
4564 bfa_fcs_lport_scn_send_ls_acc(port, fchs);
4565
4566 for (i = 0; i < num_entries; i++) {
4567 rscn_pid = rscn->event[i].portid;
4568
4569 bfa_trc(port->fcs, rscn->event[i].format);
4570 bfa_trc(port->fcs, rscn_pid);
4571
4572 /* check for duplicate entries in the list */
4573 found = BFA_FALSE;
4574 for (j = 0; j < i; j++) {
4575 if (rscn->event[j].portid == rscn_pid) {
4576 found = BFA_TRUE;
4577 break;
4578 }
4579 }
4580
4581 /* if found in down the list, pid has been already processed */
4582 if (found) {
4583 bfa_trc(port->fcs, rscn_pid);
4584 continue;
4585 }
4586
4587 switch (rscn->event[i].format) {
4588 case FC_RSCN_FORMAT_PORTID:
4589 if (rscn->event[i].qualifier == FC_QOS_RSCN_EVENT) {
4590 /*
4591 * Ignore this event.
4592 * f/w would have processed it
4593 */
4594 bfa_trc(port->fcs, rscn_pid);
4595 } else {
4596 port->stats.num_portid_rscn++;
4597 bfa_fcs_lport_scn_portid_rscn(port, rscn_pid);
4598 }
4599 break;
4600
4601 case FC_RSCN_FORMAT_FABRIC:
4602 if (rscn->event[i].qualifier ==
4603 FC_FABRIC_NAME_RSCN_EVENT) {
4604 bfa_fcs_lport_ms_fabric_rscn(port);
4605 break;
4606 }
4607 /* !!!!!!!!! Fall Through !!!!!!!!!!!!! */
4608
4609 case FC_RSCN_FORMAT_AREA:
4610 case FC_RSCN_FORMAT_DOMAIN:
4611 nsquery = BFA_TRUE;
4612 bfa_fcs_lport_scn_multiport_rscn(port,
4613 rscn->event[i].format,
4614 rscn_pid);
4615 break;
4616
4617
4618 default:
Jing Huangd4b671c2010-12-26 21:46:35 -08004619 WARN_ON(1);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004620 nsquery = BFA_TRUE;
4621 }
4622 }
4623
Jing Huang5fbe25c2010-10-18 17:17:23 -07004624 /*
4625 * If any of area, domain or fabric RSCN is received, do a fresh
4626 * discovery to find new devices.
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004627 */
4628 if (nsquery)
4629 bfa_fcs_lport_ns_query(port);
4630}
4631
Jing Huang5fbe25c2010-10-18 17:17:23 -07004632/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004633 * BFA FCS port
4634 */
Jing Huang5fbe25c2010-10-18 17:17:23 -07004635/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004636 * fcs_port_api BFA FCS port API
4637 */
4638struct bfa_fcs_lport_s *
4639bfa_fcs_get_base_port(struct bfa_fcs_s *fcs)
4640{
4641 return &fcs->fabric.bport;
4642}
4643
4644wwn_t
4645bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn, int index,
4646 int nrports, bfa_boolean_t bwwn)
4647{
4648 struct list_head *qh, *qe;
4649 struct bfa_fcs_rport_s *rport = NULL;
4650 int i;
4651 struct bfa_fcs_s *fcs;
4652
4653 if (port == NULL || nrports == 0)
4654 return (wwn_t) 0;
4655
4656 fcs = port->fcs;
4657 bfa_trc(fcs, (u32) nrports);
4658
4659 i = 0;
4660 qh = &port->rport_q;
4661 qe = bfa_q_first(qh);
4662
4663 while ((qe != qh) && (i < nrports)) {
4664 rport = (struct bfa_fcs_rport_s *) qe;
Maggie Zhangf16a1752010-12-09 19:12:32 -08004665 if (bfa_ntoh3b(rport->pid) > 0xFFF000) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004666 qe = bfa_q_next(qe);
4667 bfa_trc(fcs, (u32) rport->pwwn);
4668 bfa_trc(fcs, rport->pid);
4669 bfa_trc(fcs, i);
4670 continue;
4671 }
4672
4673 if (bwwn) {
4674 if (!memcmp(&wwn, &rport->pwwn, 8))
4675 break;
4676 } else {
4677 if (i == index)
4678 break;
4679 }
4680
4681 i++;
4682 qe = bfa_q_next(qe);
4683 }
4684
4685 bfa_trc(fcs, i);
4686 if (rport)
4687 return rport->pwwn;
4688 else
4689 return (wwn_t) 0;
4690}
4691
4692void
4693bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port,
4694 wwn_t rport_wwns[], int *nrports)
4695{
4696 struct list_head *qh, *qe;
4697 struct bfa_fcs_rport_s *rport = NULL;
4698 int i;
4699 struct bfa_fcs_s *fcs;
4700
4701 if (port == NULL || rport_wwns == NULL || *nrports == 0)
4702 return;
4703
4704 fcs = port->fcs;
4705 bfa_trc(fcs, (u32) *nrports);
4706
4707 i = 0;
4708 qh = &port->rport_q;
4709 qe = bfa_q_first(qh);
4710
4711 while ((qe != qh) && (i < *nrports)) {
4712 rport = (struct bfa_fcs_rport_s *) qe;
Maggie Zhangf16a1752010-12-09 19:12:32 -08004713 if (bfa_ntoh3b(rport->pid) > 0xFFF000) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004714 qe = bfa_q_next(qe);
4715 bfa_trc(fcs, (u32) rport->pwwn);
4716 bfa_trc(fcs, rport->pid);
4717 bfa_trc(fcs, i);
4718 continue;
4719 }
4720
4721 rport_wwns[i] = rport->pwwn;
4722
4723 i++;
4724 qe = bfa_q_next(qe);
4725 }
4726
4727 bfa_trc(fcs, i);
4728 *nrports = i;
4729}
4730
4731/*
4732 * Iterate's through all the rport's in the given port to
4733 * determine the maximum operating speed.
4734 *
4735 * !!!! To be used in TRL Functionality only !!!!
4736 */
4737bfa_port_speed_t
4738bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port)
4739{
4740 struct list_head *qh, *qe;
4741 struct bfa_fcs_rport_s *rport = NULL;
4742 struct bfa_fcs_s *fcs;
4743 bfa_port_speed_t max_speed = 0;
4744 struct bfa_port_attr_s port_attr;
4745 bfa_port_speed_t port_speed, rport_speed;
4746 bfa_boolean_t trl_enabled = bfa_fcport_is_ratelim(port->fcs->bfa);
4747
4748
4749 if (port == NULL)
4750 return 0;
4751
4752 fcs = port->fcs;
4753
4754 /* Get Physical port's current speed */
4755 bfa_fcport_get_attr(port->fcs->bfa, &port_attr);
4756 port_speed = port_attr.speed;
4757 bfa_trc(fcs, port_speed);
4758
4759 qh = &port->rport_q;
4760 qe = bfa_q_first(qh);
4761
4762 while (qe != qh) {
4763 rport = (struct bfa_fcs_rport_s *) qe;
Maggie Zhangf16a1752010-12-09 19:12:32 -08004764 if ((bfa_ntoh3b(rport->pid) > 0xFFF000) ||
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004765 (bfa_fcs_rport_get_state(rport) ==
4766 BFA_RPORT_OFFLINE)) {
4767 qe = bfa_q_next(qe);
4768 continue;
4769 }
4770
4771 rport_speed = rport->rpf.rpsc_speed;
4772 if ((trl_enabled) && (rport_speed ==
4773 BFA_PORT_SPEED_UNKNOWN)) {
4774 /* Use default ratelim speed setting */
4775 rport_speed =
4776 bfa_fcport_get_ratelim_speed(port->fcs->bfa);
4777 }
4778
4779 if ((rport_speed == BFA_PORT_SPEED_8GBPS) ||
4780 (rport_speed > port_speed)) {
4781 max_speed = rport_speed;
4782 break;
4783 } else if (rport_speed > max_speed) {
4784 max_speed = rport_speed;
4785 }
4786
4787 qe = bfa_q_next(qe);
4788 }
4789
4790 bfa_trc(fcs, max_speed);
4791 return max_speed;
4792}
4793
4794struct bfa_fcs_lport_s *
4795bfa_fcs_lookup_port(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t lpwwn)
4796{
4797 struct bfa_fcs_vport_s *vport;
4798 bfa_fcs_vf_t *vf;
4799
Jing Huangd4b671c2010-12-26 21:46:35 -08004800 WARN_ON(fcs == NULL);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004801
4802 vf = bfa_fcs_vf_lookup(fcs, vf_id);
4803 if (vf == NULL) {
4804 bfa_trc(fcs, vf_id);
4805 return NULL;
4806 }
4807
4808 if (!lpwwn || (vf->bport.port_cfg.pwwn == lpwwn))
4809 return &vf->bport;
4810
4811 vport = bfa_fcs_fabric_vport_lookup(vf, lpwwn);
4812 if (vport)
4813 return &vport->lport;
4814
4815 return NULL;
4816}
4817
4818/*
4819 * API corresponding to NPIV_VPORT_GETINFO.
4820 */
4821void
4822bfa_fcs_lport_get_info(struct bfa_fcs_lport_s *port,
4823 struct bfa_lport_info_s *port_info)
4824{
4825
4826 bfa_trc(port->fcs, port->fabric->fabric_name);
4827
4828 if (port->vport == NULL) {
4829 /*
4830 * This is a Physical port
4831 */
4832 port_info->port_type = BFA_LPORT_TYPE_PHYSICAL;
4833
4834 /*
4835 * @todo : need to fix the state & reason
4836 */
4837 port_info->port_state = 0;
4838 port_info->offline_reason = 0;
4839
4840 port_info->port_wwn = bfa_fcs_lport_get_pwwn(port);
4841 port_info->node_wwn = bfa_fcs_lport_get_nwwn(port);
4842
4843 port_info->max_vports_supp =
4844 bfa_lps_get_max_vport(port->fcs->bfa);
4845 port_info->num_vports_inuse =
Maggie Zhangf7f73812010-12-09 19:08:43 -08004846 port->fabric->num_vports;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004847 port_info->max_rports_supp = BFA_FCS_MAX_RPORTS_SUPP;
4848 port_info->num_rports_inuse = port->num_rports;
4849 } else {
4850 /*
4851 * This is a virtual port
4852 */
4853 port_info->port_type = BFA_LPORT_TYPE_VIRTUAL;
4854
4855 /*
4856 * @todo : need to fix the state & reason
4857 */
4858 port_info->port_state = 0;
4859 port_info->offline_reason = 0;
4860
4861 port_info->port_wwn = bfa_fcs_lport_get_pwwn(port);
4862 port_info->node_wwn = bfa_fcs_lport_get_nwwn(port);
4863 }
4864}
4865
4866void
4867bfa_fcs_lport_get_stats(struct bfa_fcs_lport_s *fcs_port,
4868 struct bfa_lport_stats_s *port_stats)
4869{
4870 *port_stats = fcs_port->stats;
4871}
4872
4873void
4874bfa_fcs_lport_clear_stats(struct bfa_fcs_lport_s *fcs_port)
4875{
Jing Huang6a18b162010-10-18 17:08:54 -07004876 memset(&fcs_port->stats, 0, sizeof(struct bfa_lport_stats_s));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004877}
4878
Jing Huang5fbe25c2010-10-18 17:17:23 -07004879/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004880 * FCS virtual port state machine
4881 */
4882
4883#define __vport_fcs(__vp) ((__vp)->lport.fcs)
4884#define __vport_pwwn(__vp) ((__vp)->lport.port_cfg.pwwn)
4885#define __vport_nwwn(__vp) ((__vp)->lport.port_cfg.nwwn)
4886#define __vport_bfa(__vp) ((__vp)->lport.fcs->bfa)
4887#define __vport_fcid(__vp) ((__vp)->lport.pid)
4888#define __vport_fabric(__vp) ((__vp)->lport.fabric)
4889#define __vport_vfid(__vp) ((__vp)->lport.fabric->vf_id)
4890
4891#define BFA_FCS_VPORT_MAX_RETRIES 5
4892/*
4893 * Forward declarations
4894 */
4895static void bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport);
4896static void bfa_fcs_vport_timeout(void *vport_arg);
4897static void bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport);
4898static void bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport);
4899
Jing Huang5fbe25c2010-10-18 17:17:23 -07004900/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004901 * fcs_vport_sm FCS virtual port state machine
4902 */
4903
Jing Huang5fbe25c2010-10-18 17:17:23 -07004904/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004905 * VPort State Machine events
4906 */
4907enum bfa_fcs_vport_event {
4908 BFA_FCS_VPORT_SM_CREATE = 1, /* vport create event */
4909 BFA_FCS_VPORT_SM_DELETE = 2, /* vport delete event */
4910 BFA_FCS_VPORT_SM_START = 3, /* vport start request */
4911 BFA_FCS_VPORT_SM_STOP = 4, /* stop: unsupported */
4912 BFA_FCS_VPORT_SM_ONLINE = 5, /* fabric online */
4913 BFA_FCS_VPORT_SM_OFFLINE = 6, /* fabric offline event */
4914 BFA_FCS_VPORT_SM_FRMSENT = 7, /* fdisc/logo sent events */
4915 BFA_FCS_VPORT_SM_RSP_OK = 8, /* good response */
4916 BFA_FCS_VPORT_SM_RSP_ERROR = 9, /* error/bad response */
4917 BFA_FCS_VPORT_SM_TIMEOUT = 10, /* delay timer event */
4918 BFA_FCS_VPORT_SM_DELCOMP = 11, /* lport delete completion */
4919 BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12, /* Dup wnn error*/
4920 BFA_FCS_VPORT_SM_RSP_FAILED = 13, /* non-retryable failure */
4921};
4922
4923static void bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
4924 enum bfa_fcs_vport_event event);
4925static void bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
4926 enum bfa_fcs_vport_event event);
4927static void bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
4928 enum bfa_fcs_vport_event event);
4929static void bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
4930 enum bfa_fcs_vport_event event);
4931static void bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
4932 enum bfa_fcs_vport_event event);
4933static void bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
4934 enum bfa_fcs_vport_event event);
4935static void bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
4936 enum bfa_fcs_vport_event event);
4937static void bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
4938 enum bfa_fcs_vport_event event);
4939static void bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
4940 enum bfa_fcs_vport_event event);
4941static void bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
4942 enum bfa_fcs_vport_event event);
4943
4944static struct bfa_sm_table_s vport_sm_table[] = {
4945 {BFA_SM(bfa_fcs_vport_sm_uninit), BFA_FCS_VPORT_UNINIT},
4946 {BFA_SM(bfa_fcs_vport_sm_created), BFA_FCS_VPORT_CREATED},
4947 {BFA_SM(bfa_fcs_vport_sm_offline), BFA_FCS_VPORT_OFFLINE},
4948 {BFA_SM(bfa_fcs_vport_sm_fdisc), BFA_FCS_VPORT_FDISC},
4949 {BFA_SM(bfa_fcs_vport_sm_fdisc_retry), BFA_FCS_VPORT_FDISC_RETRY},
4950 {BFA_SM(bfa_fcs_vport_sm_online), BFA_FCS_VPORT_ONLINE},
4951 {BFA_SM(bfa_fcs_vport_sm_deleting), BFA_FCS_VPORT_DELETING},
4952 {BFA_SM(bfa_fcs_vport_sm_cleanup), BFA_FCS_VPORT_CLEANUP},
4953 {BFA_SM(bfa_fcs_vport_sm_logo), BFA_FCS_VPORT_LOGO},
4954 {BFA_SM(bfa_fcs_vport_sm_error), BFA_FCS_VPORT_ERROR}
4955};
4956
Jing Huang5fbe25c2010-10-18 17:17:23 -07004957/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004958 * Beginning state.
4959 */
4960static void
4961bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
4962 enum bfa_fcs_vport_event event)
4963{
4964 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
4965 bfa_trc(__vport_fcs(vport), event);
4966
4967 switch (event) {
4968 case BFA_FCS_VPORT_SM_CREATE:
4969 bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
4970 bfa_fcs_fabric_addvport(__vport_fabric(vport), vport);
4971 break;
4972
4973 default:
4974 bfa_sm_fault(__vport_fcs(vport), event);
4975 }
4976}
4977
Jing Huang5fbe25c2010-10-18 17:17:23 -07004978/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004979 * Created state - a start event is required to start up the state machine.
4980 */
4981static void
4982bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
4983 enum bfa_fcs_vport_event event)
4984{
4985 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
4986 bfa_trc(__vport_fcs(vport), event);
4987
4988 switch (event) {
4989 case BFA_FCS_VPORT_SM_START:
Maggie Zhangf7f73812010-12-09 19:08:43 -08004990 if (bfa_sm_cmp_state(__vport_fabric(vport),
4991 bfa_fcs_fabric_sm_online)
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004992 && bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) {
4993 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
4994 bfa_fcs_vport_do_fdisc(vport);
4995 } else {
Jing Huang5fbe25c2010-10-18 17:17:23 -07004996 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004997 * Fabric is offline or not NPIV capable, stay in
4998 * offline state.
4999 */
5000 vport->vport_stats.fab_no_npiv++;
5001 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5002 }
5003 break;
5004
5005 case BFA_FCS_VPORT_SM_DELETE:
5006 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5007 bfa_fcs_lport_delete(&vport->lport);
5008 break;
5009
5010 case BFA_FCS_VPORT_SM_ONLINE:
5011 case BFA_FCS_VPORT_SM_OFFLINE:
Jing Huang5fbe25c2010-10-18 17:17:23 -07005012 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005013 * Ignore ONLINE/OFFLINE events from fabric
5014 * till vport is started.
5015 */
5016 break;
5017
5018 default:
5019 bfa_sm_fault(__vport_fcs(vport), event);
5020 }
5021}
5022
Jing Huang5fbe25c2010-10-18 17:17:23 -07005023/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005024 * Offline state - awaiting ONLINE event from fabric SM.
5025 */
5026static void
5027bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
5028 enum bfa_fcs_vport_event event)
5029{
5030 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5031 bfa_trc(__vport_fcs(vport), event);
5032
5033 switch (event) {
5034 case BFA_FCS_VPORT_SM_DELETE:
5035 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5036 bfa_fcs_lport_delete(&vport->lport);
5037 break;
5038
5039 case BFA_FCS_VPORT_SM_ONLINE:
5040 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
5041 vport->fdisc_retries = 0;
5042 bfa_fcs_vport_do_fdisc(vport);
5043 break;
5044
5045 case BFA_FCS_VPORT_SM_OFFLINE:
5046 /*
5047 * This can happen if the vport couldn't be initialzied
5048 * due the fact that the npiv was not enabled on the switch.
5049 * In that case we will put the vport in offline state.
5050 * However, the link can go down and cause the this event to
5051 * be sent when we are already offline. Ignore it.
5052 */
5053 break;
5054
5055 default:
5056 bfa_sm_fault(__vport_fcs(vport), event);
5057 }
5058}
5059
5060
Jing Huang5fbe25c2010-10-18 17:17:23 -07005061/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005062 * FDISC is sent and awaiting reply from fabric.
5063 */
5064static void
5065bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
5066 enum bfa_fcs_vport_event event)
5067{
5068 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5069 bfa_trc(__vport_fcs(vport), event);
5070
5071 switch (event) {
5072 case BFA_FCS_VPORT_SM_DELETE:
5073 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
Maggie Zhangf7f73812010-12-09 19:08:43 -08005074 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005075 bfa_fcs_lport_delete(&vport->lport);
5076 break;
5077
5078 case BFA_FCS_VPORT_SM_OFFLINE:
5079 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
Maggie Zhangf7f73812010-12-09 19:08:43 -08005080 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005081 break;
5082
5083 case BFA_FCS_VPORT_SM_RSP_OK:
5084 bfa_sm_set_state(vport, bfa_fcs_vport_sm_online);
5085 bfa_fcs_lport_online(&vport->lport);
5086 break;
5087
5088 case BFA_FCS_VPORT_SM_RSP_ERROR:
5089 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_retry);
5090 bfa_timer_start(__vport_bfa(vport), &vport->timer,
5091 bfa_fcs_vport_timeout, vport,
5092 BFA_FCS_RETRY_TIMEOUT);
5093 break;
5094
5095 case BFA_FCS_VPORT_SM_RSP_FAILED:
5096 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5097 break;
5098
5099 case BFA_FCS_VPORT_SM_RSP_DUP_WWN:
5100 bfa_sm_set_state(vport, bfa_fcs_vport_sm_error);
5101 break;
5102
5103 default:
5104 bfa_sm_fault(__vport_fcs(vport), event);
5105 }
5106}
5107
Jing Huang5fbe25c2010-10-18 17:17:23 -07005108/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005109 * FDISC attempt failed - a timer is active to retry FDISC.
5110 */
5111static void
5112bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
5113 enum bfa_fcs_vport_event event)
5114{
5115 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5116 bfa_trc(__vport_fcs(vport), event);
5117
5118 switch (event) {
5119 case BFA_FCS_VPORT_SM_DELETE:
5120 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5121 bfa_timer_stop(&vport->timer);
5122 bfa_fcs_lport_delete(&vport->lport);
5123 break;
5124
5125 case BFA_FCS_VPORT_SM_OFFLINE:
5126 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5127 bfa_timer_stop(&vport->timer);
5128 break;
5129
5130 case BFA_FCS_VPORT_SM_TIMEOUT:
5131 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
5132 vport->vport_stats.fdisc_retries++;
5133 vport->fdisc_retries++;
5134 bfa_fcs_vport_do_fdisc(vport);
5135 break;
5136
5137 default:
5138 bfa_sm_fault(__vport_fcs(vport), event);
5139 }
5140}
5141
Jing Huang5fbe25c2010-10-18 17:17:23 -07005142/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005143 * Vport is online (FDISC is complete).
5144 */
5145static void
5146bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
5147 enum bfa_fcs_vport_event event)
5148{
5149 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5150 bfa_trc(__vport_fcs(vport), event);
5151
5152 switch (event) {
5153 case BFA_FCS_VPORT_SM_DELETE:
5154 bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting);
5155 bfa_fcs_lport_delete(&vport->lport);
5156 break;
5157
5158 case BFA_FCS_VPORT_SM_OFFLINE:
5159 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
Maggie Zhangf7f73812010-12-09 19:08:43 -08005160 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005161 bfa_fcs_lport_offline(&vport->lport);
5162 break;
5163
5164 default:
5165 bfa_sm_fault(__vport_fcs(vport), event);
5166 }
5167}
5168
Jing Huang5fbe25c2010-10-18 17:17:23 -07005169/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005170 * Vport is being deleted - awaiting lport delete completion to send
5171 * LOGO to fabric.
5172 */
5173static void
5174bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
5175 enum bfa_fcs_vport_event event)
5176{
5177 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5178 bfa_trc(__vport_fcs(vport), event);
5179
5180 switch (event) {
5181 case BFA_FCS_VPORT_SM_DELETE:
5182 break;
5183
5184 case BFA_FCS_VPORT_SM_DELCOMP:
5185 bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo);
5186 bfa_fcs_vport_do_logo(vport);
5187 break;
5188
5189 case BFA_FCS_VPORT_SM_OFFLINE:
5190 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5191 break;
5192
5193 default:
5194 bfa_sm_fault(__vport_fcs(vport), event);
5195 }
5196}
5197
Jing Huang5fbe25c2010-10-18 17:17:23 -07005198/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005199 * Error State.
5200 * This state will be set when the Vport Creation fails due
5201 * to errors like Dup WWN. In this state only operation allowed
5202 * is a Vport Delete.
5203 */
5204static void
5205bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
5206 enum bfa_fcs_vport_event event)
5207{
5208 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5209 bfa_trc(__vport_fcs(vport), event);
5210
5211 switch (event) {
5212 case BFA_FCS_VPORT_SM_DELETE:
5213 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5214 bfa_fcs_lport_delete(&vport->lport);
5215 break;
5216
5217 default:
5218 bfa_trc(__vport_fcs(vport), event);
5219 }
5220}
5221
Jing Huang5fbe25c2010-10-18 17:17:23 -07005222/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005223 * Lport cleanup is in progress since vport is being deleted. Fabric is
5224 * offline, so no LOGO is needed to complete vport deletion.
5225 */
5226static void
5227bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
5228 enum bfa_fcs_vport_event event)
5229{
5230 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5231 bfa_trc(__vport_fcs(vport), event);
5232
5233 switch (event) {
5234 case BFA_FCS_VPORT_SM_DELCOMP:
5235 bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
5236 bfa_fcs_vport_free(vport);
5237 break;
5238
5239 case BFA_FCS_VPORT_SM_DELETE:
5240 break;
5241
5242 default:
5243 bfa_sm_fault(__vport_fcs(vport), event);
5244 }
5245}
5246
Jing Huang5fbe25c2010-10-18 17:17:23 -07005247/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005248 * LOGO is sent to fabric. Vport delete is in progress. Lport delete cleanup
5249 * is done.
5250 */
5251static void
5252bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
5253 enum bfa_fcs_vport_event event)
5254{
5255 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5256 bfa_trc(__vport_fcs(vport), event);
5257
5258 switch (event) {
5259 case BFA_FCS_VPORT_SM_OFFLINE:
Maggie Zhangf7f73812010-12-09 19:08:43 -08005260 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005261 /*
5262 * !!! fall through !!!
5263 */
5264
5265 case BFA_FCS_VPORT_SM_RSP_OK:
5266 case BFA_FCS_VPORT_SM_RSP_ERROR:
5267 bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
5268 bfa_fcs_vport_free(vport);
5269 break;
5270
5271 case BFA_FCS_VPORT_SM_DELETE:
5272 break;
5273
5274 default:
5275 bfa_sm_fault(__vport_fcs(vport), event);
5276 }
5277}
5278
5279
5280
Jing Huang5fbe25c2010-10-18 17:17:23 -07005281/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005282 * fcs_vport_private FCS virtual port private functions
5283 */
Jing Huang5fbe25c2010-10-18 17:17:23 -07005284/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005285 * This routine will be called to send a FDISC command.
5286 */
5287static void
5288bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport)
5289{
5290 bfa_lps_fdisc(vport->lps, vport,
5291 bfa_fcport_get_maxfrsize(__vport_bfa(vport)),
5292 __vport_pwwn(vport), __vport_nwwn(vport));
5293 vport->vport_stats.fdisc_sent++;
5294}
5295
5296static void
5297bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport)
5298{
Maggie Zhangf7f73812010-12-09 19:08:43 -08005299 u8 lsrjt_rsn = vport->lps->lsrjt_rsn;
5300 u8 lsrjt_expl = vport->lps->lsrjt_expl;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005301
5302 bfa_trc(__vport_fcs(vport), lsrjt_rsn);
5303 bfa_trc(__vport_fcs(vport), lsrjt_expl);
5304
5305 /* For certain reason codes, we don't want to retry. */
Maggie Zhangf7f73812010-12-09 19:08:43 -08005306 switch (vport->lps->lsrjt_expl) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005307 case FC_LS_RJT_EXP_INV_PORT_NAME: /* by brocade */
5308 case FC_LS_RJT_EXP_INVALID_NPORT_ID: /* by Cisco */
5309 if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
5310 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5311 else
5312 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_DUP_WWN);
5313 break;
5314
5315 case FC_LS_RJT_EXP_INSUFF_RES:
5316 /*
5317 * This means max logins per port/switch setting on the
5318 * switch was exceeded.
5319 */
5320 if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
5321 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5322 else
5323 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED);
5324 break;
5325
5326 default:
5327 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5328 }
5329}
5330
Jing Huang5fbe25c2010-10-18 17:17:23 -07005331/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005332 * Called to send a logout to the fabric. Used when a V-Port is
5333 * deleted/stopped.
5334 */
5335static void
5336bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport)
5337{
5338 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5339
5340 vport->vport_stats.logo_sent++;
5341 bfa_lps_fdisclogo(vport->lps);
5342}
5343
5344
Jing Huang5fbe25c2010-10-18 17:17:23 -07005345/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005346 * This routine will be called by bfa_timer on timer timeouts.
5347 *
5348 * param[in] vport - pointer to bfa_fcs_vport_t.
5349 * param[out] vport_status - pointer to return vport status in
5350 *
5351 * return
5352 * void
5353 *
5354 * Special Considerations:
5355 *
5356 * note
5357 */
5358static void
5359bfa_fcs_vport_timeout(void *vport_arg)
5360{
5361 struct bfa_fcs_vport_s *vport = (struct bfa_fcs_vport_s *) vport_arg;
5362
5363 vport->vport_stats.fdisc_timeouts++;
5364 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_TIMEOUT);
5365}
5366
5367static void
5368bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport)
5369{
5370 struct bfad_vport_s *vport_drv =
5371 (struct bfad_vport_s *)vport->vport_drv;
5372
5373 bfa_fcs_fabric_delvport(__vport_fabric(vport), vport);
5374
5375 if (vport_drv->comp_del)
5376 complete(vport_drv->comp_del);
5377
5378 bfa_lps_delete(vport->lps);
5379}
5380
5381
5382
Jing Huang5fbe25c2010-10-18 17:17:23 -07005383/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005384 * fcs_vport_public FCS virtual port public interfaces
5385 */
5386
Jing Huang5fbe25c2010-10-18 17:17:23 -07005387/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005388 * Online notification from fabric SM.
5389 */
5390void
5391bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport)
5392{
5393 vport->vport_stats.fab_online++;
5394 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
5395}
5396
Jing Huang5fbe25c2010-10-18 17:17:23 -07005397/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005398 * Offline notification from fabric SM.
5399 */
5400void
5401bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport)
5402{
5403 vport->vport_stats.fab_offline++;
5404 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
5405}
5406
Jing Huang5fbe25c2010-10-18 17:17:23 -07005407/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005408 * Cleanup notification from fabric SM on link timer expiry.
5409 */
5410void
5411bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport)
5412{
5413 vport->vport_stats.fab_cleanup++;
5414}
Jing Huang5fbe25c2010-10-18 17:17:23 -07005415/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005416 * delete notification from fabric SM. To be invoked from within FCS.
5417 */
5418void
5419bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport)
5420{
5421 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
5422}
5423
Jing Huang5fbe25c2010-10-18 17:17:23 -07005424/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005425 * Delete completion callback from associated lport
5426 */
5427void
5428bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport)
5429{
5430 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELCOMP);
5431}
5432
5433
5434
Jing Huang5fbe25c2010-10-18 17:17:23 -07005435/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005436 * fcs_vport_api Virtual port API
5437 */
5438
Jing Huang5fbe25c2010-10-18 17:17:23 -07005439/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005440 * Use this function to instantiate a new FCS vport object. This
5441 * function will not trigger any HW initialization process (which will be
5442 * done in vport_start() call)
5443 *
5444 * param[in] vport - pointer to bfa_fcs_vport_t. This space
5445 * needs to be allocated by the driver.
5446 * param[in] fcs - FCS instance
5447 * param[in] vport_cfg - vport configuration
5448 * param[in] vf_id - VF_ID if vport is created within a VF.
5449 * FC_VF_ID_NULL to specify base fabric.
5450 * param[in] vport_drv - Opaque handle back to the driver's vport
5451 * structure
5452 *
5453 * retval BFA_STATUS_OK - on success.
5454 * retval BFA_STATUS_FAILED - on failure.
5455 */
5456bfa_status_t
5457bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
5458 u16 vf_id, struct bfa_lport_cfg_s *vport_cfg,
5459 struct bfad_vport_s *vport_drv)
5460{
5461 if (vport_cfg->pwwn == 0)
5462 return BFA_STATUS_INVALID_WWN;
5463
5464 if (bfa_fcs_lport_get_pwwn(&fcs->fabric.bport) == vport_cfg->pwwn)
5465 return BFA_STATUS_VPORT_WWN_BP;
5466
5467 if (bfa_fcs_vport_lookup(fcs, vf_id, vport_cfg->pwwn) != NULL)
5468 return BFA_STATUS_VPORT_EXISTS;
5469
Maggie Zhangf7f73812010-12-09 19:08:43 -08005470 if (fcs->fabric.num_vports ==
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005471 bfa_lps_get_max_vport(fcs->bfa))
5472 return BFA_STATUS_VPORT_MAX;
5473
5474 vport->lps = bfa_lps_alloc(fcs->bfa);
5475 if (!vport->lps)
5476 return BFA_STATUS_VPORT_MAX;
5477
5478 vport->vport_drv = vport_drv;
5479 vport_cfg->preboot_vp = BFA_FALSE;
5480
5481 bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
5482 bfa_fcs_lport_attach(&vport->lport, fcs, vf_id, vport);
5483 bfa_fcs_lport_init(&vport->lport, vport_cfg);
5484 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_CREATE);
5485
5486 return BFA_STATUS_OK;
5487}
5488
Jing Huang5fbe25c2010-10-18 17:17:23 -07005489/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005490 * Use this function to instantiate a new FCS PBC vport object. This
5491 * function will not trigger any HW initialization process (which will be
5492 * done in vport_start() call)
5493 *
5494 * param[in] vport - pointer to bfa_fcs_vport_t. This space
5495 * needs to be allocated by the driver.
5496 * param[in] fcs - FCS instance
5497 * param[in] vport_cfg - vport configuration
5498 * param[in] vf_id - VF_ID if vport is created within a VF.
5499 * FC_VF_ID_NULL to specify base fabric.
5500 * param[in] vport_drv - Opaque handle back to the driver's vport
5501 * structure
5502 *
5503 * retval BFA_STATUS_OK - on success.
5504 * retval BFA_STATUS_FAILED - on failure.
5505 */
5506bfa_status_t
5507bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
5508 u16 vf_id, struct bfa_lport_cfg_s *vport_cfg,
5509 struct bfad_vport_s *vport_drv)
5510{
5511 bfa_status_t rc;
5512
5513 rc = bfa_fcs_vport_create(vport, fcs, vf_id, vport_cfg, vport_drv);
5514 vport->lport.port_cfg.preboot_vp = BFA_TRUE;
5515
5516 return rc;
5517}
5518
Jing Huang5fbe25c2010-10-18 17:17:23 -07005519/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005520 * Use this function to findout if this is a pbc vport or not.
5521 *
5522 * @param[in] vport - pointer to bfa_fcs_vport_t.
5523 *
5524 * @returns None
5525 */
5526bfa_boolean_t
5527bfa_fcs_is_pbc_vport(struct bfa_fcs_vport_s *vport)
5528{
5529
5530 if (vport && (vport->lport.port_cfg.preboot_vp == BFA_TRUE))
5531 return BFA_TRUE;
5532 else
5533 return BFA_FALSE;
5534
5535}
5536
Jing Huang5fbe25c2010-10-18 17:17:23 -07005537/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005538 * Use this function initialize the vport.
5539 *
5540 * @param[in] vport - pointer to bfa_fcs_vport_t.
5541 *
5542 * @returns None
5543 */
5544bfa_status_t
5545bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport)
5546{
5547 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_START);
5548
5549 return BFA_STATUS_OK;
5550}
5551
Jing Huang5fbe25c2010-10-18 17:17:23 -07005552/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005553 * Use this function quiese the vport object. This function will return
5554 * immediately, when the vport is actually stopped, the
5555 * bfa_drv_vport_stop_cb() will be called.
5556 *
5557 * param[in] vport - pointer to bfa_fcs_vport_t.
5558 *
5559 * return None
5560 */
5561bfa_status_t
5562bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport)
5563{
5564 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP);
5565
5566 return BFA_STATUS_OK;
5567}
5568
Jing Huang5fbe25c2010-10-18 17:17:23 -07005569/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005570 * Use this function to delete a vport object. Fabric object should
5571 * be stopped before this function call.
5572 *
5573 * !!!!!!! Donot invoke this from within FCS !!!!!!!
5574 *
5575 * param[in] vport - pointer to bfa_fcs_vport_t.
5576 *
5577 * return None
5578 */
5579bfa_status_t
5580bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport)
5581{
5582
5583 if (vport->lport.port_cfg.preboot_vp)
5584 return BFA_STATUS_PBC;
5585
5586 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
5587
5588 return BFA_STATUS_OK;
5589}
5590
Jing Huang5fbe25c2010-10-18 17:17:23 -07005591/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005592 * Use this function to get vport's current status info.
5593 *
5594 * param[in] vport pointer to bfa_fcs_vport_t.
5595 * param[out] attr pointer to return vport attributes
5596 *
5597 * return None
5598 */
5599void
5600bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport,
5601 struct bfa_vport_attr_s *attr)
5602{
5603 if (vport == NULL || attr == NULL)
5604 return;
5605
Jing Huang6a18b162010-10-18 17:08:54 -07005606 memset(attr, 0, sizeof(struct bfa_vport_attr_s));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005607
5608 bfa_fcs_lport_get_attr(&vport->lport, &attr->port_attr);
5609 attr->vport_state = bfa_sm_to_state(vport_sm_table, vport->sm);
5610}
5611
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005612
Jing Huang5fbe25c2010-10-18 17:17:23 -07005613/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005614 * Lookup a virtual port. Excludes base port from lookup.
5615 */
5616struct bfa_fcs_vport_s *
5617bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t vpwwn)
5618{
5619 struct bfa_fcs_vport_s *vport;
5620 struct bfa_fcs_fabric_s *fabric;
5621
5622 bfa_trc(fcs, vf_id);
5623 bfa_trc(fcs, vpwwn);
5624
5625 fabric = bfa_fcs_vf_lookup(fcs, vf_id);
5626 if (!fabric) {
5627 bfa_trc(fcs, vf_id);
5628 return NULL;
5629 }
5630
5631 vport = bfa_fcs_fabric_vport_lookup(fabric, vpwwn);
5632 return vport;
5633}
5634
Jing Huang5fbe25c2010-10-18 17:17:23 -07005635/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005636 * FDISC Response
5637 */
5638void
5639bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status)
5640{
5641 struct bfa_fcs_vport_s *vport = uarg;
5642
5643 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5644 bfa_trc(__vport_fcs(vport), status);
5645
5646 switch (status) {
5647 case BFA_STATUS_OK:
5648 /*
Uwe Kleine-Königb5950762010-11-01 15:38:34 -04005649 * Initialize the V-Port fields
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005650 */
Maggie Zhangf7f73812010-12-09 19:08:43 -08005651 __vport_fcid(vport) = vport->lps->lp_pid;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005652 vport->vport_stats.fdisc_accepts++;
5653 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
5654 break;
5655
5656 case BFA_STATUS_INVALID_MAC:
5657 /* Only for CNA */
5658 vport->vport_stats.fdisc_acc_bad++;
5659 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5660
5661 break;
5662
5663 case BFA_STATUS_EPROTOCOL:
Maggie Zhangf7f73812010-12-09 19:08:43 -08005664 switch (vport->lps->ext_status) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005665 case BFA_EPROTO_BAD_ACCEPT:
5666 vport->vport_stats.fdisc_acc_bad++;
5667 break;
5668
5669 case BFA_EPROTO_UNKNOWN_RSP:
5670 vport->vport_stats.fdisc_unknown_rsp++;
5671 break;
5672
5673 default:
5674 break;
5675 }
5676
5677 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5678 break;
5679
5680 case BFA_STATUS_FABRIC_RJT:
5681 vport->vport_stats.fdisc_rejects++;
5682 bfa_fcs_vport_fdisc_rejected(vport);
5683 break;
5684
5685 default:
5686 vport->vport_stats.fdisc_rsp_err++;
5687 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5688 }
5689}
5690
Jing Huang5fbe25c2010-10-18 17:17:23 -07005691/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005692 * LOGO response
5693 */
5694void
5695bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg)
5696{
5697 struct bfa_fcs_vport_s *vport = uarg;
5698 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
5699}
5700
Jing Huang5fbe25c2010-10-18 17:17:23 -07005701/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005702 * Received clear virtual link
5703 */
5704void
5705bfa_cb_lps_cvl_event(void *bfad, void *uarg)
5706{
5707 struct bfa_fcs_vport_s *vport = uarg;
5708
5709 /* Send an Offline followed by an ONLINE */
5710 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
5711 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
5712}