efc_domain.c 26 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2021 Broadcom. All Rights Reserved. The term
  4. * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
  5. */
  6. /*
  7. * domain_sm Domain State Machine: States
  8. */
  9. #include "efc.h"
  10. int
  11. efc_domain_cb(void *arg, int event, void *data)
  12. {
  13. struct efc *efc = arg;
  14. struct efc_domain *domain = NULL;
  15. int rc = 0;
  16. unsigned long flags = 0;
  17. if (event != EFC_HW_DOMAIN_FOUND)
  18. domain = data;
  19. /* Accept domain callback events from the user driver */
  20. spin_lock_irqsave(&efc->lock, flags);
  21. switch (event) {
  22. case EFC_HW_DOMAIN_FOUND: {
  23. u64 fcf_wwn = 0;
  24. struct efc_domain_record *drec = data;
  25. /* extract the fcf_wwn */
  26. fcf_wwn = be64_to_cpu(*((__be64 *)drec->wwn));
  27. efc_log_debug(efc, "Domain found: wwn %016llX\n", fcf_wwn);
  28. /* lookup domain, or allocate a new one */
  29. domain = efc->domain;
  30. if (!domain) {
  31. domain = efc_domain_alloc(efc, fcf_wwn);
  32. if (!domain) {
  33. efc_log_err(efc, "efc_domain_alloc() failed\n");
  34. rc = -1;
  35. break;
  36. }
  37. efc_sm_transition(&domain->drvsm, __efc_domain_init,
  38. NULL);
  39. }
  40. efc_domain_post_event(domain, EFC_EVT_DOMAIN_FOUND, drec);
  41. break;
  42. }
  43. case EFC_HW_DOMAIN_LOST:
  44. domain_trace(domain, "EFC_HW_DOMAIN_LOST:\n");
  45. efc->hold_frames = true;
  46. efc_domain_post_event(domain, EFC_EVT_DOMAIN_LOST, NULL);
  47. break;
  48. case EFC_HW_DOMAIN_ALLOC_OK:
  49. domain_trace(domain, "EFC_HW_DOMAIN_ALLOC_OK:\n");
  50. efc_domain_post_event(domain, EFC_EVT_DOMAIN_ALLOC_OK, NULL);
  51. break;
  52. case EFC_HW_DOMAIN_ALLOC_FAIL:
  53. domain_trace(domain, "EFC_HW_DOMAIN_ALLOC_FAIL:\n");
  54. efc_domain_post_event(domain, EFC_EVT_DOMAIN_ALLOC_FAIL,
  55. NULL);
  56. break;
  57. case EFC_HW_DOMAIN_ATTACH_OK:
  58. domain_trace(domain, "EFC_HW_DOMAIN_ATTACH_OK:\n");
  59. efc_domain_post_event(domain, EFC_EVT_DOMAIN_ATTACH_OK, NULL);
  60. break;
  61. case EFC_HW_DOMAIN_ATTACH_FAIL:
  62. domain_trace(domain, "EFC_HW_DOMAIN_ATTACH_FAIL:\n");
  63. efc_domain_post_event(domain,
  64. EFC_EVT_DOMAIN_ATTACH_FAIL, NULL);
  65. break;
  66. case EFC_HW_DOMAIN_FREE_OK:
  67. domain_trace(domain, "EFC_HW_DOMAIN_FREE_OK:\n");
  68. efc_domain_post_event(domain, EFC_EVT_DOMAIN_FREE_OK, NULL);
  69. break;
  70. case EFC_HW_DOMAIN_FREE_FAIL:
  71. domain_trace(domain, "EFC_HW_DOMAIN_FREE_FAIL:\n");
  72. efc_domain_post_event(domain, EFC_EVT_DOMAIN_FREE_FAIL, NULL);
  73. break;
  74. default:
  75. efc_log_warn(efc, "unsupported event %#x\n", event);
  76. }
  77. spin_unlock_irqrestore(&efc->lock, flags);
  78. if (efc->domain && domain->req_accept_frames) {
  79. domain->req_accept_frames = false;
  80. efc->hold_frames = false;
  81. }
  82. return rc;
  83. }
  84. static void
  85. _efc_domain_free(struct kref *arg)
  86. {
  87. struct efc_domain *domain = container_of(arg, struct efc_domain, ref);
  88. struct efc *efc = domain->efc;
  89. if (efc->domain_free_cb)
  90. (*efc->domain_free_cb)(efc, efc->domain_free_cb_arg);
  91. kfree(domain);
  92. }
  93. void
  94. efc_domain_free(struct efc_domain *domain)
  95. {
  96. struct efc *efc;
  97. efc = domain->efc;
  98. /* Hold frames to clear the domain pointer from the xport lookup */
  99. efc->hold_frames = false;
  100. efc_log_debug(efc, "Domain free: wwn %016llX\n", domain->fcf_wwn);
  101. xa_destroy(&domain->lookup);
  102. efc->domain = NULL;
  103. kref_put(&domain->ref, domain->release);
  104. }
  105. struct efc_domain *
  106. efc_domain_alloc(struct efc *efc, uint64_t fcf_wwn)
  107. {
  108. struct efc_domain *domain;
  109. domain = kzalloc(sizeof(*domain), GFP_ATOMIC);
  110. if (!domain)
  111. return NULL;
  112. domain->efc = efc;
  113. domain->drvsm.app = domain;
  114. /* initialize refcount */
  115. kref_init(&domain->ref);
  116. domain->release = _efc_domain_free;
  117. xa_init(&domain->lookup);
  118. INIT_LIST_HEAD(&domain->nport_list);
  119. efc->domain = domain;
  120. domain->fcf_wwn = fcf_wwn;
  121. efc_log_debug(efc, "Domain allocated: wwn %016llX\n", domain->fcf_wwn);
  122. return domain;
  123. }
  124. void
  125. efc_register_domain_free_cb(struct efc *efc,
  126. void (*callback)(struct efc *efc, void *arg),
  127. void *arg)
  128. {
  129. /* Register a callback to be called when the domain is freed */
  130. efc->domain_free_cb = callback;
  131. efc->domain_free_cb_arg = arg;
  132. if (!efc->domain && callback)
  133. (*callback)(efc, arg);
  134. }
  135. static void
  136. __efc_domain_common(const char *funcname, struct efc_sm_ctx *ctx,
  137. enum efc_sm_event evt, void *arg)
  138. {
  139. struct efc_domain *domain = ctx->app;
  140. switch (evt) {
  141. case EFC_EVT_ENTER:
  142. case EFC_EVT_REENTER:
  143. case EFC_EVT_EXIT:
  144. case EFC_EVT_ALL_CHILD_NODES_FREE:
  145. /*
  146. * this can arise if an FLOGI fails on the NPORT,
  147. * and the NPORT is shutdown
  148. */
  149. break;
  150. default:
  151. efc_log_warn(domain->efc, "%-20s %-20s not handled\n",
  152. funcname, efc_sm_event_name(evt));
  153. }
  154. }
  155. static void
  156. __efc_domain_common_shutdown(const char *funcname, struct efc_sm_ctx *ctx,
  157. enum efc_sm_event evt, void *arg)
  158. {
  159. struct efc_domain *domain = ctx->app;
  160. switch (evt) {
  161. case EFC_EVT_ENTER:
  162. case EFC_EVT_REENTER:
  163. case EFC_EVT_EXIT:
  164. break;
  165. case EFC_EVT_DOMAIN_FOUND:
  166. /* save drec, mark domain_found_pending */
  167. memcpy(&domain->pending_drec, arg,
  168. sizeof(domain->pending_drec));
  169. domain->domain_found_pending = true;
  170. break;
  171. case EFC_EVT_DOMAIN_LOST:
  172. /* unmark domain_found_pending */
  173. domain->domain_found_pending = false;
  174. break;
  175. default:
  176. efc_log_warn(domain->efc, "%-20s %-20s not handled\n",
  177. funcname, efc_sm_event_name(evt));
  178. }
  179. }
  180. #define std_domain_state_decl(...)\
  181. struct efc_domain *domain = NULL;\
  182. struct efc *efc = NULL;\
  183. \
  184. WARN_ON(!ctx || !ctx->app);\
  185. domain = ctx->app;\
  186. WARN_ON(!domain->efc);\
  187. efc = domain->efc
  188. void
  189. __efc_domain_init(struct efc_sm_ctx *ctx, enum efc_sm_event evt,
  190. void *arg)
  191. {
  192. std_domain_state_decl();
  193. domain_sm_trace(domain);
  194. switch (evt) {
  195. case EFC_EVT_ENTER:
  196. domain->attached = false;
  197. break;
  198. case EFC_EVT_DOMAIN_FOUND: {
  199. u32 i;
  200. struct efc_domain_record *drec = arg;
  201. struct efc_nport *nport;
  202. u64 my_wwnn = efc->req_wwnn;
  203. u64 my_wwpn = efc->req_wwpn;
  204. __be64 bewwpn;
  205. if (my_wwpn == 0 || my_wwnn == 0) {
  206. efc_log_debug(efc, "using default hardware WWN config\n");
  207. my_wwpn = efc->def_wwpn;
  208. my_wwnn = efc->def_wwnn;
  209. }
  210. efc_log_debug(efc, "Create nport WWPN %016llX WWNN %016llX\n",
  211. my_wwpn, my_wwnn);
  212. /* Allocate a nport and transition to __efc_nport_allocated */
  213. nport = efc_nport_alloc(domain, my_wwpn, my_wwnn, U32_MAX,
  214. efc->enable_ini, efc->enable_tgt);
  215. if (!nport) {
  216. efc_log_err(efc, "efc_nport_alloc() failed\n");
  217. break;
  218. }
  219. efc_sm_transition(&nport->sm, __efc_nport_allocated, NULL);
  220. bewwpn = cpu_to_be64(nport->wwpn);
  221. /* allocate struct efc_nport object for local port
  222. * Note: drec->fc_id is ALPA from read_topology only if loop
  223. */
  224. if (efc_cmd_nport_alloc(efc, nport, NULL, (uint8_t *)&bewwpn)) {
  225. efc_log_err(efc, "Can't allocate port\n");
  226. efc_nport_free(nport);
  227. break;
  228. }
  229. domain->is_loop = drec->is_loop;
  230. /*
  231. * If the loop position map includes ALPA == 0,
  232. * then we are in a public loop (NL_PORT)
  233. * Note that the first element of the loopmap[]
  234. * contains the count of elements, and if
  235. * ALPA == 0 is present, it will occupy the first
  236. * location after the count.
  237. */
  238. domain->is_nlport = drec->map.loop[1] == 0x00;
  239. if (!domain->is_loop) {
  240. /* Initiate HW domain alloc */
  241. if (efc_cmd_domain_alloc(efc, domain, drec->index)) {
  242. efc_log_err(efc,
  243. "Failed to initiate HW domain allocation\n");
  244. break;
  245. }
  246. efc_sm_transition(ctx, __efc_domain_wait_alloc, arg);
  247. break;
  248. }
  249. efc_log_debug(efc, "%s fc_id=%#x speed=%d\n",
  250. drec->is_loop ?
  251. (domain->is_nlport ?
  252. "public-loop" : "loop") : "other",
  253. drec->fc_id, drec->speed);
  254. nport->fc_id = drec->fc_id;
  255. nport->topology = EFC_NPORT_TOPO_FC_AL;
  256. snprintf(nport->display_name, sizeof(nport->display_name),
  257. "s%06x", drec->fc_id);
  258. if (efc->enable_ini) {
  259. u32 count = drec->map.loop[0];
  260. efc_log_debug(efc, "%d position map entries\n",
  261. count);
  262. for (i = 1; i <= count; i++) {
  263. if (drec->map.loop[i] != drec->fc_id) {
  264. struct efc_node *node;
  265. efc_log_debug(efc, "%#x -> %#x\n",
  266. drec->fc_id,
  267. drec->map.loop[i]);
  268. node = efc_node_alloc(nport,
  269. drec->map.loop[i],
  270. false, true);
  271. if (!node) {
  272. efc_log_err(efc,
  273. "efc_node_alloc() failed\n");
  274. break;
  275. }
  276. efc_node_transition(node,
  277. __efc_d_wait_loop,
  278. NULL);
  279. }
  280. }
  281. }
  282. /* Initiate HW domain alloc */
  283. if (efc_cmd_domain_alloc(efc, domain, drec->index)) {
  284. efc_log_err(efc,
  285. "Failed to initiate HW domain allocation\n");
  286. break;
  287. }
  288. efc_sm_transition(ctx, __efc_domain_wait_alloc, arg);
  289. break;
  290. }
  291. default:
  292. __efc_domain_common(__func__, ctx, evt, arg);
  293. }
  294. }
  295. void
  296. __efc_domain_wait_alloc(struct efc_sm_ctx *ctx,
  297. enum efc_sm_event evt, void *arg)
  298. {
  299. std_domain_state_decl();
  300. domain_sm_trace(domain);
  301. switch (evt) {
  302. case EFC_EVT_DOMAIN_ALLOC_OK: {
  303. struct fc_els_flogi *sp;
  304. struct efc_nport *nport;
  305. nport = domain->nport;
  306. if (WARN_ON(!nport))
  307. return;
  308. sp = (struct fc_els_flogi *)nport->service_params;
  309. /* Save the domain service parameters */
  310. memcpy(domain->service_params + 4, domain->dma.virt,
  311. sizeof(struct fc_els_flogi) - 4);
  312. memcpy(nport->service_params + 4, domain->dma.virt,
  313. sizeof(struct fc_els_flogi) - 4);
  314. /*
  315. * Update the nport's service parameters,
  316. * user might have specified non-default names
  317. */
  318. sp->fl_wwpn = cpu_to_be64(nport->wwpn);
  319. sp->fl_wwnn = cpu_to_be64(nport->wwnn);
  320. /*
  321. * Take the loop topology path,
  322. * unless we are an NL_PORT (public loop)
  323. */
  324. if (domain->is_loop && !domain->is_nlport) {
  325. /*
  326. * For loop, we already have our FC ID
  327. * and don't need fabric login.
  328. * Transition to the allocated state and
  329. * post an event to attach to
  330. * the domain. Note that this breaks the
  331. * normal action/transition
  332. * pattern here to avoid a race with the
  333. * domain attach callback.
  334. */
  335. /* sm: is_loop / domain_attach */
  336. efc_sm_transition(ctx, __efc_domain_allocated, NULL);
  337. __efc_domain_attach_internal(domain, nport->fc_id);
  338. break;
  339. }
  340. {
  341. struct efc_node *node;
  342. /* alloc fabric node, send FLOGI */
  343. node = efc_node_find(nport, FC_FID_FLOGI);
  344. if (node) {
  345. efc_log_err(efc,
  346. "Fabric Controller node already exists\n");
  347. break;
  348. }
  349. node = efc_node_alloc(nport, FC_FID_FLOGI,
  350. false, false);
  351. if (!node) {
  352. efc_log_err(efc,
  353. "Error: efc_node_alloc() failed\n");
  354. } else {
  355. efc_node_transition(node,
  356. __efc_fabric_init, NULL);
  357. }
  358. /* Accept frames */
  359. domain->req_accept_frames = true;
  360. }
  361. /* sm: / start fabric logins */
  362. efc_sm_transition(ctx, __efc_domain_allocated, NULL);
  363. break;
  364. }
  365. case EFC_EVT_DOMAIN_ALLOC_FAIL:
  366. efc_log_err(efc, "%s recv'd waiting for DOMAIN_ALLOC_OK;",
  367. efc_sm_event_name(evt));
  368. efc_log_err(efc, "shutting down domain\n");
  369. domain->req_domain_free = true;
  370. break;
  371. case EFC_EVT_DOMAIN_FOUND:
  372. /* Should not happen */
  373. break;
  374. case EFC_EVT_DOMAIN_LOST:
  375. efc_log_debug(efc,
  376. "%s received while waiting for hw_domain_alloc()\n",
  377. efc_sm_event_name(evt));
  378. efc_sm_transition(ctx, __efc_domain_wait_domain_lost, NULL);
  379. break;
  380. default:
  381. __efc_domain_common(__func__, ctx, evt, arg);
  382. }
  383. }
  384. void
  385. __efc_domain_allocated(struct efc_sm_ctx *ctx,
  386. enum efc_sm_event evt, void *arg)
  387. {
  388. std_domain_state_decl();
  389. domain_sm_trace(domain);
  390. switch (evt) {
  391. case EFC_EVT_DOMAIN_REQ_ATTACH: {
  392. int rc = 0;
  393. u32 fc_id;
  394. if (WARN_ON(!arg))
  395. return;
  396. fc_id = *((u32 *)arg);
  397. efc_log_debug(efc, "Requesting hw domain attach fc_id x%x\n",
  398. fc_id);
  399. /* Update nport lookup */
  400. rc = xa_err(xa_store(&domain->lookup, fc_id, domain->nport,
  401. GFP_ATOMIC));
  402. if (rc) {
  403. efc_log_err(efc, "Sport lookup store failed: %d\n", rc);
  404. return;
  405. }
  406. /* Update display name for the nport */
  407. efc_node_fcid_display(fc_id, domain->nport->display_name,
  408. sizeof(domain->nport->display_name));
  409. /* Issue domain attach call */
  410. rc = efc_cmd_domain_attach(efc, domain, fc_id);
  411. if (rc) {
  412. efc_log_err(efc, "efc_hw_domain_attach failed: %d\n",
  413. rc);
  414. return;
  415. }
  416. /* sm: / domain_attach */
  417. efc_sm_transition(ctx, __efc_domain_wait_attach, NULL);
  418. break;
  419. }
  420. case EFC_EVT_DOMAIN_FOUND:
  421. /* Should not happen */
  422. efc_log_err(efc, "%s: evt: %d should not happen\n",
  423. __func__, evt);
  424. break;
  425. case EFC_EVT_DOMAIN_LOST: {
  426. efc_log_debug(efc,
  427. "%s received while in EFC_EVT_DOMAIN_REQ_ATTACH\n",
  428. efc_sm_event_name(evt));
  429. if (!list_empty(&domain->nport_list)) {
  430. /*
  431. * if there are nports, transition to
  432. * wait state and send shutdown to each
  433. * nport
  434. */
  435. struct efc_nport *nport = NULL, *nport_next = NULL;
  436. efc_sm_transition(ctx, __efc_domain_wait_nports_free,
  437. NULL);
  438. list_for_each_entry_safe(nport, nport_next,
  439. &domain->nport_list,
  440. list_entry) {
  441. efc_sm_post_event(&nport->sm,
  442. EFC_EVT_SHUTDOWN, NULL);
  443. }
  444. } else {
  445. /* no nports exist, free domain */
  446. efc_sm_transition(ctx, __efc_domain_wait_shutdown,
  447. NULL);
  448. if (efc_cmd_domain_free(efc, domain))
  449. efc_log_err(efc, "hw_domain_free failed\n");
  450. }
  451. break;
  452. }
  453. default:
  454. __efc_domain_common(__func__, ctx, evt, arg);
  455. }
  456. }
  457. void
  458. __efc_domain_wait_attach(struct efc_sm_ctx *ctx,
  459. enum efc_sm_event evt, void *arg)
  460. {
  461. std_domain_state_decl();
  462. domain_sm_trace(domain);
  463. switch (evt) {
  464. case EFC_EVT_DOMAIN_ATTACH_OK: {
  465. struct efc_node *node = NULL;
  466. struct efc_nport *nport, *next_nport;
  467. unsigned long index;
  468. /*
  469. * Set domain notify pending state to avoid
  470. * duplicate domain event post
  471. */
  472. domain->domain_notify_pend = true;
  473. /* Mark as attached */
  474. domain->attached = true;
  475. /* Transition to ready */
  476. /* sm: / forward event to all nports and nodes */
  477. efc_sm_transition(ctx, __efc_domain_ready, NULL);
  478. /* We have an FCFI, so we can accept frames */
  479. domain->req_accept_frames = true;
  480. /*
  481. * Notify all nodes that the domain attach request
  482. * has completed
  483. * Note: nport will have already received notification
  484. * of nport attached as a result of the HW's port attach.
  485. */
  486. list_for_each_entry_safe(nport, next_nport,
  487. &domain->nport_list, list_entry) {
  488. xa_for_each(&nport->lookup, index, node) {
  489. efc_node_post_event(node,
  490. EFC_EVT_DOMAIN_ATTACH_OK,
  491. NULL);
  492. }
  493. }
  494. domain->domain_notify_pend = false;
  495. break;
  496. }
  497. case EFC_EVT_DOMAIN_ATTACH_FAIL:
  498. efc_log_debug(efc,
  499. "%s received while waiting for hw attach\n",
  500. efc_sm_event_name(evt));
  501. break;
  502. case EFC_EVT_DOMAIN_FOUND:
  503. /* Should not happen */
  504. efc_log_err(efc, "%s: evt: %d should not happen\n",
  505. __func__, evt);
  506. break;
  507. case EFC_EVT_DOMAIN_LOST:
  508. /*
  509. * Domain lost while waiting for an attach to complete,
  510. * go to a state that waits for the domain attach to
  511. * complete, then handle domain lost
  512. */
  513. efc_sm_transition(ctx, __efc_domain_wait_domain_lost, NULL);
  514. break;
  515. case EFC_EVT_DOMAIN_REQ_ATTACH:
  516. /*
  517. * In P2P we can get an attach request from
  518. * the other FLOGI path, so drop this one
  519. */
  520. break;
  521. default:
  522. __efc_domain_common(__func__, ctx, evt, arg);
  523. }
  524. }
  525. void
  526. __efc_domain_ready(struct efc_sm_ctx *ctx, enum efc_sm_event evt, void *arg)
  527. {
  528. std_domain_state_decl();
  529. domain_sm_trace(domain);
  530. switch (evt) {
  531. case EFC_EVT_ENTER: {
  532. /* start any pending vports */
  533. if (efc_vport_start(domain)) {
  534. efc_log_debug(domain->efc,
  535. "efc_vport_start didn't start vports\n");
  536. }
  537. break;
  538. }
  539. case EFC_EVT_DOMAIN_LOST: {
  540. if (!list_empty(&domain->nport_list)) {
  541. /*
  542. * if there are nports, transition to wait state
  543. * and send shutdown to each nport
  544. */
  545. struct efc_nport *nport = NULL, *nport_next = NULL;
  546. efc_sm_transition(ctx, __efc_domain_wait_nports_free,
  547. NULL);
  548. list_for_each_entry_safe(nport, nport_next,
  549. &domain->nport_list,
  550. list_entry) {
  551. efc_sm_post_event(&nport->sm,
  552. EFC_EVT_SHUTDOWN, NULL);
  553. }
  554. } else {
  555. /* no nports exist, free domain */
  556. efc_sm_transition(ctx, __efc_domain_wait_shutdown,
  557. NULL);
  558. if (efc_cmd_domain_free(efc, domain))
  559. efc_log_err(efc, "hw_domain_free failed\n");
  560. }
  561. break;
  562. }
  563. case EFC_EVT_DOMAIN_FOUND:
  564. /* Should not happen */
  565. efc_log_err(efc, "%s: evt: %d should not happen\n",
  566. __func__, evt);
  567. break;
  568. case EFC_EVT_DOMAIN_REQ_ATTACH: {
  569. /* can happen during p2p */
  570. u32 fc_id;
  571. fc_id = *((u32 *)arg);
  572. /* Assume that the domain is attached */
  573. WARN_ON(!domain->attached);
  574. /*
  575. * Verify that the requested FC_ID
  576. * is the same as the one we're working with
  577. */
  578. WARN_ON(domain->nport->fc_id != fc_id);
  579. break;
  580. }
  581. default:
  582. __efc_domain_common(__func__, ctx, evt, arg);
  583. }
  584. }
  585. void
  586. __efc_domain_wait_nports_free(struct efc_sm_ctx *ctx, enum efc_sm_event evt,
  587. void *arg)
  588. {
  589. std_domain_state_decl();
  590. domain_sm_trace(domain);
  591. /* Wait for nodes to free prior to the domain shutdown */
  592. switch (evt) {
  593. case EFC_EVT_ALL_CHILD_NODES_FREE: {
  594. int rc;
  595. /* sm: / efc_hw_domain_free */
  596. efc_sm_transition(ctx, __efc_domain_wait_shutdown, NULL);
  597. /* Request efc_hw_domain_free and wait for completion */
  598. rc = efc_cmd_domain_free(efc, domain);
  599. if (rc) {
  600. efc_log_err(efc, "efc_hw_domain_free() failed: %d\n",
  601. rc);
  602. }
  603. break;
  604. }
  605. default:
  606. __efc_domain_common_shutdown(__func__, ctx, evt, arg);
  607. }
  608. }
  609. void
  610. __efc_domain_wait_shutdown(struct efc_sm_ctx *ctx,
  611. enum efc_sm_event evt, void *arg)
  612. {
  613. std_domain_state_decl();
  614. domain_sm_trace(domain);
  615. switch (evt) {
  616. case EFC_EVT_DOMAIN_FREE_OK:
  617. /* sm: / domain_free */
  618. if (domain->domain_found_pending) {
  619. /*
  620. * save fcf_wwn and drec from this domain,
  621. * free current domain and allocate
  622. * a new one with the same fcf_wwn
  623. * could use a SLI-4 "re-register VPI"
  624. * operation here?
  625. */
  626. u64 fcf_wwn = domain->fcf_wwn;
  627. struct efc_domain_record drec = domain->pending_drec;
  628. efc_log_debug(efc, "Reallocating domain\n");
  629. domain->req_domain_free = true;
  630. domain = efc_domain_alloc(efc, fcf_wwn);
  631. if (!domain) {
  632. efc_log_err(efc,
  633. "efc_domain_alloc() failed\n");
  634. return;
  635. }
  636. /*
  637. * got a new domain; at this point,
  638. * there are at least two domains
  639. * once the req_domain_free flag is processed,
  640. * the associated domain will be removed.
  641. */
  642. efc_sm_transition(&domain->drvsm, __efc_domain_init,
  643. NULL);
  644. efc_sm_post_event(&domain->drvsm,
  645. EFC_EVT_DOMAIN_FOUND, &drec);
  646. } else {
  647. domain->req_domain_free = true;
  648. }
  649. break;
  650. default:
  651. __efc_domain_common_shutdown(__func__, ctx, evt, arg);
  652. }
  653. }
  654. void
  655. __efc_domain_wait_domain_lost(struct efc_sm_ctx *ctx,
  656. enum efc_sm_event evt, void *arg)
  657. {
  658. std_domain_state_decl();
  659. domain_sm_trace(domain);
  660. /*
  661. * Wait for the domain alloc/attach completion
  662. * after receiving a domain lost.
  663. */
  664. switch (evt) {
  665. case EFC_EVT_DOMAIN_ALLOC_OK:
  666. case EFC_EVT_DOMAIN_ATTACH_OK: {
  667. if (!list_empty(&domain->nport_list)) {
  668. /*
  669. * if there are nports, transition to
  670. * wait state and send shutdown to each nport
  671. */
  672. struct efc_nport *nport = NULL, *nport_next = NULL;
  673. efc_sm_transition(ctx, __efc_domain_wait_nports_free,
  674. NULL);
  675. list_for_each_entry_safe(nport, nport_next,
  676. &domain->nport_list,
  677. list_entry) {
  678. efc_sm_post_event(&nport->sm,
  679. EFC_EVT_SHUTDOWN, NULL);
  680. }
  681. } else {
  682. /* no nports exist, free domain */
  683. efc_sm_transition(ctx, __efc_domain_wait_shutdown,
  684. NULL);
  685. if (efc_cmd_domain_free(efc, domain))
  686. efc_log_err(efc, "hw_domain_free() failed\n");
  687. }
  688. break;
  689. }
  690. case EFC_EVT_DOMAIN_ALLOC_FAIL:
  691. case EFC_EVT_DOMAIN_ATTACH_FAIL:
  692. efc_log_err(efc, "[domain] %-20s: failed\n",
  693. efc_sm_event_name(evt));
  694. break;
  695. default:
  696. __efc_domain_common_shutdown(__func__, ctx, evt, arg);
  697. }
  698. }
  699. void
  700. __efc_domain_attach_internal(struct efc_domain *domain, u32 s_id)
  701. {
  702. memcpy(domain->dma.virt,
  703. ((uint8_t *)domain->flogi_service_params) + 4,
  704. sizeof(struct fc_els_flogi) - 4);
  705. (void)efc_sm_post_event(&domain->drvsm, EFC_EVT_DOMAIN_REQ_ATTACH,
  706. &s_id);
  707. }
  708. void
  709. efc_domain_attach(struct efc_domain *domain, u32 s_id)
  710. {
  711. __efc_domain_attach_internal(domain, s_id);
  712. }
  713. int
  714. efc_domain_post_event(struct efc_domain *domain,
  715. enum efc_sm_event event, void *arg)
  716. {
  717. int rc;
  718. bool req_domain_free;
  719. rc = efc_sm_post_event(&domain->drvsm, event, arg);
  720. req_domain_free = domain->req_domain_free;
  721. domain->req_domain_free = false;
  722. if (req_domain_free)
  723. efc_domain_free(domain);
  724. return rc;
  725. }
  726. static void
  727. efct_domain_process_pending(struct efc_domain *domain)
  728. {
  729. struct efc *efc = domain->efc;
  730. struct efc_hw_sequence *seq = NULL;
  731. u32 processed = 0;
  732. unsigned long flags = 0;
  733. for (;;) {
  734. /* need to check for hold frames condition after each frame
  735. * processed because any given frame could cause a transition
  736. * to a state that holds frames
  737. */
  738. if (efc->hold_frames)
  739. break;
  740. /* Get next frame/sequence */
  741. spin_lock_irqsave(&efc->pend_frames_lock, flags);
  742. if (!list_empty(&efc->pend_frames)) {
  743. seq = list_first_entry(&efc->pend_frames,
  744. struct efc_hw_sequence, list_entry);
  745. list_del(&seq->list_entry);
  746. }
  747. if (!seq) {
  748. processed = efc->pend_frames_processed;
  749. efc->pend_frames_processed = 0;
  750. spin_unlock_irqrestore(&efc->pend_frames_lock, flags);
  751. break;
  752. }
  753. efc->pend_frames_processed++;
  754. spin_unlock_irqrestore(&efc->pend_frames_lock, flags);
  755. /* now dispatch frame(s) to dispatch function */
  756. if (efc_domain_dispatch_frame(domain, seq))
  757. efc->tt.hw_seq_free(efc, seq);
  758. seq = NULL;
  759. }
  760. if (processed != 0)
  761. efc_log_debug(efc, "%u domain frames held and processed\n",
  762. processed);
  763. }
  764. void
  765. efc_dispatch_frame(struct efc *efc, struct efc_hw_sequence *seq)
  766. {
  767. struct efc_domain *domain = efc->domain;
  768. /*
  769. * If we are holding frames or the domain is not yet registered or
  770. * there's already frames on the pending list,
  771. * then add the new frame to pending list
  772. */
  773. if (!domain || efc->hold_frames || !list_empty(&efc->pend_frames)) {
  774. unsigned long flags = 0;
  775. spin_lock_irqsave(&efc->pend_frames_lock, flags);
  776. INIT_LIST_HEAD(&seq->list_entry);
  777. list_add_tail(&seq->list_entry, &efc->pend_frames);
  778. spin_unlock_irqrestore(&efc->pend_frames_lock, flags);
  779. if (domain) {
  780. /* immediately process pending frames */
  781. efct_domain_process_pending(domain);
  782. }
  783. } else {
  784. /*
  785. * We are not holding frames and pending list is empty,
  786. * just process frame. A non-zero return means the frame
  787. * was not handled - so cleanup
  788. */
  789. if (efc_domain_dispatch_frame(domain, seq))
  790. efc->tt.hw_seq_free(efc, seq);
  791. }
  792. }
  793. int
  794. efc_domain_dispatch_frame(void *arg, struct efc_hw_sequence *seq)
  795. {
  796. struct efc_domain *domain = (struct efc_domain *)arg;
  797. struct efc *efc = domain->efc;
  798. struct fc_frame_header *hdr;
  799. struct efc_node *node = NULL;
  800. struct efc_nport *nport = NULL;
  801. unsigned long flags = 0;
  802. u32 s_id, d_id, rc = EFC_HW_SEQ_FREE;
  803. if (!seq->header || !seq->header->dma.virt || !seq->payload->dma.virt) {
  804. efc_log_err(efc, "Sequence header or payload is null\n");
  805. return rc;
  806. }
  807. hdr = seq->header->dma.virt;
  808. /* extract the s_id and d_id */
  809. s_id = ntoh24(hdr->fh_s_id);
  810. d_id = ntoh24(hdr->fh_d_id);
  811. spin_lock_irqsave(&efc->lock, flags);
  812. nport = efc_nport_find(domain, d_id);
  813. if (!nport) {
  814. if (hdr->fh_type == FC_TYPE_FCP) {
  815. /* Drop frame */
  816. efc_log_warn(efc, "FCP frame with invalid d_id x%x\n",
  817. d_id);
  818. goto out;
  819. }
  820. /* p2p will use this case */
  821. nport = domain->nport;
  822. if (!nport || !kref_get_unless_zero(&nport->ref)) {
  823. efc_log_err(efc, "Physical nport is NULL\n");
  824. goto out;
  825. }
  826. }
  827. /* Lookup the node given the remote s_id */
  828. node = efc_node_find(nport, s_id);
  829. /* If not found, then create a new node */
  830. if (!node) {
  831. /*
  832. * If this is solicited data or control based on R_CTL and
  833. * there is no node context, then we can drop the frame
  834. */
  835. if ((hdr->fh_r_ctl == FC_RCTL_DD_SOL_DATA) ||
  836. (hdr->fh_r_ctl == FC_RCTL_DD_SOL_CTL)) {
  837. efc_log_debug(efc, "sol data/ctrl frame without node\n");
  838. goto out_release;
  839. }
  840. node = efc_node_alloc(nport, s_id, false, false);
  841. if (!node) {
  842. efc_log_err(efc, "efc_node_alloc() failed\n");
  843. goto out_release;
  844. }
  845. /* don't send PLOGI on efc_d_init entry */
  846. efc_node_init_device(node, false);
  847. }
  848. if (node->hold_frames || !list_empty(&node->pend_frames)) {
  849. /* add frame to node's pending list */
  850. spin_lock(&node->pend_frames_lock);
  851. INIT_LIST_HEAD(&seq->list_entry);
  852. list_add_tail(&seq->list_entry, &node->pend_frames);
  853. spin_unlock(&node->pend_frames_lock);
  854. rc = EFC_HW_SEQ_HOLD;
  855. goto out_release;
  856. }
  857. /* now dispatch frame to the node frame handler */
  858. efc_node_dispatch_frame(node, seq);
  859. out_release:
  860. kref_put(&nport->ref, nport->release);
  861. out:
  862. spin_unlock_irqrestore(&efc->lock, flags);
  863. return rc;
  864. }
  865. void
  866. efc_node_dispatch_frame(void *arg, struct efc_hw_sequence *seq)
  867. {
  868. struct fc_frame_header *hdr = seq->header->dma.virt;
  869. u32 port_id;
  870. struct efc_node *node = (struct efc_node *)arg;
  871. struct efc *efc = node->efc;
  872. port_id = ntoh24(hdr->fh_s_id);
  873. if (WARN_ON(port_id != node->rnode.fc_id))
  874. return;
  875. if ((!(ntoh24(hdr->fh_f_ctl) & FC_FC_END_SEQ)) ||
  876. !(ntoh24(hdr->fh_f_ctl) & FC_FC_SEQ_INIT)) {
  877. node_printf(node,
  878. "Drop frame hdr = %08x %08x %08x %08x %08x %08x\n",
  879. cpu_to_be32(((u32 *)hdr)[0]),
  880. cpu_to_be32(((u32 *)hdr)[1]),
  881. cpu_to_be32(((u32 *)hdr)[2]),
  882. cpu_to_be32(((u32 *)hdr)[3]),
  883. cpu_to_be32(((u32 *)hdr)[4]),
  884. cpu_to_be32(((u32 *)hdr)[5]));
  885. return;
  886. }
  887. switch (hdr->fh_r_ctl) {
  888. case FC_RCTL_ELS_REQ:
  889. case FC_RCTL_ELS_REP:
  890. efc_node_recv_els_frame(node, seq);
  891. break;
  892. case FC_RCTL_BA_ABTS:
  893. case FC_RCTL_BA_ACC:
  894. case FC_RCTL_BA_RJT:
  895. case FC_RCTL_BA_NOP:
  896. efc_log_err(efc, "Received ABTS:\n");
  897. break;
  898. case FC_RCTL_DD_UNSOL_CMD:
  899. case FC_RCTL_DD_UNSOL_CTL:
  900. switch (hdr->fh_type) {
  901. case FC_TYPE_FCP:
  902. if ((hdr->fh_r_ctl & 0xf) == FC_RCTL_DD_UNSOL_CMD) {
  903. if (!node->fcp_enabled) {
  904. efc_node_recv_fcp_cmd(node, seq);
  905. break;
  906. }
  907. efc_log_err(efc, "Recvd FCP CMD. Drop IO\n");
  908. } else if ((hdr->fh_r_ctl & 0xf) ==
  909. FC_RCTL_DD_SOL_DATA) {
  910. node_printf(node,
  911. "solicited data recvd. Drop IO\n");
  912. }
  913. break;
  914. case FC_TYPE_CT:
  915. efc_node_recv_ct_frame(node, seq);
  916. break;
  917. default:
  918. break;
  919. }
  920. break;
  921. default:
  922. efc_log_err(efc, "Unhandled frame rctl: %02x\n", hdr->fh_r_ctl);
  923. }
  924. }