bfa_fcs_lport.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940
  1. /*
  2. * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
  3. * 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. /**
  18. * bfa_fcs_port.c BFA FCS port
  19. */
  20. #include <fcs/bfa_fcs.h>
  21. #include <fcs/bfa_fcs_lport.h>
  22. #include <fcs/bfa_fcs_rport.h>
  23. #include <fcb/bfa_fcb_port.h>
  24. #include <bfa_svc.h>
  25. #include <log/bfa_log_fcs.h>
  26. #include "fcs.h"
  27. #include "fcs_lport.h"
  28. #include "fcs_vport.h"
  29. #include "fcs_rport.h"
  30. #include "fcs_fcxp.h"
  31. #include "fcs_trcmod.h"
  32. #include "lport_priv.h"
  33. #include <aen/bfa_aen_lport.h>
  34. BFA_TRC_FILE(FCS, PORT);
  35. /**
  36. * Forward declarations
  37. */
  38. static void bfa_fcs_port_aen_post(struct bfa_fcs_port_s *port,
  39. enum bfa_lport_aen_event event);
  40. static void bfa_fcs_port_send_ls_rjt(struct bfa_fcs_port_s *port,
  41. struct fchs_s *rx_fchs, u8 reason_code,
  42. u8 reason_code_expl);
  43. static void bfa_fcs_port_plogi(struct bfa_fcs_port_s *port,
  44. struct fchs_s *rx_fchs,
  45. struct fc_logi_s *plogi);
  46. static void bfa_fcs_port_online_actions(struct bfa_fcs_port_s *port);
  47. static void bfa_fcs_port_offline_actions(struct bfa_fcs_port_s *port);
  48. static void bfa_fcs_port_unknown_init(struct bfa_fcs_port_s *port);
  49. static void bfa_fcs_port_unknown_online(struct bfa_fcs_port_s *port);
  50. static void bfa_fcs_port_unknown_offline(struct bfa_fcs_port_s *port);
  51. static void bfa_fcs_port_deleted(struct bfa_fcs_port_s *port);
  52. static void bfa_fcs_port_echo(struct bfa_fcs_port_s *port,
  53. struct fchs_s *rx_fchs,
  54. struct fc_echo_s *echo, u16 len);
  55. static void bfa_fcs_port_rnid(struct bfa_fcs_port_s *port,
  56. struct fchs_s *rx_fchs,
  57. struct fc_rnid_cmd_s *rnid, u16 len);
  58. static void bfa_fs_port_get_gen_topo_data(struct bfa_fcs_port_s *port,
  59. struct fc_rnid_general_topology_data_s *gen_topo_data);
  60. static struct {
  61. void (*init) (struct bfa_fcs_port_s *port);
  62. void (*online) (struct bfa_fcs_port_s *port);
  63. void (*offline) (struct bfa_fcs_port_s *port);
  64. } __port_action[] = {
  65. {
  66. bfa_fcs_port_unknown_init, bfa_fcs_port_unknown_online,
  67. bfa_fcs_port_unknown_offline}, {
  68. bfa_fcs_port_fab_init, bfa_fcs_port_fab_online,
  69. bfa_fcs_port_fab_offline}, {
  70. bfa_fcs_port_loop_init, bfa_fcs_port_loop_online,
  71. bfa_fcs_port_loop_offline}, {
  72. bfa_fcs_port_n2n_init, bfa_fcs_port_n2n_online,
  73. bfa_fcs_port_n2n_offline},};
  74. /**
  75. * fcs_port_sm FCS logical port state machine
  76. */
  77. enum bfa_fcs_port_event {
  78. BFA_FCS_PORT_SM_CREATE = 1,
  79. BFA_FCS_PORT_SM_ONLINE = 2,
  80. BFA_FCS_PORT_SM_OFFLINE = 3,
  81. BFA_FCS_PORT_SM_DELETE = 4,
  82. BFA_FCS_PORT_SM_DELRPORT = 5,
  83. };
  84. static void bfa_fcs_port_sm_uninit(struct bfa_fcs_port_s *port,
  85. enum bfa_fcs_port_event event);
  86. static void bfa_fcs_port_sm_init(struct bfa_fcs_port_s *port,
  87. enum bfa_fcs_port_event event);
  88. static void bfa_fcs_port_sm_online(struct bfa_fcs_port_s *port,
  89. enum bfa_fcs_port_event event);
  90. static void bfa_fcs_port_sm_offline(struct bfa_fcs_port_s *port,
  91. enum bfa_fcs_port_event event);
  92. static void bfa_fcs_port_sm_deleting(struct bfa_fcs_port_s *port,
  93. enum bfa_fcs_port_event event);
  94. static void
  95. bfa_fcs_port_sm_uninit(struct bfa_fcs_port_s *port,
  96. enum bfa_fcs_port_event event)
  97. {
  98. bfa_trc(port->fcs, port->port_cfg.pwwn);
  99. bfa_trc(port->fcs, event);
  100. switch (event) {
  101. case BFA_FCS_PORT_SM_CREATE:
  102. bfa_sm_set_state(port, bfa_fcs_port_sm_init);
  103. break;
  104. default:
  105. bfa_assert(0);
  106. }
  107. }
  108. static void
  109. bfa_fcs_port_sm_init(struct bfa_fcs_port_s *port, enum bfa_fcs_port_event event)
  110. {
  111. bfa_trc(port->fcs, port->port_cfg.pwwn);
  112. bfa_trc(port->fcs, event);
  113. switch (event) {
  114. case BFA_FCS_PORT_SM_ONLINE:
  115. bfa_sm_set_state(port, bfa_fcs_port_sm_online);
  116. bfa_fcs_port_online_actions(port);
  117. break;
  118. case BFA_FCS_PORT_SM_DELETE:
  119. bfa_sm_set_state(port, bfa_fcs_port_sm_uninit);
  120. bfa_fcs_port_deleted(port);
  121. break;
  122. default:
  123. bfa_assert(0);
  124. }
  125. }
  126. static void
  127. bfa_fcs_port_sm_online(struct bfa_fcs_port_s *port,
  128. enum bfa_fcs_port_event event)
  129. {
  130. struct bfa_fcs_rport_s *rport;
  131. struct list_head *qe, *qen;
  132. bfa_trc(port->fcs, port->port_cfg.pwwn);
  133. bfa_trc(port->fcs, event);
  134. switch (event) {
  135. case BFA_FCS_PORT_SM_OFFLINE:
  136. bfa_sm_set_state(port, bfa_fcs_port_sm_offline);
  137. bfa_fcs_port_offline_actions(port);
  138. break;
  139. case BFA_FCS_PORT_SM_DELETE:
  140. __port_action[port->fabric->fab_type].offline(port);
  141. if (port->num_rports == 0) {
  142. bfa_sm_set_state(port, bfa_fcs_port_sm_uninit);
  143. bfa_fcs_port_deleted(port);
  144. } else {
  145. bfa_sm_set_state(port, bfa_fcs_port_sm_deleting);
  146. list_for_each_safe(qe, qen, &port->rport_q) {
  147. rport = (struct bfa_fcs_rport_s *)qe;
  148. bfa_fcs_rport_delete(rport);
  149. }
  150. }
  151. break;
  152. case BFA_FCS_PORT_SM_DELRPORT:
  153. break;
  154. default:
  155. bfa_assert(0);
  156. }
  157. }
  158. static void
  159. bfa_fcs_port_sm_offline(struct bfa_fcs_port_s *port,
  160. enum bfa_fcs_port_event event)
  161. {
  162. struct bfa_fcs_rport_s *rport;
  163. struct list_head *qe, *qen;
  164. bfa_trc(port->fcs, port->port_cfg.pwwn);
  165. bfa_trc(port->fcs, event);
  166. switch (event) {
  167. case BFA_FCS_PORT_SM_ONLINE:
  168. bfa_sm_set_state(port, bfa_fcs_port_sm_online);
  169. bfa_fcs_port_online_actions(port);
  170. break;
  171. case BFA_FCS_PORT_SM_DELETE:
  172. if (port->num_rports == 0) {
  173. bfa_sm_set_state(port, bfa_fcs_port_sm_uninit);
  174. bfa_fcs_port_deleted(port);
  175. } else {
  176. bfa_sm_set_state(port, bfa_fcs_port_sm_deleting);
  177. list_for_each_safe(qe, qen, &port->rport_q) {
  178. rport = (struct bfa_fcs_rport_s *)qe;
  179. bfa_fcs_rport_delete(rport);
  180. }
  181. }
  182. break;
  183. case BFA_FCS_PORT_SM_DELRPORT:
  184. case BFA_FCS_PORT_SM_OFFLINE:
  185. break;
  186. default:
  187. bfa_assert(0);
  188. }
  189. }
  190. static void
  191. bfa_fcs_port_sm_deleting(struct bfa_fcs_port_s *port,
  192. enum bfa_fcs_port_event event)
  193. {
  194. bfa_trc(port->fcs, port->port_cfg.pwwn);
  195. bfa_trc(port->fcs, event);
  196. switch (event) {
  197. case BFA_FCS_PORT_SM_DELRPORT:
  198. if (port->num_rports == 0) {
  199. bfa_sm_set_state(port, bfa_fcs_port_sm_uninit);
  200. bfa_fcs_port_deleted(port);
  201. }
  202. break;
  203. default:
  204. bfa_assert(0);
  205. }
  206. }
  207. /**
  208. * fcs_port_pvt
  209. */
  210. /**
  211. * Send AEN notification
  212. */
  213. static void
  214. bfa_fcs_port_aen_post(struct bfa_fcs_port_s *port,
  215. enum bfa_lport_aen_event event)
  216. {
  217. union bfa_aen_data_u aen_data;
  218. struct bfa_log_mod_s *logmod = port->fcs->logm;
  219. enum bfa_port_role role = port->port_cfg.roles;
  220. wwn_t lpwwn = bfa_fcs_port_get_pwwn(port);
  221. char lpwwn_ptr[BFA_STRING_32];
  222. char *role_str[BFA_PORT_ROLE_FCP_MAX / 2 + 1] =
  223. { "Initiator", "Target", "IPFC" };
  224. wwn2str(lpwwn_ptr, lpwwn);
  225. bfa_assert(role <= BFA_PORT_ROLE_FCP_MAX);
  226. switch (event) {
  227. case BFA_LPORT_AEN_ONLINE:
  228. bfa_log(logmod, BFA_AEN_LPORT_ONLINE, lpwwn_ptr,
  229. role_str[role / 2]);
  230. break;
  231. case BFA_LPORT_AEN_OFFLINE:
  232. bfa_log(logmod, BFA_AEN_LPORT_OFFLINE, lpwwn_ptr,
  233. role_str[role / 2]);
  234. break;
  235. case BFA_LPORT_AEN_NEW:
  236. bfa_log(logmod, BFA_AEN_LPORT_NEW, lpwwn_ptr,
  237. role_str[role / 2]);
  238. break;
  239. case BFA_LPORT_AEN_DELETE:
  240. bfa_log(logmod, BFA_AEN_LPORT_DELETE, lpwwn_ptr,
  241. role_str[role / 2]);
  242. break;
  243. case BFA_LPORT_AEN_DISCONNECT:
  244. bfa_log(logmod, BFA_AEN_LPORT_DISCONNECT, lpwwn_ptr,
  245. role_str[role / 2]);
  246. break;
  247. default:
  248. break;
  249. }
  250. aen_data.lport.vf_id = port->fabric->vf_id;
  251. aen_data.lport.roles = role;
  252. aen_data.lport.ppwwn =
  253. bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(port->fcs));
  254. aen_data.lport.lpwwn = lpwwn;
  255. }
  256. /*
  257. * Send a LS reject
  258. */
  259. static void
  260. bfa_fcs_port_send_ls_rjt(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
  261. u8 reason_code, u8 reason_code_expl)
  262. {
  263. struct fchs_s fchs;
  264. struct bfa_fcxp_s *fcxp;
  265. struct bfa_rport_s *bfa_rport = NULL;
  266. int len;
  267. bfa_trc(port->fcs, rx_fchs->s_id);
  268. fcxp = bfa_fcs_fcxp_alloc(port->fcs);
  269. if (!fcxp)
  270. return;
  271. len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
  272. bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
  273. reason_code, reason_code_expl);
  274. bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
  275. BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
  276. FC_MAX_PDUSZ, 0);
  277. }
  278. /**
  279. * Process incoming plogi from a remote port.
  280. */
  281. static void
  282. bfa_fcs_port_plogi(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
  283. struct fc_logi_s *plogi)
  284. {
  285. struct bfa_fcs_rport_s *rport;
  286. bfa_trc(port->fcs, rx_fchs->d_id);
  287. bfa_trc(port->fcs, rx_fchs->s_id);
  288. /*
  289. * If min cfg mode is enabled, drop any incoming PLOGIs
  290. */
  291. if (__fcs_min_cfg(port->fcs)) {
  292. bfa_trc(port->fcs, rx_fchs->s_id);
  293. return;
  294. }
  295. if (fc_plogi_parse(rx_fchs) != FC_PARSE_OK) {
  296. bfa_trc(port->fcs, rx_fchs->s_id);
  297. /*
  298. * send a LS reject
  299. */
  300. bfa_fcs_port_send_ls_rjt(port, rx_fchs,
  301. FC_LS_RJT_RSN_PROTOCOL_ERROR,
  302. FC_LS_RJT_EXP_SPARMS_ERR_OPTIONS);
  303. return;
  304. }
  305. /**
  306. * Direct Attach P2P mode : verify address assigned by the r-port.
  307. */
  308. if ((!bfa_fcs_fabric_is_switched(port->fabric))
  309. &&
  310. (memcmp
  311. ((void *)&bfa_fcs_port_get_pwwn(port), (void *)&plogi->port_name,
  312. sizeof(wwn_t)) < 0)) {
  313. if (BFA_FCS_PID_IS_WKA(rx_fchs->d_id)) {
  314. /*
  315. * Address assigned to us cannot be a WKA
  316. */
  317. bfa_fcs_port_send_ls_rjt(port, rx_fchs,
  318. FC_LS_RJT_RSN_PROTOCOL_ERROR,
  319. FC_LS_RJT_EXP_INVALID_NPORT_ID);
  320. return;
  321. }
  322. port->pid = rx_fchs->d_id;
  323. }
  324. /**
  325. * First, check if we know the device by pwwn.
  326. */
  327. rport = bfa_fcs_port_get_rport_by_pwwn(port, plogi->port_name);
  328. if (rport) {
  329. /**
  330. * Direct Attach P2P mode: handle address assigned by the rport.
  331. */
  332. if ((!bfa_fcs_fabric_is_switched(port->fabric))
  333. &&
  334. (memcmp
  335. ((void *)&bfa_fcs_port_get_pwwn(port),
  336. (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
  337. port->pid = rx_fchs->d_id;
  338. rport->pid = rx_fchs->s_id;
  339. }
  340. bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
  341. return;
  342. }
  343. /**
  344. * Next, lookup rport by PID.
  345. */
  346. rport = bfa_fcs_port_get_rport_by_pid(port, rx_fchs->s_id);
  347. if (!rport) {
  348. /**
  349. * Inbound PLOGI from a new device.
  350. */
  351. bfa_fcs_rport_plogi_create(port, rx_fchs, plogi);
  352. return;
  353. }
  354. /**
  355. * Rport is known only by PID.
  356. */
  357. if (rport->pwwn) {
  358. /**
  359. * This is a different device with the same pid. Old device
  360. * disappeared. Send implicit LOGO to old device.
  361. */
  362. bfa_assert(rport->pwwn != plogi->port_name);
  363. bfa_fcs_rport_logo_imp(rport);
  364. /**
  365. * Inbound PLOGI from a new device (with old PID).
  366. */
  367. bfa_fcs_rport_plogi_create(port, rx_fchs, plogi);
  368. return;
  369. }
  370. /**
  371. * PLOGI crossing each other.
  372. */
  373. bfa_assert(rport->pwwn == WWN_NULL);
  374. bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
  375. }
  376. /*
  377. * Process incoming ECHO.
  378. * Since it does not require a login, it is processed here.
  379. */
  380. static void
  381. bfa_fcs_port_echo(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
  382. struct fc_echo_s *echo, u16 rx_len)
  383. {
  384. struct fchs_s fchs;
  385. struct bfa_fcxp_s *fcxp;
  386. struct bfa_rport_s *bfa_rport = NULL;
  387. int len, pyld_len;
  388. bfa_trc(port->fcs, rx_fchs->s_id);
  389. bfa_trc(port->fcs, rx_fchs->d_id);
  390. bfa_trc(port->fcs, rx_len);
  391. fcxp = bfa_fcs_fcxp_alloc(port->fcs);
  392. if (!fcxp)
  393. return;
  394. len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
  395. bfa_fcs_port_get_fcid(port), rx_fchs->ox_id);
  396. /*
  397. * Copy the payload (if any) from the echo frame
  398. */
  399. pyld_len = rx_len - sizeof(struct fchs_s);
  400. bfa_trc(port->fcs, pyld_len);
  401. if (pyld_len > len)
  402. memcpy(((u8 *) bfa_fcxp_get_reqbuf(fcxp)) +
  403. sizeof(struct fc_echo_s), (echo + 1),
  404. (pyld_len - sizeof(struct fc_echo_s)));
  405. bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
  406. BFA_FALSE, FC_CLASS_3, pyld_len, &fchs, NULL, NULL,
  407. FC_MAX_PDUSZ, 0);
  408. }
  409. /*
  410. * Process incoming RNID.
  411. * Since it does not require a login, it is processed here.
  412. */
  413. static void
  414. bfa_fcs_port_rnid(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
  415. struct fc_rnid_cmd_s *rnid, u16 rx_len)
  416. {
  417. struct fc_rnid_common_id_data_s common_id_data;
  418. struct fc_rnid_general_topology_data_s gen_topo_data;
  419. struct fchs_s fchs;
  420. struct bfa_fcxp_s *fcxp;
  421. struct bfa_rport_s *bfa_rport = NULL;
  422. u16 len;
  423. u32 data_format;
  424. bfa_trc(port->fcs, rx_fchs->s_id);
  425. bfa_trc(port->fcs, rx_fchs->d_id);
  426. bfa_trc(port->fcs, rx_len);
  427. fcxp = bfa_fcs_fcxp_alloc(port->fcs);
  428. if (!fcxp)
  429. return;
  430. /*
  431. * Check Node Indentification Data Format
  432. * We only support General Topology Discovery Format.
  433. * For any other requested Data Formats, we return Common Node Id Data
  434. * only, as per FC-LS.
  435. */
  436. bfa_trc(port->fcs, rnid->node_id_data_format);
  437. if (rnid->node_id_data_format == RNID_NODEID_DATA_FORMAT_DISCOVERY) {
  438. data_format = RNID_NODEID_DATA_FORMAT_DISCOVERY;
  439. /*
  440. * Get General topology data for this port
  441. */
  442. bfa_fs_port_get_gen_topo_data(port, &gen_topo_data);
  443. } else {
  444. data_format = RNID_NODEID_DATA_FORMAT_COMMON;
  445. }
  446. /*
  447. * Copy the Node Id Info
  448. */
  449. common_id_data.port_name = bfa_fcs_port_get_pwwn(port);
  450. common_id_data.node_name = bfa_fcs_port_get_nwwn(port);
  451. len = fc_rnid_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
  452. bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
  453. data_format, &common_id_data, &gen_topo_data);
  454. bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
  455. BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
  456. FC_MAX_PDUSZ, 0);
  457. return;
  458. }
  459. /*
  460. * Fill out General Topolpgy Discovery Data for RNID ELS.
  461. */
  462. static void
  463. bfa_fs_port_get_gen_topo_data(struct bfa_fcs_port_s *port,
  464. struct fc_rnid_general_topology_data_s *gen_topo_data)
  465. {
  466. bfa_os_memset(gen_topo_data, 0,
  467. sizeof(struct fc_rnid_general_topology_data_s));
  468. gen_topo_data->asso_type = bfa_os_htonl(RNID_ASSOCIATED_TYPE_HOST);
  469. gen_topo_data->phy_port_num = 0; /* @todo */
  470. gen_topo_data->num_attached_nodes = bfa_os_htonl(1);
  471. }
  472. static void
  473. bfa_fcs_port_online_actions(struct bfa_fcs_port_s *port)
  474. {
  475. bfa_trc(port->fcs, port->fabric->oper_type);
  476. __port_action[port->fabric->fab_type].init(port);
  477. __port_action[port->fabric->fab_type].online(port);
  478. bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_ONLINE);
  479. bfa_fcb_port_online(port->fcs->bfad, port->port_cfg.roles,
  480. port->fabric->vf_drv, (port->vport == NULL) ?
  481. NULL : port->vport->vport_drv);
  482. }
  483. static void
  484. bfa_fcs_port_offline_actions(struct bfa_fcs_port_s *port)
  485. {
  486. struct list_head *qe, *qen;
  487. struct bfa_fcs_rport_s *rport;
  488. bfa_trc(port->fcs, port->fabric->oper_type);
  489. __port_action[port->fabric->fab_type].offline(port);
  490. if (bfa_fcs_fabric_is_online(port->fabric) == BFA_TRUE) {
  491. bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_DISCONNECT);
  492. } else {
  493. bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_OFFLINE);
  494. }
  495. bfa_fcb_port_offline(port->fcs->bfad, port->port_cfg.roles,
  496. port->fabric->vf_drv,
  497. (port->vport == NULL) ? NULL : port->vport->vport_drv);
  498. list_for_each_safe(qe, qen, &port->rport_q) {
  499. rport = (struct bfa_fcs_rport_s *)qe;
  500. bfa_fcs_rport_offline(rport);
  501. }
  502. }
  503. static void
  504. bfa_fcs_port_unknown_init(struct bfa_fcs_port_s *port)
  505. {
  506. bfa_assert(0);
  507. }
  508. static void
  509. bfa_fcs_port_unknown_online(struct bfa_fcs_port_s *port)
  510. {
  511. bfa_assert(0);
  512. }
  513. static void
  514. bfa_fcs_port_unknown_offline(struct bfa_fcs_port_s *port)
  515. {
  516. bfa_assert(0);
  517. }
  518. static void
  519. bfa_fcs_port_deleted(struct bfa_fcs_port_s *port)
  520. {
  521. bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_DELETE);
  522. /*
  523. * Base port will be deleted by the OS driver
  524. */
  525. if (port->vport) {
  526. bfa_fcb_port_delete(port->fcs->bfad, port->port_cfg.roles,
  527. port->fabric->vf_drv,
  528. port->vport ? port->vport->vport_drv : NULL);
  529. bfa_fcs_vport_delete_comp(port->vport);
  530. } else {
  531. bfa_fcs_fabric_port_delete_comp(port->fabric);
  532. }
  533. }
  534. /**
  535. * fcs_lport_api BFA FCS port API
  536. */
  537. /**
  538. * Module initialization
  539. */
  540. void
  541. bfa_fcs_port_modinit(struct bfa_fcs_s *fcs)
  542. {
  543. }
  544. /**
  545. * Module cleanup
  546. */
  547. void
  548. bfa_fcs_port_modexit(struct bfa_fcs_s *fcs)
  549. {
  550. bfa_fcs_modexit_comp(fcs);
  551. }
  552. /**
  553. * Unsolicited frame receive handling.
  554. */
  555. void
  556. bfa_fcs_port_uf_recv(struct bfa_fcs_port_s *lport, struct fchs_s *fchs,
  557. u16 len)
  558. {
  559. u32 pid = fchs->s_id;
  560. struct bfa_fcs_rport_s *rport = NULL;
  561. struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
  562. bfa_stats(lport, uf_recvs);
  563. if (!bfa_fcs_port_is_online(lport)) {
  564. bfa_stats(lport, uf_recv_drops);
  565. return;
  566. }
  567. /**
  568. * First, handle ELSs that donot require a login.
  569. */
  570. /*
  571. * Handle PLOGI first
  572. */
  573. if ((fchs->type == FC_TYPE_ELS) &&
  574. (els_cmd->els_code == FC_ELS_PLOGI)) {
  575. bfa_fcs_port_plogi(lport, fchs, (struct fc_logi_s *) els_cmd);
  576. return;
  577. }
  578. /*
  579. * Handle ECHO separately.
  580. */
  581. if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_ECHO)) {
  582. bfa_fcs_port_echo(lport, fchs,
  583. (struct fc_echo_s *) els_cmd, len);
  584. return;
  585. }
  586. /*
  587. * Handle RNID separately.
  588. */
  589. if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_RNID)) {
  590. bfa_fcs_port_rnid(lport, fchs,
  591. (struct fc_rnid_cmd_s *) els_cmd, len);
  592. return;
  593. }
  594. /**
  595. * look for a matching remote port ID
  596. */
  597. rport = bfa_fcs_port_get_rport_by_pid(lport, pid);
  598. if (rport) {
  599. bfa_trc(rport->fcs, fchs->s_id);
  600. bfa_trc(rport->fcs, fchs->d_id);
  601. bfa_trc(rport->fcs, fchs->type);
  602. bfa_fcs_rport_uf_recv(rport, fchs, len);
  603. return;
  604. }
  605. /**
  606. * Only handles ELS frames for now.
  607. */
  608. if (fchs->type != FC_TYPE_ELS) {
  609. bfa_trc(lport->fcs, fchs->type);
  610. bfa_assert(0);
  611. return;
  612. }
  613. bfa_trc(lport->fcs, els_cmd->els_code);
  614. if (els_cmd->els_code == FC_ELS_RSCN) {
  615. bfa_fcs_port_scn_process_rscn(lport, fchs, len);
  616. return;
  617. }
  618. if (els_cmd->els_code == FC_ELS_LOGO) {
  619. /**
  620. * @todo Handle LOGO frames received.
  621. */
  622. bfa_trc(lport->fcs, els_cmd->els_code);
  623. return;
  624. }
  625. if (els_cmd->els_code == FC_ELS_PRLI) {
  626. /**
  627. * @todo Handle PRLI frames received.
  628. */
  629. bfa_trc(lport->fcs, els_cmd->els_code);
  630. return;
  631. }
  632. /**
  633. * Unhandled ELS frames. Send a LS_RJT.
  634. */
  635. bfa_fcs_port_send_ls_rjt(lport, fchs, FC_LS_RJT_RSN_CMD_NOT_SUPP,
  636. FC_LS_RJT_EXP_NO_ADDL_INFO);
  637. }
  638. /**
  639. * PID based Lookup for a R-Port in the Port R-Port Queue
  640. */
  641. struct bfa_fcs_rport_s *
  642. bfa_fcs_port_get_rport_by_pid(struct bfa_fcs_port_s *port, u32 pid)
  643. {
  644. struct bfa_fcs_rport_s *rport;
  645. struct list_head *qe;
  646. list_for_each(qe, &port->rport_q) {
  647. rport = (struct bfa_fcs_rport_s *)qe;
  648. if (rport->pid == pid)
  649. return rport;
  650. }
  651. bfa_trc(port->fcs, pid);
  652. return NULL;
  653. }
  654. /**
  655. * PWWN based Lookup for a R-Port in the Port R-Port Queue
  656. */
  657. struct bfa_fcs_rport_s *
  658. bfa_fcs_port_get_rport_by_pwwn(struct bfa_fcs_port_s *port, wwn_t pwwn)
  659. {
  660. struct bfa_fcs_rport_s *rport;
  661. struct list_head *qe;
  662. list_for_each(qe, &port->rport_q) {
  663. rport = (struct bfa_fcs_rport_s *)qe;
  664. if (wwn_is_equal(rport->pwwn, pwwn))
  665. return rport;
  666. }
  667. bfa_trc(port->fcs, pwwn);
  668. return (NULL);
  669. }
  670. /**
  671. * NWWN based Lookup for a R-Port in the Port R-Port Queue
  672. */
  673. struct bfa_fcs_rport_s *
  674. bfa_fcs_port_get_rport_by_nwwn(struct bfa_fcs_port_s *port, wwn_t nwwn)
  675. {
  676. struct bfa_fcs_rport_s *rport;
  677. struct list_head *qe;
  678. list_for_each(qe, &port->rport_q) {
  679. rport = (struct bfa_fcs_rport_s *)qe;
  680. if (wwn_is_equal(rport->nwwn, nwwn))
  681. return rport;
  682. }
  683. bfa_trc(port->fcs, nwwn);
  684. return (NULL);
  685. }
  686. /**
  687. * Called by rport module when new rports are discovered.
  688. */
  689. void
  690. bfa_fcs_port_add_rport(struct bfa_fcs_port_s *port,
  691. struct bfa_fcs_rport_s *rport)
  692. {
  693. list_add_tail(&rport->qe, &port->rport_q);
  694. port->num_rports++;
  695. }
  696. /**
  697. * Called by rport module to when rports are deleted.
  698. */
  699. void
  700. bfa_fcs_port_del_rport(struct bfa_fcs_port_s *port,
  701. struct bfa_fcs_rport_s *rport)
  702. {
  703. bfa_assert(bfa_q_is_on_q(&port->rport_q, rport));
  704. list_del(&rport->qe);
  705. port->num_rports--;
  706. bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELRPORT);
  707. }
  708. /**
  709. * Called by fabric for base port when fabric login is complete.
  710. * Called by vport for virtual ports when FDISC is complete.
  711. */
  712. void
  713. bfa_fcs_port_online(struct bfa_fcs_port_s *port)
  714. {
  715. bfa_sm_send_event(port, BFA_FCS_PORT_SM_ONLINE);
  716. }
  717. /**
  718. * Called by fabric for base port when fabric goes offline.
  719. * Called by vport for virtual ports when virtual port becomes offline.
  720. */
  721. void
  722. bfa_fcs_port_offline(struct bfa_fcs_port_s *port)
  723. {
  724. bfa_sm_send_event(port, BFA_FCS_PORT_SM_OFFLINE);
  725. }
  726. /**
  727. * Called by fabric to delete base lport and associated resources.
  728. *
  729. * Called by vport to delete lport and associated resources. Should call
  730. * bfa_fcs_vport_delete_comp() for vports on completion.
  731. */
  732. void
  733. bfa_fcs_port_delete(struct bfa_fcs_port_s *port)
  734. {
  735. bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELETE);
  736. }
  737. /**
  738. * Called by fabric in private loop topology to process LIP event.
  739. */
  740. void
  741. bfa_fcs_port_lip(struct bfa_fcs_port_s *port)
  742. {
  743. }
  744. /**
  745. * Return TRUE if port is online, else return FALSE
  746. */
  747. bfa_boolean_t
  748. bfa_fcs_port_is_online(struct bfa_fcs_port_s *port)
  749. {
  750. return (bfa_sm_cmp_state(port, bfa_fcs_port_sm_online));
  751. }
  752. /**
  753. * Logical port initialization of base or virtual port.
  754. * Called by fabric for base port or by vport for virtual ports.
  755. */
  756. void
  757. bfa_fcs_lport_init(struct bfa_fcs_port_s *lport, struct bfa_fcs_s *fcs,
  758. u16 vf_id, struct bfa_port_cfg_s *port_cfg,
  759. struct bfa_fcs_vport_s *vport)
  760. {
  761. lport->fcs = fcs;
  762. lport->fabric = bfa_fcs_vf_lookup(fcs, vf_id);
  763. bfa_os_assign(lport->port_cfg, *port_cfg);
  764. lport->vport = vport;
  765. lport->lp_tag = (vport) ? bfa_lps_get_tag(vport->lps) :
  766. bfa_lps_get_tag(lport->fabric->lps);
  767. INIT_LIST_HEAD(&lport->rport_q);
  768. lport->num_rports = 0;
  769. lport->bfad_port =
  770. bfa_fcb_port_new(fcs->bfad, lport, lport->port_cfg.roles,
  771. lport->fabric->vf_drv,
  772. vport ? vport->vport_drv : NULL);
  773. bfa_fcs_port_aen_post(lport, BFA_LPORT_AEN_NEW);
  774. bfa_sm_set_state(lport, bfa_fcs_port_sm_uninit);
  775. bfa_sm_send_event(lport, BFA_FCS_PORT_SM_CREATE);
  776. }
  777. /**
  778. * fcs_lport_api
  779. */
  780. void
  781. bfa_fcs_port_get_attr(struct bfa_fcs_port_s *port,
  782. struct bfa_port_attr_s *port_attr)
  783. {
  784. if (bfa_sm_cmp_state(port, bfa_fcs_port_sm_online))
  785. port_attr->pid = port->pid;
  786. else
  787. port_attr->pid = 0;
  788. port_attr->port_cfg = port->port_cfg;
  789. if (port->fabric) {
  790. port_attr->port_type = bfa_fcs_fabric_port_type(port->fabric);
  791. port_attr->loopback = bfa_fcs_fabric_is_loopback(port->fabric);
  792. port_attr->fabric_name = bfa_fcs_port_get_fabric_name(port);
  793. memcpy(port_attr->fabric_ip_addr,
  794. bfa_fcs_port_get_fabric_ipaddr(port),
  795. BFA_FCS_FABRIC_IPADDR_SZ);
  796. if (port->vport != NULL)
  797. port_attr->port_type = BFA_PPORT_TYPE_VPORT;
  798. } else {
  799. port_attr->port_type = BFA_PPORT_TYPE_UNKNOWN;
  800. port_attr->state = BFA_PORT_UNINIT;
  801. }
  802. }