bnx2fc_els.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. /*
  2. * bnx2fc_els.c: Broadcom NetXtreme II Linux FCoE offload driver.
  3. * This file contains helper routines that handle ELS requests
  4. * and responses.
  5. *
  6. * Copyright (c) 2008 - 2010 Broadcom Corporation
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation.
  11. *
  12. * Written by: Bhanu Prakash Gollapudi (bprakash@broadcom.com)
  13. */
  14. #include "bnx2fc.h"
  15. static void bnx2fc_logo_resp(struct fc_seq *seq, struct fc_frame *fp,
  16. void *arg);
  17. static void bnx2fc_flogi_resp(struct fc_seq *seq, struct fc_frame *fp,
  18. void *arg);
  19. static int bnx2fc_initiate_els(struct bnx2fc_rport *tgt, unsigned int op,
  20. void *data, u32 data_len,
  21. void (*cb_func)(struct bnx2fc_els_cb_arg *cb_arg),
  22. struct bnx2fc_els_cb_arg *cb_arg, u32 timer_msec);
  23. static void bnx2fc_rrq_compl(struct bnx2fc_els_cb_arg *cb_arg)
  24. {
  25. struct bnx2fc_cmd *orig_io_req;
  26. struct bnx2fc_cmd *rrq_req;
  27. int rc = 0;
  28. BUG_ON(!cb_arg);
  29. rrq_req = cb_arg->io_req;
  30. orig_io_req = cb_arg->aborted_io_req;
  31. BUG_ON(!orig_io_req);
  32. BNX2FC_ELS_DBG("rrq_compl: orig xid = 0x%x, rrq_xid = 0x%x\n",
  33. orig_io_req->xid, rrq_req->xid);
  34. kref_put(&orig_io_req->refcount, bnx2fc_cmd_release);
  35. if (test_and_clear_bit(BNX2FC_FLAG_ELS_TIMEOUT, &rrq_req->req_flags)) {
  36. /*
  37. * els req is timed out. cleanup the IO with FW and
  38. * drop the completion. Remove from active_cmd_queue.
  39. */
  40. BNX2FC_ELS_DBG("rrq xid - 0x%x timed out, clean it up\n",
  41. rrq_req->xid);
  42. if (rrq_req->on_active_queue) {
  43. list_del_init(&rrq_req->link);
  44. rrq_req->on_active_queue = 0;
  45. rc = bnx2fc_initiate_cleanup(rrq_req);
  46. BUG_ON(rc);
  47. }
  48. }
  49. kfree(cb_arg);
  50. }
  51. int bnx2fc_send_rrq(struct bnx2fc_cmd *aborted_io_req)
  52. {
  53. struct fc_els_rrq rrq;
  54. struct bnx2fc_rport *tgt = aborted_io_req->tgt;
  55. struct fc_lport *lport = tgt->rdata->local_port;
  56. struct bnx2fc_els_cb_arg *cb_arg = NULL;
  57. u32 sid = tgt->sid;
  58. u32 r_a_tov = lport->r_a_tov;
  59. unsigned long start = jiffies;
  60. int rc;
  61. BNX2FC_ELS_DBG("Sending RRQ orig_xid = 0x%x\n",
  62. aborted_io_req->xid);
  63. memset(&rrq, 0, sizeof(rrq));
  64. cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_NOIO);
  65. if (!cb_arg) {
  66. printk(KERN_ERR PFX "Unable to allocate cb_arg for RRQ\n");
  67. rc = -ENOMEM;
  68. goto rrq_err;
  69. }
  70. cb_arg->aborted_io_req = aborted_io_req;
  71. rrq.rrq_cmd = ELS_RRQ;
  72. hton24(rrq.rrq_s_id, sid);
  73. rrq.rrq_ox_id = htons(aborted_io_req->xid);
  74. rrq.rrq_rx_id = htons(aborted_io_req->task->rx_wr_tx_rd.rx_id);
  75. retry_rrq:
  76. rc = bnx2fc_initiate_els(tgt, ELS_RRQ, &rrq, sizeof(rrq),
  77. bnx2fc_rrq_compl, cb_arg,
  78. r_a_tov);
  79. if (rc == -ENOMEM) {
  80. if (time_after(jiffies, start + (10 * HZ))) {
  81. BNX2FC_ELS_DBG("rrq Failed\n");
  82. rc = FAILED;
  83. goto rrq_err;
  84. }
  85. msleep(20);
  86. goto retry_rrq;
  87. }
  88. rrq_err:
  89. if (rc) {
  90. BNX2FC_ELS_DBG("RRQ failed - release orig io req 0x%x\n",
  91. aborted_io_req->xid);
  92. kfree(cb_arg);
  93. spin_lock_bh(&tgt->tgt_lock);
  94. kref_put(&aborted_io_req->refcount, bnx2fc_cmd_release);
  95. spin_unlock_bh(&tgt->tgt_lock);
  96. }
  97. return rc;
  98. }
  99. static void bnx2fc_l2_els_compl(struct bnx2fc_els_cb_arg *cb_arg)
  100. {
  101. struct bnx2fc_cmd *els_req;
  102. struct bnx2fc_rport *tgt;
  103. struct bnx2fc_mp_req *mp_req;
  104. struct fc_frame_header *fc_hdr;
  105. unsigned char *buf;
  106. void *resp_buf;
  107. u32 resp_len, hdr_len;
  108. u16 l2_oxid;
  109. int frame_len;
  110. int rc = 0;
  111. l2_oxid = cb_arg->l2_oxid;
  112. BNX2FC_ELS_DBG("ELS COMPL - l2_oxid = 0x%x\n", l2_oxid);
  113. els_req = cb_arg->io_req;
  114. if (test_and_clear_bit(BNX2FC_FLAG_ELS_TIMEOUT, &els_req->req_flags)) {
  115. /*
  116. * els req is timed out. cleanup the IO with FW and
  117. * drop the completion. libfc will handle the els timeout
  118. */
  119. if (els_req->on_active_queue) {
  120. list_del_init(&els_req->link);
  121. els_req->on_active_queue = 0;
  122. rc = bnx2fc_initiate_cleanup(els_req);
  123. BUG_ON(rc);
  124. }
  125. goto free_arg;
  126. }
  127. tgt = els_req->tgt;
  128. mp_req = &(els_req->mp_req);
  129. fc_hdr = &(mp_req->resp_fc_hdr);
  130. resp_len = mp_req->resp_len;
  131. resp_buf = mp_req->resp_buf;
  132. buf = kzalloc(PAGE_SIZE, GFP_ATOMIC);
  133. if (!buf) {
  134. printk(KERN_ERR PFX "Unable to alloc mp buf\n");
  135. goto free_arg;
  136. }
  137. hdr_len = sizeof(*fc_hdr);
  138. if (hdr_len + resp_len > PAGE_SIZE) {
  139. printk(KERN_ERR PFX "l2_els_compl: resp len is "
  140. "beyond page size\n");
  141. goto free_buf;
  142. }
  143. memcpy(buf, fc_hdr, hdr_len);
  144. memcpy(buf + hdr_len, resp_buf, resp_len);
  145. frame_len = hdr_len + resp_len;
  146. bnx2fc_process_l2_frame_compl(tgt, buf, frame_len, l2_oxid);
  147. free_buf:
  148. kfree(buf);
  149. free_arg:
  150. kfree(cb_arg);
  151. }
  152. int bnx2fc_send_adisc(struct bnx2fc_rport *tgt, struct fc_frame *fp)
  153. {
  154. struct fc_els_adisc *adisc;
  155. struct fc_frame_header *fh;
  156. struct bnx2fc_els_cb_arg *cb_arg;
  157. struct fc_lport *lport = tgt->rdata->local_port;
  158. u32 r_a_tov = lport->r_a_tov;
  159. int rc;
  160. fh = fc_frame_header_get(fp);
  161. cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_ATOMIC);
  162. if (!cb_arg) {
  163. printk(KERN_ERR PFX "Unable to allocate cb_arg for ADISC\n");
  164. return -ENOMEM;
  165. }
  166. cb_arg->l2_oxid = ntohs(fh->fh_ox_id);
  167. BNX2FC_ELS_DBG("send ADISC: l2_oxid = 0x%x\n", cb_arg->l2_oxid);
  168. adisc = fc_frame_payload_get(fp, sizeof(*adisc));
  169. /* adisc is initialized by libfc */
  170. rc = bnx2fc_initiate_els(tgt, ELS_ADISC, adisc, sizeof(*adisc),
  171. bnx2fc_l2_els_compl, cb_arg, 2 * r_a_tov);
  172. if (rc)
  173. kfree(cb_arg);
  174. return rc;
  175. }
  176. int bnx2fc_send_logo(struct bnx2fc_rport *tgt, struct fc_frame *fp)
  177. {
  178. struct fc_els_logo *logo;
  179. struct fc_frame_header *fh;
  180. struct bnx2fc_els_cb_arg *cb_arg;
  181. struct fc_lport *lport = tgt->rdata->local_port;
  182. u32 r_a_tov = lport->r_a_tov;
  183. int rc;
  184. fh = fc_frame_header_get(fp);
  185. cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_ATOMIC);
  186. if (!cb_arg) {
  187. printk(KERN_ERR PFX "Unable to allocate cb_arg for LOGO\n");
  188. return -ENOMEM;
  189. }
  190. cb_arg->l2_oxid = ntohs(fh->fh_ox_id);
  191. BNX2FC_ELS_DBG("Send LOGO: l2_oxid = 0x%x\n", cb_arg->l2_oxid);
  192. logo = fc_frame_payload_get(fp, sizeof(*logo));
  193. /* logo is initialized by libfc */
  194. rc = bnx2fc_initiate_els(tgt, ELS_LOGO, logo, sizeof(*logo),
  195. bnx2fc_l2_els_compl, cb_arg, 2 * r_a_tov);
  196. if (rc)
  197. kfree(cb_arg);
  198. return rc;
  199. }
  200. int bnx2fc_send_rls(struct bnx2fc_rport *tgt, struct fc_frame *fp)
  201. {
  202. struct fc_els_rls *rls;
  203. struct fc_frame_header *fh;
  204. struct bnx2fc_els_cb_arg *cb_arg;
  205. struct fc_lport *lport = tgt->rdata->local_port;
  206. u32 r_a_tov = lport->r_a_tov;
  207. int rc;
  208. fh = fc_frame_header_get(fp);
  209. cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_ATOMIC);
  210. if (!cb_arg) {
  211. printk(KERN_ERR PFX "Unable to allocate cb_arg for LOGO\n");
  212. return -ENOMEM;
  213. }
  214. cb_arg->l2_oxid = ntohs(fh->fh_ox_id);
  215. rls = fc_frame_payload_get(fp, sizeof(*rls));
  216. /* rls is initialized by libfc */
  217. rc = bnx2fc_initiate_els(tgt, ELS_RLS, rls, sizeof(*rls),
  218. bnx2fc_l2_els_compl, cb_arg, 2 * r_a_tov);
  219. if (rc)
  220. kfree(cb_arg);
  221. return rc;
  222. }
  223. static int bnx2fc_initiate_els(struct bnx2fc_rport *tgt, unsigned int op,
  224. void *data, u32 data_len,
  225. void (*cb_func)(struct bnx2fc_els_cb_arg *cb_arg),
  226. struct bnx2fc_els_cb_arg *cb_arg, u32 timer_msec)
  227. {
  228. struct fcoe_port *port = tgt->port;
  229. struct bnx2fc_hba *hba = port->priv;
  230. struct fc_rport *rport = tgt->rport;
  231. struct fc_lport *lport = port->lport;
  232. struct bnx2fc_cmd *els_req;
  233. struct bnx2fc_mp_req *mp_req;
  234. struct fc_frame_header *fc_hdr;
  235. struct fcoe_task_ctx_entry *task;
  236. struct fcoe_task_ctx_entry *task_page;
  237. int rc = 0;
  238. int task_idx, index;
  239. u32 did, sid;
  240. u16 xid;
  241. rc = fc_remote_port_chkready(rport);
  242. if (rc) {
  243. printk(KERN_ALERT PFX "els 0x%x: rport not ready\n", op);
  244. rc = -EINVAL;
  245. goto els_err;
  246. }
  247. if (lport->state != LPORT_ST_READY || !(lport->link_up)) {
  248. printk(KERN_ALERT PFX "els 0x%x: link is not ready\n", op);
  249. rc = -EINVAL;
  250. goto els_err;
  251. }
  252. if (!(test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags)) ||
  253. (test_bit(BNX2FC_FLAG_EXPL_LOGO, &tgt->flags))) {
  254. printk(KERN_ERR PFX "els 0x%x: tgt not ready\n", op);
  255. rc = -EINVAL;
  256. goto els_err;
  257. }
  258. els_req = bnx2fc_elstm_alloc(tgt, BNX2FC_ELS);
  259. if (!els_req) {
  260. rc = -ENOMEM;
  261. goto els_err;
  262. }
  263. els_req->sc_cmd = NULL;
  264. els_req->port = port;
  265. els_req->tgt = tgt;
  266. els_req->cb_func = cb_func;
  267. cb_arg->io_req = els_req;
  268. els_req->cb_arg = cb_arg;
  269. mp_req = (struct bnx2fc_mp_req *)&(els_req->mp_req);
  270. rc = bnx2fc_init_mp_req(els_req);
  271. if (rc == FAILED) {
  272. printk(KERN_ALERT PFX "ELS MP request init failed\n");
  273. spin_lock_bh(&tgt->tgt_lock);
  274. kref_put(&els_req->refcount, bnx2fc_cmd_release);
  275. spin_unlock_bh(&tgt->tgt_lock);
  276. rc = -ENOMEM;
  277. goto els_err;
  278. } else {
  279. /* rc SUCCESS */
  280. rc = 0;
  281. }
  282. /* Set the data_xfer_len to the size of ELS payload */
  283. mp_req->req_len = data_len;
  284. els_req->data_xfer_len = mp_req->req_len;
  285. /* Fill ELS Payload */
  286. if ((op >= ELS_LS_RJT) && (op <= ELS_AUTH_ELS)) {
  287. memcpy(mp_req->req_buf, data, data_len);
  288. } else {
  289. printk(KERN_ALERT PFX "Invalid ELS op 0x%x\n", op);
  290. els_req->cb_func = NULL;
  291. els_req->cb_arg = NULL;
  292. spin_lock_bh(&tgt->tgt_lock);
  293. kref_put(&els_req->refcount, bnx2fc_cmd_release);
  294. spin_unlock_bh(&tgt->tgt_lock);
  295. rc = -EINVAL;
  296. }
  297. if (rc)
  298. goto els_err;
  299. /* Fill FC header */
  300. fc_hdr = &(mp_req->req_fc_hdr);
  301. did = tgt->rport->port_id;
  302. sid = tgt->sid;
  303. __fc_fill_fc_hdr(fc_hdr, FC_RCTL_ELS_REQ, did, sid,
  304. FC_TYPE_ELS, FC_FC_FIRST_SEQ | FC_FC_END_SEQ |
  305. FC_FC_SEQ_INIT, 0);
  306. /* Obtain exchange id */
  307. xid = els_req->xid;
  308. task_idx = xid/BNX2FC_TASKS_PER_PAGE;
  309. index = xid % BNX2FC_TASKS_PER_PAGE;
  310. /* Initialize task context for this IO request */
  311. task_page = (struct fcoe_task_ctx_entry *) hba->task_ctx[task_idx];
  312. task = &(task_page[index]);
  313. bnx2fc_init_mp_task(els_req, task);
  314. spin_lock_bh(&tgt->tgt_lock);
  315. if (!test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags)) {
  316. printk(KERN_ERR PFX "initiate_els.. session not ready\n");
  317. els_req->cb_func = NULL;
  318. els_req->cb_arg = NULL;
  319. kref_put(&els_req->refcount, bnx2fc_cmd_release);
  320. spin_unlock_bh(&tgt->tgt_lock);
  321. return -EINVAL;
  322. }
  323. if (timer_msec)
  324. bnx2fc_cmd_timer_set(els_req, timer_msec);
  325. bnx2fc_add_2_sq(tgt, xid);
  326. els_req->on_active_queue = 1;
  327. list_add_tail(&els_req->link, &tgt->els_queue);
  328. /* Ring doorbell */
  329. bnx2fc_ring_doorbell(tgt);
  330. spin_unlock_bh(&tgt->tgt_lock);
  331. els_err:
  332. return rc;
  333. }
  334. void bnx2fc_process_els_compl(struct bnx2fc_cmd *els_req,
  335. struct fcoe_task_ctx_entry *task, u8 num_rq)
  336. {
  337. struct bnx2fc_mp_req *mp_req;
  338. struct fc_frame_header *fc_hdr;
  339. u64 *hdr;
  340. u64 *temp_hdr;
  341. BNX2FC_ELS_DBG("Entered process_els_compl xid = 0x%x"
  342. "cmd_type = %d\n", els_req->xid, els_req->cmd_type);
  343. if (test_and_set_bit(BNX2FC_FLAG_ELS_DONE,
  344. &els_req->req_flags)) {
  345. BNX2FC_ELS_DBG("Timer context finished processing this "
  346. "els - 0x%x\n", els_req->xid);
  347. /* This IO doesn't receive cleanup completion */
  348. kref_put(&els_req->refcount, bnx2fc_cmd_release);
  349. return;
  350. }
  351. /* Cancel the timeout_work, as we received the response */
  352. if (cancel_delayed_work(&els_req->timeout_work))
  353. kref_put(&els_req->refcount,
  354. bnx2fc_cmd_release); /* drop timer hold */
  355. if (els_req->on_active_queue) {
  356. list_del_init(&els_req->link);
  357. els_req->on_active_queue = 0;
  358. }
  359. mp_req = &(els_req->mp_req);
  360. fc_hdr = &(mp_req->resp_fc_hdr);
  361. hdr = (u64 *)fc_hdr;
  362. temp_hdr = (u64 *)
  363. &task->cmn.general.cmd_info.mp_fc_frame.fc_hdr;
  364. hdr[0] = cpu_to_be64(temp_hdr[0]);
  365. hdr[1] = cpu_to_be64(temp_hdr[1]);
  366. hdr[2] = cpu_to_be64(temp_hdr[2]);
  367. mp_req->resp_len = task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_off;
  368. /* Parse ELS response */
  369. if ((els_req->cb_func) && (els_req->cb_arg)) {
  370. els_req->cb_func(els_req->cb_arg);
  371. els_req->cb_arg = NULL;
  372. }
  373. kref_put(&els_req->refcount, bnx2fc_cmd_release);
  374. }
  375. static void bnx2fc_flogi_resp(struct fc_seq *seq, struct fc_frame *fp,
  376. void *arg)
  377. {
  378. struct fcoe_ctlr *fip = arg;
  379. struct fc_exch *exch = fc_seq_exch(seq);
  380. struct fc_lport *lport = exch->lp;
  381. u8 *mac;
  382. struct fc_frame_header *fh;
  383. u8 op;
  384. if (IS_ERR(fp))
  385. goto done;
  386. mac = fr_cb(fp)->granted_mac;
  387. if (is_zero_ether_addr(mac)) {
  388. fh = fc_frame_header_get(fp);
  389. if (fh->fh_type != FC_TYPE_ELS) {
  390. printk(KERN_ERR PFX "bnx2fc_flogi_resp:"
  391. "fh_type != FC_TYPE_ELS\n");
  392. fc_frame_free(fp);
  393. return;
  394. }
  395. op = fc_frame_payload_op(fp);
  396. if (lport->vport) {
  397. if (op == ELS_LS_RJT) {
  398. printk(KERN_ERR PFX "bnx2fc_flogi_resp is LS_RJT\n");
  399. fc_vport_terminate(lport->vport);
  400. fc_frame_free(fp);
  401. return;
  402. }
  403. }
  404. if (fcoe_ctlr_recv_flogi(fip, lport, fp)) {
  405. fc_frame_free(fp);
  406. return;
  407. }
  408. }
  409. fip->update_mac(lport, mac);
  410. done:
  411. fc_lport_flogi_resp(seq, fp, lport);
  412. }
  413. static void bnx2fc_logo_resp(struct fc_seq *seq, struct fc_frame *fp,
  414. void *arg)
  415. {
  416. struct fcoe_ctlr *fip = arg;
  417. struct fc_exch *exch = fc_seq_exch(seq);
  418. struct fc_lport *lport = exch->lp;
  419. static u8 zero_mac[ETH_ALEN] = { 0 };
  420. if (!IS_ERR(fp))
  421. fip->update_mac(lport, zero_mac);
  422. fc_lport_logo_resp(seq, fp, lport);
  423. }
  424. struct fc_seq *bnx2fc_elsct_send(struct fc_lport *lport, u32 did,
  425. struct fc_frame *fp, unsigned int op,
  426. void (*resp)(struct fc_seq *,
  427. struct fc_frame *,
  428. void *),
  429. void *arg, u32 timeout)
  430. {
  431. struct fcoe_port *port = lport_priv(lport);
  432. struct bnx2fc_hba *hba = port->priv;
  433. struct fcoe_ctlr *fip = &hba->ctlr;
  434. struct fc_frame_header *fh = fc_frame_header_get(fp);
  435. switch (op) {
  436. case ELS_FLOGI:
  437. case ELS_FDISC:
  438. return fc_elsct_send(lport, did, fp, op, bnx2fc_flogi_resp,
  439. fip, timeout);
  440. case ELS_LOGO:
  441. /* only hook onto fabric logouts, not port logouts */
  442. if (ntoh24(fh->fh_d_id) != FC_FID_FLOGI)
  443. break;
  444. return fc_elsct_send(lport, did, fp, op, bnx2fc_logo_resp,
  445. fip, timeout);
  446. }
  447. return fc_elsct_send(lport, did, fp, op, resp, arg, timeout);
  448. }