blob: 76e65a32f38cef5fac802cd68e76c7c1c2c63e49 [file] [log] [blame]
Bhanu Gollapudi853e2bd2011-02-04 12:10:34 -08001/*
Chad Dupuisde909d82015-10-19 15:40:36 -04002 * bnx2fc_els.c: QLogic Linux FCoE offload driver.
Bhanu Gollapudi853e2bd2011-02-04 12:10:34 -08003 * This file contains helper routines that handle ELS requests
4 * and responses.
5 *
Chad Dupuis97586092015-10-19 15:40:35 -04006 * Copyright (c) 2008-2013 Broadcom Corporation
Chad Dupuis21144b82017-06-26 08:59:34 -07007 * Copyright (c) 2014-2016 QLogic Corporation
8 * Copyright (c) 2016-2017 Cavium Inc.
Bhanu Gollapudi853e2bd2011-02-04 12:10:34 -08009 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation.
13 *
14 * Written by: Bhanu Prakash Gollapudi (bprakash@broadcom.com)
15 */
16
17#include "bnx2fc.h"
18
19static void bnx2fc_logo_resp(struct fc_seq *seq, struct fc_frame *fp,
20 void *arg);
21static void bnx2fc_flogi_resp(struct fc_seq *seq, struct fc_frame *fp,
22 void *arg);
23static int bnx2fc_initiate_els(struct bnx2fc_rport *tgt, unsigned int op,
24 void *data, u32 data_len,
25 void (*cb_func)(struct bnx2fc_els_cb_arg *cb_arg),
26 struct bnx2fc_els_cb_arg *cb_arg, u32 timer_msec);
27
28static void bnx2fc_rrq_compl(struct bnx2fc_els_cb_arg *cb_arg)
29{
30 struct bnx2fc_cmd *orig_io_req;
31 struct bnx2fc_cmd *rrq_req;
32 int rc = 0;
33
34 BUG_ON(!cb_arg);
35 rrq_req = cb_arg->io_req;
36 orig_io_req = cb_arg->aborted_io_req;
37 BUG_ON(!orig_io_req);
38 BNX2FC_ELS_DBG("rrq_compl: orig xid = 0x%x, rrq_xid = 0x%x\n",
39 orig_io_req->xid, rrq_req->xid);
40
41 kref_put(&orig_io_req->refcount, bnx2fc_cmd_release);
42
43 if (test_and_clear_bit(BNX2FC_FLAG_ELS_TIMEOUT, &rrq_req->req_flags)) {
44 /*
45 * els req is timed out. cleanup the IO with FW and
46 * drop the completion. Remove from active_cmd_queue.
47 */
48 BNX2FC_ELS_DBG("rrq xid - 0x%x timed out, clean it up\n",
49 rrq_req->xid);
50
51 if (rrq_req->on_active_queue) {
52 list_del_init(&rrq_req->link);
53 rrq_req->on_active_queue = 0;
54 rc = bnx2fc_initiate_cleanup(rrq_req);
55 BUG_ON(rc);
56 }
57 }
58 kfree(cb_arg);
59}
60int bnx2fc_send_rrq(struct bnx2fc_cmd *aborted_io_req)
61{
62
63 struct fc_els_rrq rrq;
64 struct bnx2fc_rport *tgt = aborted_io_req->tgt;
Chad Dupuisde08f462017-06-26 08:59:33 -070065 struct fc_lport *lport = NULL;
Bhanu Gollapudi853e2bd2011-02-04 12:10:34 -080066 struct bnx2fc_els_cb_arg *cb_arg = NULL;
Chad Dupuisde08f462017-06-26 08:59:33 -070067 u32 sid = 0;
68 u32 r_a_tov = 0;
Bhanu Gollapudi853e2bd2011-02-04 12:10:34 -080069 unsigned long start = jiffies;
70 int rc;
71
Chad Dupuisde08f462017-06-26 08:59:33 -070072 if (!test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags))
73 return -EINVAL;
74
75 lport = tgt->rdata->local_port;
76 sid = tgt->sid;
77 r_a_tov = lport->r_a_tov;
78
Bhanu Gollapudi853e2bd2011-02-04 12:10:34 -080079 BNX2FC_ELS_DBG("Sending RRQ orig_xid = 0x%x\n",
80 aborted_io_req->xid);
81 memset(&rrq, 0, sizeof(rrq));
82
83 cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_NOIO);
84 if (!cb_arg) {
85 printk(KERN_ERR PFX "Unable to allocate cb_arg for RRQ\n");
86 rc = -ENOMEM;
87 goto rrq_err;
88 }
89
90 cb_arg->aborted_io_req = aborted_io_req;
91
92 rrq.rrq_cmd = ELS_RRQ;
93 hton24(rrq.rrq_s_id, sid);
94 rrq.rrq_ox_id = htons(aborted_io_req->xid);
Vlad Zolotarov619c5cb2011-06-14 14:33:44 +030095 rrq.rrq_rx_id = htons(aborted_io_req->task->rxwr_txrd.var_ctx.rx_id);
Bhanu Gollapudi853e2bd2011-02-04 12:10:34 -080096
97retry_rrq:
98 rc = bnx2fc_initiate_els(tgt, ELS_RRQ, &rrq, sizeof(rrq),
99 bnx2fc_rrq_compl, cb_arg,
100 r_a_tov);
101 if (rc == -ENOMEM) {
102 if (time_after(jiffies, start + (10 * HZ))) {
103 BNX2FC_ELS_DBG("rrq Failed\n");
104 rc = FAILED;
105 goto rrq_err;
106 }
107 msleep(20);
108 goto retry_rrq;
109 }
110rrq_err:
111 if (rc) {
112 BNX2FC_ELS_DBG("RRQ failed - release orig io req 0x%x\n",
113 aborted_io_req->xid);
114 kfree(cb_arg);
115 spin_lock_bh(&tgt->tgt_lock);
116 kref_put(&aborted_io_req->refcount, bnx2fc_cmd_release);
117 spin_unlock_bh(&tgt->tgt_lock);
118 }
119 return rc;
120}
121
122static void bnx2fc_l2_els_compl(struct bnx2fc_els_cb_arg *cb_arg)
123{
124 struct bnx2fc_cmd *els_req;
125 struct bnx2fc_rport *tgt;
126 struct bnx2fc_mp_req *mp_req;
127 struct fc_frame_header *fc_hdr;
128 unsigned char *buf;
129 void *resp_buf;
130 u32 resp_len, hdr_len;
131 u16 l2_oxid;
132 int frame_len;
133 int rc = 0;
134
135 l2_oxid = cb_arg->l2_oxid;
136 BNX2FC_ELS_DBG("ELS COMPL - l2_oxid = 0x%x\n", l2_oxid);
137
138 els_req = cb_arg->io_req;
139 if (test_and_clear_bit(BNX2FC_FLAG_ELS_TIMEOUT, &els_req->req_flags)) {
140 /*
141 * els req is timed out. cleanup the IO with FW and
142 * drop the completion. libfc will handle the els timeout
143 */
144 if (els_req->on_active_queue) {
145 list_del_init(&els_req->link);
146 els_req->on_active_queue = 0;
147 rc = bnx2fc_initiate_cleanup(els_req);
148 BUG_ON(rc);
149 }
150 goto free_arg;
151 }
152
153 tgt = els_req->tgt;
154 mp_req = &(els_req->mp_req);
155 fc_hdr = &(mp_req->resp_fc_hdr);
156 resp_len = mp_req->resp_len;
157 resp_buf = mp_req->resp_buf;
158
159 buf = kzalloc(PAGE_SIZE, GFP_ATOMIC);
160 if (!buf) {
161 printk(KERN_ERR PFX "Unable to alloc mp buf\n");
162 goto free_arg;
163 }
164 hdr_len = sizeof(*fc_hdr);
165 if (hdr_len + resp_len > PAGE_SIZE) {
166 printk(KERN_ERR PFX "l2_els_compl: resp len is "
167 "beyond page size\n");
168 goto free_buf;
169 }
170 memcpy(buf, fc_hdr, hdr_len);
171 memcpy(buf + hdr_len, resp_buf, resp_len);
172 frame_len = hdr_len + resp_len;
173
174 bnx2fc_process_l2_frame_compl(tgt, buf, frame_len, l2_oxid);
175
176free_buf:
177 kfree(buf);
178free_arg:
179 kfree(cb_arg);
180}
181
182int bnx2fc_send_adisc(struct bnx2fc_rport *tgt, struct fc_frame *fp)
183{
184 struct fc_els_adisc *adisc;
185 struct fc_frame_header *fh;
186 struct bnx2fc_els_cb_arg *cb_arg;
187 struct fc_lport *lport = tgt->rdata->local_port;
188 u32 r_a_tov = lport->r_a_tov;
189 int rc;
190
191 fh = fc_frame_header_get(fp);
192 cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_ATOMIC);
193 if (!cb_arg) {
194 printk(KERN_ERR PFX "Unable to allocate cb_arg for ADISC\n");
195 return -ENOMEM;
196 }
197
198 cb_arg->l2_oxid = ntohs(fh->fh_ox_id);
199
200 BNX2FC_ELS_DBG("send ADISC: l2_oxid = 0x%x\n", cb_arg->l2_oxid);
201 adisc = fc_frame_payload_get(fp, sizeof(*adisc));
202 /* adisc is initialized by libfc */
203 rc = bnx2fc_initiate_els(tgt, ELS_ADISC, adisc, sizeof(*adisc),
204 bnx2fc_l2_els_compl, cb_arg, 2 * r_a_tov);
205 if (rc)
206 kfree(cb_arg);
207 return rc;
208}
209
210int bnx2fc_send_logo(struct bnx2fc_rport *tgt, struct fc_frame *fp)
211{
212 struct fc_els_logo *logo;
213 struct fc_frame_header *fh;
214 struct bnx2fc_els_cb_arg *cb_arg;
215 struct fc_lport *lport = tgt->rdata->local_port;
216 u32 r_a_tov = lport->r_a_tov;
217 int rc;
218
219 fh = fc_frame_header_get(fp);
220 cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_ATOMIC);
221 if (!cb_arg) {
222 printk(KERN_ERR PFX "Unable to allocate cb_arg for LOGO\n");
223 return -ENOMEM;
224 }
225
226 cb_arg->l2_oxid = ntohs(fh->fh_ox_id);
227
228 BNX2FC_ELS_DBG("Send LOGO: l2_oxid = 0x%x\n", cb_arg->l2_oxid);
229 logo = fc_frame_payload_get(fp, sizeof(*logo));
230 /* logo is initialized by libfc */
231 rc = bnx2fc_initiate_els(tgt, ELS_LOGO, logo, sizeof(*logo),
232 bnx2fc_l2_els_compl, cb_arg, 2 * r_a_tov);
233 if (rc)
234 kfree(cb_arg);
235 return rc;
236}
237
238int bnx2fc_send_rls(struct bnx2fc_rport *tgt, struct fc_frame *fp)
239{
240 struct fc_els_rls *rls;
241 struct fc_frame_header *fh;
242 struct bnx2fc_els_cb_arg *cb_arg;
243 struct fc_lport *lport = tgt->rdata->local_port;
244 u32 r_a_tov = lport->r_a_tov;
245 int rc;
246
247 fh = fc_frame_header_get(fp);
248 cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_ATOMIC);
249 if (!cb_arg) {
250 printk(KERN_ERR PFX "Unable to allocate cb_arg for LOGO\n");
251 return -ENOMEM;
252 }
253
254 cb_arg->l2_oxid = ntohs(fh->fh_ox_id);
255
256 rls = fc_frame_payload_get(fp, sizeof(*rls));
257 /* rls is initialized by libfc */
258 rc = bnx2fc_initiate_els(tgt, ELS_RLS, rls, sizeof(*rls),
259 bnx2fc_l2_els_compl, cb_arg, 2 * r_a_tov);
260 if (rc)
261 kfree(cb_arg);
262 return rc;
263}
264
Baoyou Xie3f7d67d2016-09-04 14:52:21 +0800265static void bnx2fc_srr_compl(struct bnx2fc_els_cb_arg *cb_arg)
Bhanu Prakash Gollapudi74446952011-07-27 11:32:06 -0700266{
267 struct bnx2fc_mp_req *mp_req;
268 struct fc_frame_header *fc_hdr, *fh;
269 struct bnx2fc_cmd *srr_req;
270 struct bnx2fc_cmd *orig_io_req;
271 struct fc_frame *fp;
272 unsigned char *buf;
273 void *resp_buf;
274 u32 resp_len, hdr_len;
275 u8 opcode;
276 int rc = 0;
277
278 orig_io_req = cb_arg->aborted_io_req;
279 srr_req = cb_arg->io_req;
Bhanu Prakash Gollapudi74446952011-07-27 11:32:06 -0700280 if (test_and_clear_bit(BNX2FC_FLAG_ELS_TIMEOUT, &srr_req->req_flags)) {
281 /* SRR timedout */
282 BNX2FC_IO_DBG(srr_req, "srr timed out, abort "
283 "orig_io - 0x%x\n",
284 orig_io_req->xid);
285 rc = bnx2fc_initiate_abts(srr_req);
286 if (rc != SUCCESS) {
287 BNX2FC_IO_DBG(srr_req, "srr_compl: initiate_abts "
288 "failed. issue cleanup\n");
289 bnx2fc_initiate_cleanup(srr_req);
290 }
Bhanu Prakash Gollapudi32c30452011-10-23 23:23:57 -0700291 if (test_bit(BNX2FC_FLAG_IO_COMPL, &orig_io_req->req_flags) ||
292 test_bit(BNX2FC_FLAG_ISSUE_ABTS, &orig_io_req->req_flags)) {
293 BNX2FC_IO_DBG(srr_req, "srr_compl:xid 0x%x flags = %lx",
294 orig_io_req->xid, orig_io_req->req_flags);
295 goto srr_compl_done;
296 }
Bhanu Prakash Gollapudi74446952011-07-27 11:32:06 -0700297 orig_io_req->srr_retry++;
298 if (orig_io_req->srr_retry <= SRR_RETRY_COUNT) {
299 struct bnx2fc_rport *tgt = orig_io_req->tgt;
300 spin_unlock_bh(&tgt->tgt_lock);
301 rc = bnx2fc_send_srr(orig_io_req,
302 orig_io_req->srr_offset,
303 orig_io_req->srr_rctl);
304 spin_lock_bh(&tgt->tgt_lock);
305 if (!rc)
306 goto srr_compl_done;
307 }
308
309 rc = bnx2fc_initiate_abts(orig_io_req);
310 if (rc != SUCCESS) {
311 BNX2FC_IO_DBG(srr_req, "srr_compl: initiate_abts "
312 "failed xid = 0x%x. issue cleanup\n",
313 orig_io_req->xid);
314 bnx2fc_initiate_cleanup(orig_io_req);
315 }
316 goto srr_compl_done;
317 }
Bhanu Prakash Gollapudi32c30452011-10-23 23:23:57 -0700318 if (test_bit(BNX2FC_FLAG_IO_COMPL, &orig_io_req->req_flags) ||
319 test_bit(BNX2FC_FLAG_ISSUE_ABTS, &orig_io_req->req_flags)) {
320 BNX2FC_IO_DBG(srr_req, "srr_compl:xid - 0x%x flags = %lx",
321 orig_io_req->xid, orig_io_req->req_flags);
322 goto srr_compl_done;
323 }
Bhanu Prakash Gollapudi74446952011-07-27 11:32:06 -0700324 mp_req = &(srr_req->mp_req);
325 fc_hdr = &(mp_req->resp_fc_hdr);
326 resp_len = mp_req->resp_len;
327 resp_buf = mp_req->resp_buf;
328
329 hdr_len = sizeof(*fc_hdr);
330 buf = kzalloc(PAGE_SIZE, GFP_ATOMIC);
331 if (!buf) {
332 printk(KERN_ERR PFX "srr buf: mem alloc failure\n");
333 goto srr_compl_done;
334 }
335 memcpy(buf, fc_hdr, hdr_len);
336 memcpy(buf + hdr_len, resp_buf, resp_len);
337
338 fp = fc_frame_alloc(NULL, resp_len);
339 if (!fp) {
340 printk(KERN_ERR PFX "fc_frame_alloc failure\n");
341 goto free_buf;
342 }
343
344 fh = (struct fc_frame_header *) fc_frame_header_get(fp);
345 /* Copy FC Frame header and payload into the frame */
346 memcpy(fh, buf, hdr_len + resp_len);
347
348 opcode = fc_frame_payload_op(fp);
349 switch (opcode) {
350 case ELS_LS_ACC:
351 BNX2FC_IO_DBG(srr_req, "SRR success\n");
352 break;
353 case ELS_LS_RJT:
354 BNX2FC_IO_DBG(srr_req, "SRR rejected\n");
355 rc = bnx2fc_initiate_abts(orig_io_req);
356 if (rc != SUCCESS) {
357 BNX2FC_IO_DBG(srr_req, "srr_compl: initiate_abts "
358 "failed xid = 0x%x. issue cleanup\n",
359 orig_io_req->xid);
360 bnx2fc_initiate_cleanup(orig_io_req);
361 }
362 break;
363 default:
364 BNX2FC_IO_DBG(srr_req, "srr compl - invalid opcode = %d\n",
365 opcode);
366 break;
367 }
368 fc_frame_free(fp);
369free_buf:
370 kfree(buf);
371srr_compl_done:
372 kref_put(&orig_io_req->refcount, bnx2fc_cmd_release);
373}
374
Baoyou Xie3f7d67d2016-09-04 14:52:21 +0800375static void bnx2fc_rec_compl(struct bnx2fc_els_cb_arg *cb_arg)
Bhanu Prakash Gollapudi74446952011-07-27 11:32:06 -0700376{
377 struct bnx2fc_cmd *orig_io_req, *new_io_req;
378 struct bnx2fc_cmd *rec_req;
379 struct bnx2fc_mp_req *mp_req;
380 struct fc_frame_header *fc_hdr, *fh;
381 struct fc_els_ls_rjt *rjt;
382 struct fc_els_rec_acc *acc;
383 struct bnx2fc_rport *tgt;
384 struct fcoe_err_report_entry *err_entry;
385 struct scsi_cmnd *sc_cmd;
386 enum fc_rctl r_ctl;
387 unsigned char *buf;
388 void *resp_buf;
389 struct fc_frame *fp;
390 u8 opcode;
391 u32 offset;
392 u32 e_stat;
393 u32 resp_len, hdr_len;
394 int rc = 0;
395 bool send_seq_clnp = false;
396 bool abort_io = false;
397
398 BNX2FC_MISC_DBG("Entered rec_compl callback\n");
399 rec_req = cb_arg->io_req;
400 orig_io_req = cb_arg->aborted_io_req;
401 BNX2FC_IO_DBG(rec_req, "rec_compl: orig xid = 0x%x", orig_io_req->xid);
402 tgt = orig_io_req->tgt;
403
Bhanu Prakash Gollapudi74446952011-07-27 11:32:06 -0700404 /* Handle REC timeout case */
405 if (test_and_clear_bit(BNX2FC_FLAG_ELS_TIMEOUT, &rec_req->req_flags)) {
406 BNX2FC_IO_DBG(rec_req, "timed out, abort "
407 "orig_io - 0x%x\n",
408 orig_io_req->xid);
409 /* els req is timed out. send abts for els */
410 rc = bnx2fc_initiate_abts(rec_req);
411 if (rc != SUCCESS) {
412 BNX2FC_IO_DBG(rec_req, "rec_compl: initiate_abts "
413 "failed. issue cleanup\n");
414 bnx2fc_initiate_cleanup(rec_req);
415 }
416 orig_io_req->rec_retry++;
417 /* REC timedout. send ABTS to the orig IO req */
418 if (orig_io_req->rec_retry <= REC_RETRY_COUNT) {
419 spin_unlock_bh(&tgt->tgt_lock);
420 rc = bnx2fc_send_rec(orig_io_req);
421 spin_lock_bh(&tgt->tgt_lock);
422 if (!rc)
423 goto rec_compl_done;
424 }
425 rc = bnx2fc_initiate_abts(orig_io_req);
426 if (rc != SUCCESS) {
427 BNX2FC_IO_DBG(rec_req, "rec_compl: initiate_abts "
428 "failed xid = 0x%x. issue cleanup\n",
429 orig_io_req->xid);
430 bnx2fc_initiate_cleanup(orig_io_req);
431 }
432 goto rec_compl_done;
433 }
Bhanu Prakash Gollapudic1c16bd2011-08-30 15:54:49 -0700434
435 if (test_bit(BNX2FC_FLAG_IO_COMPL, &orig_io_req->req_flags)) {
436 BNX2FC_IO_DBG(rec_req, "completed"
437 "orig_io - 0x%x\n",
438 orig_io_req->xid);
439 goto rec_compl_done;
440 }
441 if (test_bit(BNX2FC_FLAG_ISSUE_ABTS, &orig_io_req->req_flags)) {
442 BNX2FC_IO_DBG(rec_req, "abts in prog "
443 "orig_io - 0x%x\n",
444 orig_io_req->xid);
445 goto rec_compl_done;
446 }
447
Bhanu Prakash Gollapudi74446952011-07-27 11:32:06 -0700448 mp_req = &(rec_req->mp_req);
449 fc_hdr = &(mp_req->resp_fc_hdr);
450 resp_len = mp_req->resp_len;
451 acc = resp_buf = mp_req->resp_buf;
452
453 hdr_len = sizeof(*fc_hdr);
454
455 buf = kzalloc(PAGE_SIZE, GFP_ATOMIC);
456 if (!buf) {
457 printk(KERN_ERR PFX "rec buf: mem alloc failure\n");
458 goto rec_compl_done;
459 }
460 memcpy(buf, fc_hdr, hdr_len);
461 memcpy(buf + hdr_len, resp_buf, resp_len);
462
463 fp = fc_frame_alloc(NULL, resp_len);
464 if (!fp) {
465 printk(KERN_ERR PFX "fc_frame_alloc failure\n");
466 goto free_buf;
467 }
468
469 fh = (struct fc_frame_header *) fc_frame_header_get(fp);
470 /* Copy FC Frame header and payload into the frame */
471 memcpy(fh, buf, hdr_len + resp_len);
472
473 opcode = fc_frame_payload_op(fp);
474 if (opcode == ELS_LS_RJT) {
475 BNX2FC_IO_DBG(rec_req, "opcode is RJT\n");
476 rjt = fc_frame_payload_get(fp, sizeof(*rjt));
477 if ((rjt->er_reason == ELS_RJT_LOGIC ||
478 rjt->er_reason == ELS_RJT_UNAB) &&
479 rjt->er_explan == ELS_EXPL_OXID_RXID) {
480 BNX2FC_IO_DBG(rec_req, "handle CMD LOST case\n");
481 new_io_req = bnx2fc_cmd_alloc(tgt);
482 if (!new_io_req)
483 goto abort_io;
484 new_io_req->sc_cmd = orig_io_req->sc_cmd;
485 /* cleanup orig_io_req that is with the FW */
486 set_bit(BNX2FC_FLAG_CMD_LOST,
487 &orig_io_req->req_flags);
488 bnx2fc_initiate_cleanup(orig_io_req);
489 /* Post a new IO req with the same sc_cmd */
490 BNX2FC_IO_DBG(rec_req, "Post IO request again\n");
Bhanu Prakash Gollapudi74446952011-07-27 11:32:06 -0700491 rc = bnx2fc_post_io_req(tgt, new_io_req);
Bhanu Prakash Gollapudi74446952011-07-27 11:32:06 -0700492 if (!rc)
493 goto free_frame;
494 BNX2FC_IO_DBG(rec_req, "REC: io post err\n");
495 }
496abort_io:
497 rc = bnx2fc_initiate_abts(orig_io_req);
498 if (rc != SUCCESS) {
499 BNX2FC_IO_DBG(rec_req, "rec_compl: initiate_abts "
500 "failed. issue cleanup\n");
501 bnx2fc_initiate_cleanup(orig_io_req);
502 }
503 } else if (opcode == ELS_LS_ACC) {
504 /* REVISIT: Check if the exchange is already aborted */
505 offset = ntohl(acc->reca_fc4value);
506 e_stat = ntohl(acc->reca_e_stat);
507 if (e_stat & ESB_ST_SEQ_INIT) {
508 BNX2FC_IO_DBG(rec_req, "target has the seq init\n");
509 goto free_frame;
510 }
511 BNX2FC_IO_DBG(rec_req, "e_stat = 0x%x, offset = 0x%x\n",
512 e_stat, offset);
513 /* Seq initiative is with us */
514 err_entry = (struct fcoe_err_report_entry *)
515 &orig_io_req->err_entry;
516 sc_cmd = orig_io_req->sc_cmd;
517 if (sc_cmd->sc_data_direction == DMA_TO_DEVICE) {
518 /* SCSI WRITE command */
519 if (offset == orig_io_req->data_xfer_len) {
520 BNX2FC_IO_DBG(rec_req, "WRITE - resp lost\n");
521 /* FCP_RSP lost */
522 r_ctl = FC_RCTL_DD_CMD_STATUS;
523 offset = 0;
524 } else {
525 /* start transmitting from offset */
526 BNX2FC_IO_DBG(rec_req, "XFER_RDY/DATA lost\n");
527 send_seq_clnp = true;
528 r_ctl = FC_RCTL_DD_DATA_DESC;
529 if (bnx2fc_initiate_seq_cleanup(orig_io_req,
530 offset, r_ctl))
531 abort_io = true;
532 /* XFER_RDY */
533 }
534 } else {
535 /* SCSI READ command */
536 if (err_entry->data.rx_buf_off ==
537 orig_io_req->data_xfer_len) {
538 /* FCP_RSP lost */
539 BNX2FC_IO_DBG(rec_req, "READ - resp lost\n");
540 r_ctl = FC_RCTL_DD_CMD_STATUS;
541 offset = 0;
542 } else {
543 /* request retransmission from this offset */
544 send_seq_clnp = true;
545 offset = err_entry->data.rx_buf_off;
546 BNX2FC_IO_DBG(rec_req, "RD DATA lost\n");
547 /* FCP_DATA lost */
548 r_ctl = FC_RCTL_DD_SOL_DATA;
549 if (bnx2fc_initiate_seq_cleanup(orig_io_req,
550 offset, r_ctl))
551 abort_io = true;
552 }
553 }
554 if (abort_io) {
555 rc = bnx2fc_initiate_abts(orig_io_req);
556 if (rc != SUCCESS) {
557 BNX2FC_IO_DBG(rec_req, "rec_compl:initiate_abts"
558 " failed. issue cleanup\n");
559 bnx2fc_initiate_cleanup(orig_io_req);
560 }
561 } else if (!send_seq_clnp) {
562 BNX2FC_IO_DBG(rec_req, "Send SRR - FCP_RSP\n");
563 spin_unlock_bh(&tgt->tgt_lock);
564 rc = bnx2fc_send_srr(orig_io_req, offset, r_ctl);
565 spin_lock_bh(&tgt->tgt_lock);
566
567 if (rc) {
568 BNX2FC_IO_DBG(rec_req, "Unable to send SRR"
569 " IO will abort\n");
570 }
571 }
572 }
573free_frame:
574 fc_frame_free(fp);
575free_buf:
576 kfree(buf);
577rec_compl_done:
578 kref_put(&orig_io_req->refcount, bnx2fc_cmd_release);
579 kfree(cb_arg);
580}
581
Bhanu Prakash Gollapudi6c5a7ce2011-07-27 11:32:05 -0700582int bnx2fc_send_rec(struct bnx2fc_cmd *orig_io_req)
583{
Bhanu Prakash Gollapudi74446952011-07-27 11:32:06 -0700584 struct fc_els_rec rec;
585 struct bnx2fc_rport *tgt = orig_io_req->tgt;
586 struct fc_lport *lport = tgt->rdata->local_port;
587 struct bnx2fc_els_cb_arg *cb_arg = NULL;
588 u32 sid = tgt->sid;
589 u32 r_a_tov = lport->r_a_tov;
590 int rc;
591
592 BNX2FC_IO_DBG(orig_io_req, "Sending REC\n");
593 memset(&rec, 0, sizeof(rec));
594
595 cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_ATOMIC);
596 if (!cb_arg) {
597 printk(KERN_ERR PFX "Unable to allocate cb_arg for REC\n");
598 rc = -ENOMEM;
599 goto rec_err;
600 }
601 kref_get(&orig_io_req->refcount);
602
603 cb_arg->aborted_io_req = orig_io_req;
604
605 rec.rec_cmd = ELS_REC;
606 hton24(rec.rec_s_id, sid);
607 rec.rec_ox_id = htons(orig_io_req->xid);
608 rec.rec_rx_id = htons(orig_io_req->task->rxwr_txrd.var_ctx.rx_id);
609
610 rc = bnx2fc_initiate_els(tgt, ELS_REC, &rec, sizeof(rec),
611 bnx2fc_rec_compl, cb_arg,
612 r_a_tov);
613rec_err:
614 if (rc) {
615 BNX2FC_IO_DBG(orig_io_req, "REC failed - release\n");
616 spin_lock_bh(&tgt->tgt_lock);
617 kref_put(&orig_io_req->refcount, bnx2fc_cmd_release);
618 spin_unlock_bh(&tgt->tgt_lock);
619 kfree(cb_arg);
620 }
621 return rc;
Bhanu Prakash Gollapudi6c5a7ce2011-07-27 11:32:05 -0700622}
623
624int bnx2fc_send_srr(struct bnx2fc_cmd *orig_io_req, u32 offset, u8 r_ctl)
625{
Bhanu Prakash Gollapudi74446952011-07-27 11:32:06 -0700626 struct fcp_srr srr;
627 struct bnx2fc_rport *tgt = orig_io_req->tgt;
628 struct fc_lport *lport = tgt->rdata->local_port;
629 struct bnx2fc_els_cb_arg *cb_arg = NULL;
630 u32 r_a_tov = lport->r_a_tov;
631 int rc;
632
633 BNX2FC_IO_DBG(orig_io_req, "Sending SRR\n");
634 memset(&srr, 0, sizeof(srr));
635
636 cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_ATOMIC);
637 if (!cb_arg) {
638 printk(KERN_ERR PFX "Unable to allocate cb_arg for SRR\n");
639 rc = -ENOMEM;
640 goto srr_err;
641 }
642 kref_get(&orig_io_req->refcount);
643
644 cb_arg->aborted_io_req = orig_io_req;
645
646 srr.srr_op = ELS_SRR;
647 srr.srr_ox_id = htons(orig_io_req->xid);
648 srr.srr_rx_id = htons(orig_io_req->task->rxwr_txrd.var_ctx.rx_id);
649 srr.srr_rel_off = htonl(offset);
650 srr.srr_r_ctl = r_ctl;
651 orig_io_req->srr_offset = offset;
652 orig_io_req->srr_rctl = r_ctl;
653
654 rc = bnx2fc_initiate_els(tgt, ELS_SRR, &srr, sizeof(srr),
655 bnx2fc_srr_compl, cb_arg,
656 r_a_tov);
657srr_err:
658 if (rc) {
659 BNX2FC_IO_DBG(orig_io_req, "SRR failed - release\n");
660 spin_lock_bh(&tgt->tgt_lock);
661 kref_put(&orig_io_req->refcount, bnx2fc_cmd_release);
662 spin_unlock_bh(&tgt->tgt_lock);
663 kfree(cb_arg);
664 } else
665 set_bit(BNX2FC_FLAG_SRR_SENT, &orig_io_req->req_flags);
666
667 return rc;
Bhanu Prakash Gollapudi6c5a7ce2011-07-27 11:32:05 -0700668}
669
Bhanu Gollapudi853e2bd2011-02-04 12:10:34 -0800670static int bnx2fc_initiate_els(struct bnx2fc_rport *tgt, unsigned int op,
671 void *data, u32 data_len,
672 void (*cb_func)(struct bnx2fc_els_cb_arg *cb_arg),
673 struct bnx2fc_els_cb_arg *cb_arg, u32 timer_msec)
674{
675 struct fcoe_port *port = tgt->port;
Bhanu Prakash Gollapudiaea71a02011-07-26 14:51:39 -0700676 struct bnx2fc_interface *interface = port->priv;
Bhanu Gollapudi853e2bd2011-02-04 12:10:34 -0800677 struct fc_rport *rport = tgt->rport;
678 struct fc_lport *lport = port->lport;
679 struct bnx2fc_cmd *els_req;
680 struct bnx2fc_mp_req *mp_req;
681 struct fc_frame_header *fc_hdr;
682 struct fcoe_task_ctx_entry *task;
683 struct fcoe_task_ctx_entry *task_page;
684 int rc = 0;
685 int task_idx, index;
686 u32 did, sid;
687 u16 xid;
688
689 rc = fc_remote_port_chkready(rport);
690 if (rc) {
Bhanu Prakash Gollapudib2a554f2011-06-27 23:30:53 -0700691 printk(KERN_ERR PFX "els 0x%x: rport not ready\n", op);
Bhanu Gollapudi853e2bd2011-02-04 12:10:34 -0800692 rc = -EINVAL;
693 goto els_err;
694 }
695 if (lport->state != LPORT_ST_READY || !(lport->link_up)) {
Bhanu Prakash Gollapudib2a554f2011-06-27 23:30:53 -0700696 printk(KERN_ERR PFX "els 0x%x: link is not ready\n", op);
Bhanu Gollapudi853e2bd2011-02-04 12:10:34 -0800697 rc = -EINVAL;
698 goto els_err;
699 }
Chad Dupuis50a874142015-10-19 15:40:39 -0400700 if (!(test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags))) {
Bhanu Gollapudi853e2bd2011-02-04 12:10:34 -0800701 printk(KERN_ERR PFX "els 0x%x: tgt not ready\n", op);
702 rc = -EINVAL;
703 goto els_err;
704 }
705 els_req = bnx2fc_elstm_alloc(tgt, BNX2FC_ELS);
706 if (!els_req) {
707 rc = -ENOMEM;
708 goto els_err;
709 }
710
711 els_req->sc_cmd = NULL;
712 els_req->port = port;
713 els_req->tgt = tgt;
714 els_req->cb_func = cb_func;
715 cb_arg->io_req = els_req;
716 els_req->cb_arg = cb_arg;
Chad Dupuis1fffa192015-10-19 15:40:37 -0400717 els_req->data_xfer_len = data_len;
Bhanu Gollapudi853e2bd2011-02-04 12:10:34 -0800718
719 mp_req = (struct bnx2fc_mp_req *)&(els_req->mp_req);
720 rc = bnx2fc_init_mp_req(els_req);
721 if (rc == FAILED) {
Bhanu Prakash Gollapudib2a554f2011-06-27 23:30:53 -0700722 printk(KERN_ERR PFX "ELS MP request init failed\n");
Bhanu Gollapudi853e2bd2011-02-04 12:10:34 -0800723 spin_lock_bh(&tgt->tgt_lock);
724 kref_put(&els_req->refcount, bnx2fc_cmd_release);
725 spin_unlock_bh(&tgt->tgt_lock);
726 rc = -ENOMEM;
727 goto els_err;
728 } else {
729 /* rc SUCCESS */
730 rc = 0;
731 }
732
733 /* Set the data_xfer_len to the size of ELS payload */
734 mp_req->req_len = data_len;
735 els_req->data_xfer_len = mp_req->req_len;
736
737 /* Fill ELS Payload */
738 if ((op >= ELS_LS_RJT) && (op <= ELS_AUTH_ELS)) {
739 memcpy(mp_req->req_buf, data, data_len);
740 } else {
Bhanu Prakash Gollapudib2a554f2011-06-27 23:30:53 -0700741 printk(KERN_ERR PFX "Invalid ELS op 0x%x\n", op);
Bhanu Gollapudi853e2bd2011-02-04 12:10:34 -0800742 els_req->cb_func = NULL;
743 els_req->cb_arg = NULL;
744 spin_lock_bh(&tgt->tgt_lock);
745 kref_put(&els_req->refcount, bnx2fc_cmd_release);
746 spin_unlock_bh(&tgt->tgt_lock);
747 rc = -EINVAL;
748 }
749
750 if (rc)
751 goto els_err;
752
753 /* Fill FC header */
754 fc_hdr = &(mp_req->req_fc_hdr);
755
756 did = tgt->rport->port_id;
757 sid = tgt->sid;
758
Bhanu Prakash Gollapudi74446952011-07-27 11:32:06 -0700759 if (op == ELS_SRR)
760 __fc_fill_fc_hdr(fc_hdr, FC_RCTL_ELS4_REQ, did, sid,
761 FC_TYPE_FCP, FC_FC_FIRST_SEQ |
762 FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
763 else
764 __fc_fill_fc_hdr(fc_hdr, FC_RCTL_ELS_REQ, did, sid,
765 FC_TYPE_ELS, FC_FC_FIRST_SEQ |
766 FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
Bhanu Gollapudi853e2bd2011-02-04 12:10:34 -0800767
768 /* Obtain exchange id */
769 xid = els_req->xid;
770 task_idx = xid/BNX2FC_TASKS_PER_PAGE;
771 index = xid % BNX2FC_TASKS_PER_PAGE;
772
773 /* Initialize task context for this IO request */
Bhanu Prakash Gollapudiaea71a02011-07-26 14:51:39 -0700774 task_page = (struct fcoe_task_ctx_entry *)
775 interface->hba->task_ctx[task_idx];
Bhanu Gollapudi853e2bd2011-02-04 12:10:34 -0800776 task = &(task_page[index]);
777 bnx2fc_init_mp_task(els_req, task);
778
779 spin_lock_bh(&tgt->tgt_lock);
780
781 if (!test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags)) {
782 printk(KERN_ERR PFX "initiate_els.. session not ready\n");
783 els_req->cb_func = NULL;
784 els_req->cb_arg = NULL;
785 kref_put(&els_req->refcount, bnx2fc_cmd_release);
786 spin_unlock_bh(&tgt->tgt_lock);
787 return -EINVAL;
788 }
789
790 if (timer_msec)
791 bnx2fc_cmd_timer_set(els_req, timer_msec);
792 bnx2fc_add_2_sq(tgt, xid);
793
794 els_req->on_active_queue = 1;
795 list_add_tail(&els_req->link, &tgt->els_queue);
796
797 /* Ring doorbell */
798 bnx2fc_ring_doorbell(tgt);
799 spin_unlock_bh(&tgt->tgt_lock);
800
801els_err:
802 return rc;
803}
804
805void bnx2fc_process_els_compl(struct bnx2fc_cmd *els_req,
806 struct fcoe_task_ctx_entry *task, u8 num_rq)
807{
808 struct bnx2fc_mp_req *mp_req;
809 struct fc_frame_header *fc_hdr;
810 u64 *hdr;
811 u64 *temp_hdr;
812
813 BNX2FC_ELS_DBG("Entered process_els_compl xid = 0x%x"
814 "cmd_type = %d\n", els_req->xid, els_req->cmd_type);
815
816 if (test_and_set_bit(BNX2FC_FLAG_ELS_DONE,
817 &els_req->req_flags)) {
818 BNX2FC_ELS_DBG("Timer context finished processing this "
819 "els - 0x%x\n", els_req->xid);
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300820 /* This IO doesn't receive cleanup completion */
Bhanu Gollapudi853e2bd2011-02-04 12:10:34 -0800821 kref_put(&els_req->refcount, bnx2fc_cmd_release);
822 return;
823 }
824
825 /* Cancel the timeout_work, as we received the response */
826 if (cancel_delayed_work(&els_req->timeout_work))
827 kref_put(&els_req->refcount,
828 bnx2fc_cmd_release); /* drop timer hold */
829
830 if (els_req->on_active_queue) {
831 list_del_init(&els_req->link);
832 els_req->on_active_queue = 0;
833 }
834
835 mp_req = &(els_req->mp_req);
836 fc_hdr = &(mp_req->resp_fc_hdr);
837
838 hdr = (u64 *)fc_hdr;
839 temp_hdr = (u64 *)
Vlad Zolotarov619c5cb2011-06-14 14:33:44 +0300840 &task->rxwr_only.union_ctx.comp_info.mp_rsp.fc_hdr;
Bhanu Gollapudi853e2bd2011-02-04 12:10:34 -0800841 hdr[0] = cpu_to_be64(temp_hdr[0]);
842 hdr[1] = cpu_to_be64(temp_hdr[1]);
843 hdr[2] = cpu_to_be64(temp_hdr[2]);
844
Vlad Zolotarov619c5cb2011-06-14 14:33:44 +0300845 mp_req->resp_len =
846 task->rxwr_only.union_ctx.comp_info.mp_rsp.mp_payload_len;
Bhanu Gollapudi853e2bd2011-02-04 12:10:34 -0800847
848 /* Parse ELS response */
849 if ((els_req->cb_func) && (els_req->cb_arg)) {
850 els_req->cb_func(els_req->cb_arg);
851 els_req->cb_arg = NULL;
852 }
853
854 kref_put(&els_req->refcount, bnx2fc_cmd_release);
855}
856
857static void bnx2fc_flogi_resp(struct fc_seq *seq, struct fc_frame *fp,
858 void *arg)
859{
860 struct fcoe_ctlr *fip = arg;
861 struct fc_exch *exch = fc_seq_exch(seq);
862 struct fc_lport *lport = exch->lp;
863 u8 *mac;
Bhanu Gollapudi853e2bd2011-02-04 12:10:34 -0800864 u8 op;
865
866 if (IS_ERR(fp))
867 goto done;
868
869 mac = fr_cb(fp)->granted_mac;
870 if (is_zero_ether_addr(mac)) {
Bhanu Gollapudi853e2bd2011-02-04 12:10:34 -0800871 op = fc_frame_payload_op(fp);
872 if (lport->vport) {
873 if (op == ELS_LS_RJT) {
874 printk(KERN_ERR PFX "bnx2fc_flogi_resp is LS_RJT\n");
875 fc_vport_terminate(lport->vport);
876 fc_frame_free(fp);
877 return;
878 }
879 }
Bhanu Prakash Gollapudide9c05f2012-04-24 15:26:01 -0700880 fcoe_ctlr_recv_flogi(fip, lport, fp);
Bhanu Gollapudi853e2bd2011-02-04 12:10:34 -0800881 }
Bhanu Prakash Gollapudide9c05f2012-04-24 15:26:01 -0700882 if (!is_zero_ether_addr(mac))
883 fip->update_mac(lport, mac);
Bhanu Gollapudi853e2bd2011-02-04 12:10:34 -0800884done:
885 fc_lport_flogi_resp(seq, fp, lport);
886}
887
888static void bnx2fc_logo_resp(struct fc_seq *seq, struct fc_frame *fp,
889 void *arg)
890{
891 struct fcoe_ctlr *fip = arg;
892 struct fc_exch *exch = fc_seq_exch(seq);
893 struct fc_lport *lport = exch->lp;
894 static u8 zero_mac[ETH_ALEN] = { 0 };
895
896 if (!IS_ERR(fp))
897 fip->update_mac(lport, zero_mac);
898 fc_lport_logo_resp(seq, fp, lport);
899}
900
901struct fc_seq *bnx2fc_elsct_send(struct fc_lport *lport, u32 did,
902 struct fc_frame *fp, unsigned int op,
903 void (*resp)(struct fc_seq *,
904 struct fc_frame *,
905 void *),
906 void *arg, u32 timeout)
907{
908 struct fcoe_port *port = lport_priv(lport);
Bhanu Prakash Gollapudiaea71a02011-07-26 14:51:39 -0700909 struct bnx2fc_interface *interface = port->priv;
Robert Lovefd8f8902012-05-22 19:06:16 -0700910 struct fcoe_ctlr *fip = bnx2fc_to_ctlr(interface);
Bhanu Gollapudi853e2bd2011-02-04 12:10:34 -0800911 struct fc_frame_header *fh = fc_frame_header_get(fp);
912
913 switch (op) {
914 case ELS_FLOGI:
915 case ELS_FDISC:
916 return fc_elsct_send(lport, did, fp, op, bnx2fc_flogi_resp,
917 fip, timeout);
918 case ELS_LOGO:
919 /* only hook onto fabric logouts, not port logouts */
920 if (ntoh24(fh->fh_d_id) != FC_FID_FLOGI)
921 break;
922 return fc_elsct_send(lport, did, fp, op, bnx2fc_logo_resp,
923 fip, timeout);
924 }
925 return fc_elsct_send(lport, did, fp, op, resp, arg, timeout);
926}