scn.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  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. #include <bfa.h>
  18. #include <bfa_svc.h>
  19. #include "fcs_lport.h"
  20. #include "fcs_rport.h"
  21. #include "fcs_ms.h"
  22. #include "fcs_trcmod.h"
  23. #include "fcs_fcxp.h"
  24. #include "fcs.h"
  25. #include "lport_priv.h"
  26. BFA_TRC_FILE(FCS, SCN);
  27. #define FC_QOS_RSCN_EVENT 0x0c
  28. #define FC_FABRIC_NAME_RSCN_EVENT 0x0d
  29. /*
  30. * forward declarations
  31. */
  32. static void bfa_fcs_port_scn_send_scr(void *scn_cbarg,
  33. struct bfa_fcxp_s *fcxp_alloced);
  34. static void bfa_fcs_port_scn_scr_response(void *fcsarg,
  35. struct bfa_fcxp_s *fcxp,
  36. void *cbarg,
  37. bfa_status_t req_status,
  38. u32 rsp_len,
  39. u32 resid_len,
  40. struct fchs_s *rsp_fchs);
  41. static void bfa_fcs_port_scn_send_ls_acc(struct bfa_fcs_port_s *port,
  42. struct fchs_s *rx_fchs);
  43. static void bfa_fcs_port_scn_timeout(void *arg);
  44. /**
  45. * fcs_scm_sm FCS SCN state machine
  46. */
  47. /**
  48. * VPort SCN State Machine events
  49. */
  50. enum port_scn_event {
  51. SCNSM_EVENT_PORT_ONLINE = 1,
  52. SCNSM_EVENT_PORT_OFFLINE = 2,
  53. SCNSM_EVENT_RSP_OK = 3,
  54. SCNSM_EVENT_RSP_ERROR = 4,
  55. SCNSM_EVENT_TIMEOUT = 5,
  56. SCNSM_EVENT_SCR_SENT = 6,
  57. };
  58. static void bfa_fcs_port_scn_sm_offline(struct bfa_fcs_port_scn_s *scn,
  59. enum port_scn_event event);
  60. static void bfa_fcs_port_scn_sm_sending_scr(struct bfa_fcs_port_scn_s *scn,
  61. enum port_scn_event event);
  62. static void bfa_fcs_port_scn_sm_scr(struct bfa_fcs_port_scn_s *scn,
  63. enum port_scn_event event);
  64. static void bfa_fcs_port_scn_sm_scr_retry(struct bfa_fcs_port_scn_s *scn,
  65. enum port_scn_event event);
  66. static void bfa_fcs_port_scn_sm_online(struct bfa_fcs_port_scn_s *scn,
  67. enum port_scn_event event);
  68. /**
  69. * Starting state - awaiting link up.
  70. */
  71. static void
  72. bfa_fcs_port_scn_sm_offline(struct bfa_fcs_port_scn_s *scn,
  73. enum port_scn_event event)
  74. {
  75. switch (event) {
  76. case SCNSM_EVENT_PORT_ONLINE:
  77. bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_sending_scr);
  78. bfa_fcs_port_scn_send_scr(scn, NULL);
  79. break;
  80. case SCNSM_EVENT_PORT_OFFLINE:
  81. break;
  82. default:
  83. bfa_assert(0);
  84. }
  85. }
  86. static void
  87. bfa_fcs_port_scn_sm_sending_scr(struct bfa_fcs_port_scn_s *scn,
  88. enum port_scn_event event)
  89. {
  90. switch (event) {
  91. case SCNSM_EVENT_SCR_SENT:
  92. bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_scr);
  93. break;
  94. case SCNSM_EVENT_PORT_OFFLINE:
  95. bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_offline);
  96. bfa_fcxp_walloc_cancel(scn->port->fcs->bfa, &scn->fcxp_wqe);
  97. break;
  98. default:
  99. bfa_assert(0);
  100. }
  101. }
  102. static void
  103. bfa_fcs_port_scn_sm_scr(struct bfa_fcs_port_scn_s *scn,
  104. enum port_scn_event event)
  105. {
  106. struct bfa_fcs_port_s *port = scn->port;
  107. switch (event) {
  108. case SCNSM_EVENT_RSP_OK:
  109. bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_online);
  110. break;
  111. case SCNSM_EVENT_RSP_ERROR:
  112. bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_scr_retry);
  113. bfa_timer_start(port->fcs->bfa, &scn->timer,
  114. bfa_fcs_port_scn_timeout, scn,
  115. BFA_FCS_RETRY_TIMEOUT);
  116. break;
  117. case SCNSM_EVENT_PORT_OFFLINE:
  118. bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_offline);
  119. bfa_fcxp_discard(scn->fcxp);
  120. break;
  121. default:
  122. bfa_assert(0);
  123. }
  124. }
  125. static void
  126. bfa_fcs_port_scn_sm_scr_retry(struct bfa_fcs_port_scn_s *scn,
  127. enum port_scn_event event)
  128. {
  129. switch (event) {
  130. case SCNSM_EVENT_TIMEOUT:
  131. bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_sending_scr);
  132. bfa_fcs_port_scn_send_scr(scn, NULL);
  133. break;
  134. case SCNSM_EVENT_PORT_OFFLINE:
  135. bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_offline);
  136. bfa_timer_stop(&scn->timer);
  137. break;
  138. default:
  139. bfa_assert(0);
  140. }
  141. }
  142. static void
  143. bfa_fcs_port_scn_sm_online(struct bfa_fcs_port_scn_s *scn,
  144. enum port_scn_event event)
  145. {
  146. switch (event) {
  147. case SCNSM_EVENT_PORT_OFFLINE:
  148. bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_offline);
  149. break;
  150. default:
  151. bfa_assert(0);
  152. }
  153. }
  154. /**
  155. * fcs_scn_private FCS SCN private functions
  156. */
  157. /**
  158. * This routine will be called to send a SCR command.
  159. */
  160. static void
  161. bfa_fcs_port_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced)
  162. {
  163. struct bfa_fcs_port_scn_s *scn = scn_cbarg;
  164. struct bfa_fcs_port_s *port = scn->port;
  165. struct fchs_s fchs;
  166. int len;
  167. struct bfa_fcxp_s *fcxp;
  168. bfa_trc(port->fcs, port->pid);
  169. bfa_trc(port->fcs, port->port_cfg.pwwn);
  170. fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
  171. if (!fcxp) {
  172. bfa_fcxp_alloc_wait(port->fcs->bfa, &scn->fcxp_wqe,
  173. bfa_fcs_port_scn_send_scr, scn);
  174. return;
  175. }
  176. scn->fcxp = fcxp;
  177. /*
  178. * Handle VU registrations for Base port only
  179. */
  180. if ((!port->vport) && bfa_ioc_get_fcmode(&port->fcs->bfa->ioc)) {
  181. len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
  182. bfa_lps_is_brcd_fabric(port->fabric->lps),
  183. port->pid, 0);
  184. } else {
  185. len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), BFA_FALSE,
  186. port->pid, 0);
  187. }
  188. bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
  189. FC_CLASS_3, len, &fchs, bfa_fcs_port_scn_scr_response,
  190. (void *)scn, FC_MAX_PDUSZ, FC_RA_TOV);
  191. bfa_sm_send_event(scn, SCNSM_EVENT_SCR_SENT);
  192. }
  193. static void
  194. bfa_fcs_port_scn_scr_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
  195. void *cbarg, bfa_status_t req_status,
  196. u32 rsp_len, u32 resid_len,
  197. struct fchs_s *rsp_fchs)
  198. {
  199. struct bfa_fcs_port_scn_s *scn = (struct bfa_fcs_port_scn_s *)cbarg;
  200. struct bfa_fcs_port_s *port = scn->port;
  201. struct fc_els_cmd_s *els_cmd;
  202. struct fc_ls_rjt_s *ls_rjt;
  203. bfa_trc(port->fcs, port->port_cfg.pwwn);
  204. /*
  205. * Sanity Checks
  206. */
  207. if (req_status != BFA_STATUS_OK) {
  208. bfa_trc(port->fcs, req_status);
  209. bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
  210. return;
  211. }
  212. els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
  213. switch (els_cmd->els_code) {
  214. case FC_ELS_ACC:
  215. bfa_sm_send_event(scn, SCNSM_EVENT_RSP_OK);
  216. break;
  217. case FC_ELS_LS_RJT:
  218. ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
  219. bfa_trc(port->fcs, ls_rjt->reason_code);
  220. bfa_trc(port->fcs, ls_rjt->reason_code_expl);
  221. bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
  222. break;
  223. default:
  224. bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
  225. }
  226. }
  227. /*
  228. * Send a LS Accept
  229. */
  230. static void
  231. bfa_fcs_port_scn_send_ls_acc(struct bfa_fcs_port_s *port,
  232. struct fchs_s *rx_fchs)
  233. {
  234. struct fchs_s fchs;
  235. struct bfa_fcxp_s *fcxp;
  236. struct bfa_rport_s *bfa_rport = NULL;
  237. int len;
  238. bfa_trc(port->fcs, rx_fchs->s_id);
  239. fcxp = bfa_fcs_fcxp_alloc(port->fcs);
  240. if (!fcxp)
  241. return;
  242. len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
  243. bfa_fcs_port_get_fcid(port), rx_fchs->ox_id);
  244. bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
  245. BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
  246. FC_MAX_PDUSZ, 0);
  247. }
  248. /**
  249. * This routine will be called by bfa_timer on timer timeouts.
  250. *
  251. * param[in] vport - pointer to bfa_fcs_port_t.
  252. * param[out] vport_status - pointer to return vport status in
  253. *
  254. * return
  255. * void
  256. *
  257. * Special Considerations:
  258. *
  259. * note
  260. */
  261. static void
  262. bfa_fcs_port_scn_timeout(void *arg)
  263. {
  264. struct bfa_fcs_port_scn_s *scn = (struct bfa_fcs_port_scn_s *)arg;
  265. bfa_sm_send_event(scn, SCNSM_EVENT_TIMEOUT);
  266. }
  267. /**
  268. * fcs_scn_public FCS state change notification public interfaces
  269. */
  270. /*
  271. * Functions called by port/fab
  272. */
  273. void
  274. bfa_fcs_port_scn_init(struct bfa_fcs_port_s *port)
  275. {
  276. struct bfa_fcs_port_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
  277. scn->port = port;
  278. bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_offline);
  279. }
  280. void
  281. bfa_fcs_port_scn_offline(struct bfa_fcs_port_s *port)
  282. {
  283. struct bfa_fcs_port_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
  284. scn->port = port;
  285. bfa_sm_send_event(scn, SCNSM_EVENT_PORT_OFFLINE);
  286. }
  287. void
  288. bfa_fcs_port_scn_online(struct bfa_fcs_port_s *port)
  289. {
  290. struct bfa_fcs_port_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
  291. scn->port = port;
  292. bfa_sm_send_event(scn, SCNSM_EVENT_PORT_ONLINE);
  293. }
  294. static void
  295. bfa_fcs_port_scn_portid_rscn(struct bfa_fcs_port_s *port, u32 rpid)
  296. {
  297. struct bfa_fcs_rport_s *rport;
  298. bfa_trc(port->fcs, rpid);
  299. /**
  300. * If this is an unknown device, then it just came online.
  301. * Otherwise let rport handle the RSCN event.
  302. */
  303. rport = bfa_fcs_port_get_rport_by_pid(port, rpid);
  304. if (rport == NULL) {
  305. /*
  306. * If min cfg mode is enabled, we donot need to
  307. * discover any new rports.
  308. */
  309. if (!__fcs_min_cfg(port->fcs))
  310. rport = bfa_fcs_rport_create(port, rpid);
  311. } else {
  312. bfa_fcs_rport_scn(rport);
  313. }
  314. }
  315. /**
  316. * rscn format based PID comparison
  317. */
  318. #define __fc_pid_match(__c0, __c1, __fmt) \
  319. (((__fmt) == FC_RSCN_FORMAT_FABRIC) || \
  320. (((__fmt) == FC_RSCN_FORMAT_DOMAIN) && \
  321. ((__c0)[0] == (__c1)[0])) || \
  322. (((__fmt) == FC_RSCN_FORMAT_AREA) && \
  323. ((__c0)[0] == (__c1)[0]) && \
  324. ((__c0)[1] == (__c1)[1])))
  325. static void
  326. bfa_fcs_port_scn_multiport_rscn(struct bfa_fcs_port_s *port,
  327. enum fc_rscn_format format, u32 rscn_pid)
  328. {
  329. struct bfa_fcs_rport_s *rport;
  330. struct list_head *qe, *qe_next;
  331. u8 *c0, *c1;
  332. bfa_trc(port->fcs, format);
  333. bfa_trc(port->fcs, rscn_pid);
  334. c0 = (u8 *) &rscn_pid;
  335. list_for_each_safe(qe, qe_next, &port->rport_q) {
  336. rport = (struct bfa_fcs_rport_s *)qe;
  337. c1 = (u8 *) &rport->pid;
  338. if (__fc_pid_match(c0, c1, format))
  339. bfa_fcs_rport_scn(rport);
  340. }
  341. }
  342. void
  343. bfa_fcs_port_scn_process_rscn(struct bfa_fcs_port_s *port, struct fchs_s *fchs,
  344. u32 len)
  345. {
  346. struct fc_rscn_pl_s *rscn = (struct fc_rscn_pl_s *) (fchs + 1);
  347. int num_entries;
  348. u32 rscn_pid;
  349. bfa_boolean_t nsquery = BFA_FALSE;
  350. int i = 0;
  351. num_entries =
  352. (bfa_os_ntohs(rscn->payldlen) -
  353. sizeof(u32)) / sizeof(rscn->event[0]);
  354. bfa_trc(port->fcs, num_entries);
  355. port->stats.num_rscn++;
  356. bfa_fcs_port_scn_send_ls_acc(port, fchs);
  357. for (i = 0; i < num_entries; i++) {
  358. rscn_pid = rscn->event[i].portid;
  359. bfa_trc(port->fcs, rscn->event[i].format);
  360. bfa_trc(port->fcs, rscn_pid);
  361. switch (rscn->event[i].format) {
  362. case FC_RSCN_FORMAT_PORTID:
  363. if (rscn->event[i].qualifier == FC_QOS_RSCN_EVENT) {
  364. /*
  365. * Ignore this event. f/w would have processed
  366. * it
  367. */
  368. bfa_trc(port->fcs, rscn_pid);
  369. } else {
  370. port->stats.num_portid_rscn++;
  371. bfa_fcs_port_scn_portid_rscn(port, rscn_pid);
  372. }
  373. break;
  374. case FC_RSCN_FORMAT_FABRIC:
  375. if (rscn->event[i].qualifier ==
  376. FC_FABRIC_NAME_RSCN_EVENT) {
  377. bfa_fcs_port_ms_fabric_rscn(port);
  378. break;
  379. }
  380. /*
  381. * !!!!!!!!! Fall Through !!!!!!!!!!!!!
  382. */
  383. case FC_RSCN_FORMAT_AREA:
  384. case FC_RSCN_FORMAT_DOMAIN:
  385. nsquery = BFA_TRUE;
  386. bfa_fcs_port_scn_multiport_rscn(port,
  387. rscn->event[i].format,
  388. rscn_pid);
  389. break;
  390. default:
  391. bfa_assert(0);
  392. nsquery = BFA_TRUE;
  393. }
  394. }
  395. /**
  396. * If any of area, domain or fabric RSCN is received, do a fresh discovery
  397. * to find new devices.
  398. */
  399. if (nsquery)
  400. bfa_fcs_port_ns_query(port);
  401. }