diff options
author | Bhanu Prakash Gollapudi <bprakash@broadcom.com> | 2011-07-27 14:32:06 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2011-07-28 03:45:19 -0400 |
commit | 744469542951d32979a8dcb1dbed560bfed1745e (patch) | |
tree | d6be8757d3804b19fcc7cd498e215d8a232d2904 | |
parent | 6c5a7ce4f176b641fd11e59be4df31ee3e6202dd (diff) |
[SCSI] bnx2fc: REC/SRR link service request and response handling
Signed-off-by: Bhanu Prakash Gollapudi <bprakash@broadcom.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r-- | drivers/scsi/bnx2fc/bnx2fc.h | 12 | ||||
-rw-r--r-- | drivers/scsi/bnx2fc/bnx2fc_els.c | 417 | ||||
-rw-r--r-- | drivers/scsi/bnx2fc/bnx2fc_io.c | 9 |
3 files changed, 421 insertions, 17 deletions
diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h index 45d5391229e2..cd506c0ee2f6 100644 --- a/drivers/scsi/bnx2fc/bnx2fc.h +++ b/drivers/scsi/bnx2fc/bnx2fc.h | |||
@@ -141,6 +141,9 @@ | |||
141 | 141 | ||
142 | #define BNX2FC_RNID_HBA 0x7 | 142 | #define BNX2FC_RNID_HBA 0x7 |
143 | 143 | ||
144 | #define SRR_RETRY_COUNT 5 | ||
145 | #define REC_RETRY_COUNT 1 | ||
146 | |||
144 | /* bnx2fc driver uses only one instance of fcoe_percpu_s */ | 147 | /* bnx2fc driver uses only one instance of fcoe_percpu_s */ |
145 | extern struct fcoe_percpu_s bnx2fc_global; | 148 | extern struct fcoe_percpu_s bnx2fc_global; |
146 | 149 | ||
@@ -386,6 +389,7 @@ struct bnx2fc_cmd { | |||
386 | struct completion tm_done; | 389 | struct completion tm_done; |
387 | int wait_for_comp; | 390 | int wait_for_comp; |
388 | u16 xid; | 391 | u16 xid; |
392 | struct fcoe_err_report_entry err_entry; | ||
389 | struct fcoe_task_ctx_entry *task; | 393 | struct fcoe_task_ctx_entry *task; |
390 | struct io_bdt *bd_tbl; | 394 | struct io_bdt *bd_tbl; |
391 | struct fcp_rsp *rsp; | 395 | struct fcp_rsp *rsp; |
@@ -402,6 +406,12 @@ struct bnx2fc_cmd { | |||
402 | #define BNX2FC_FLAG_IO_COMPL 0x9 | 406 | #define BNX2FC_FLAG_IO_COMPL 0x9 |
403 | #define BNX2FC_FLAG_ELS_DONE 0xa | 407 | #define BNX2FC_FLAG_ELS_DONE 0xa |
404 | #define BNX2FC_FLAG_ELS_TIMEOUT 0xb | 408 | #define BNX2FC_FLAG_ELS_TIMEOUT 0xb |
409 | #define BNX2FC_FLAG_CMD_LOST 0xc | ||
410 | #define BNX2FC_FLAG_SRR_SENT 0xd | ||
411 | u8 rec_retry; | ||
412 | u8 srr_retry; | ||
413 | u32 srr_offset; | ||
414 | u8 srr_rctl; | ||
405 | u32 fcp_resid; | 415 | u32 fcp_resid; |
406 | u32 fcp_rsp_len; | 416 | u32 fcp_rsp_len; |
407 | u32 fcp_sns_len; | 417 | u32 fcp_sns_len; |
@@ -432,6 +442,7 @@ struct bnx2fc_unsol_els { | |||
432 | 442 | ||
433 | 443 | ||
434 | 444 | ||
445 | struct bnx2fc_cmd *bnx2fc_cmd_alloc(struct bnx2fc_rport *tgt); | ||
435 | struct bnx2fc_cmd *bnx2fc_elstm_alloc(struct bnx2fc_rport *tgt, int type); | 446 | struct bnx2fc_cmd *bnx2fc_elstm_alloc(struct bnx2fc_rport *tgt, int type); |
436 | void bnx2fc_cmd_release(struct kref *ref); | 447 | void bnx2fc_cmd_release(struct kref *ref); |
437 | int bnx2fc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc_cmd); | 448 | int bnx2fc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc_cmd); |
@@ -522,6 +533,7 @@ void bnx2fc_process_l2_frame_compl(struct bnx2fc_rport *tgt, | |||
522 | unsigned char *buf, | 533 | unsigned char *buf, |
523 | u32 frame_len, u16 l2_oxid); | 534 | u32 frame_len, u16 l2_oxid); |
524 | int bnx2fc_send_stat_req(struct bnx2fc_hba *hba); | 535 | int bnx2fc_send_stat_req(struct bnx2fc_hba *hba); |
536 | int bnx2fc_post_io_req(struct bnx2fc_rport *tgt, struct bnx2fc_cmd *io_req); | ||
525 | int bnx2fc_send_rec(struct bnx2fc_cmd *orig_io_req); | 537 | int bnx2fc_send_rec(struct bnx2fc_cmd *orig_io_req); |
526 | int bnx2fc_send_srr(struct bnx2fc_cmd *orig_io_req, u32 offset, u8 r_ctl); | 538 | int bnx2fc_send_srr(struct bnx2fc_cmd *orig_io_req, u32 offset, u8 r_ctl); |
527 | void bnx2fc_process_seq_cleanup_compl(struct bnx2fc_cmd *seq_clnup_req, | 539 | void bnx2fc_process_seq_cleanup_compl(struct bnx2fc_cmd *seq_clnup_req, |
diff --git a/drivers/scsi/bnx2fc/bnx2fc_els.c b/drivers/scsi/bnx2fc/bnx2fc_els.c index 75d0b6ac6c2b..296c6aa62ac2 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_els.c +++ b/drivers/scsi/bnx2fc/bnx2fc_els.c | |||
@@ -253,25 +253,409 @@ int bnx2fc_send_rls(struct bnx2fc_rport *tgt, struct fc_frame *fp) | |||
253 | return rc; | 253 | return rc; |
254 | } | 254 | } |
255 | 255 | ||
256 | void bnx2fc_srr_compl(struct bnx2fc_els_cb_arg *cb_arg) | ||
257 | { | ||
258 | struct bnx2fc_mp_req *mp_req; | ||
259 | struct fc_frame_header *fc_hdr, *fh; | ||
260 | struct bnx2fc_cmd *srr_req; | ||
261 | struct bnx2fc_cmd *orig_io_req; | ||
262 | struct fc_frame *fp; | ||
263 | unsigned char *buf; | ||
264 | void *resp_buf; | ||
265 | u32 resp_len, hdr_len; | ||
266 | u8 opcode; | ||
267 | int rc = 0; | ||
268 | |||
269 | orig_io_req = cb_arg->aborted_io_req; | ||
270 | srr_req = cb_arg->io_req; | ||
271 | if (test_bit(BNX2FC_FLAG_IO_COMPL, &orig_io_req->req_flags)) { | ||
272 | BNX2FC_IO_DBG(srr_req, "srr_compl: xid - 0x%x completed", | ||
273 | orig_io_req->xid); | ||
274 | goto srr_compl_done; | ||
275 | } | ||
276 | if (test_bit(BNX2FC_FLAG_ISSUE_ABTS, &orig_io_req->req_flags)) { | ||
277 | BNX2FC_IO_DBG(srr_req, "rec abts in prog " | ||
278 | "orig_io - 0x%x\n", | ||
279 | orig_io_req->xid); | ||
280 | goto srr_compl_done; | ||
281 | } | ||
282 | if (test_and_clear_bit(BNX2FC_FLAG_ELS_TIMEOUT, &srr_req->req_flags)) { | ||
283 | /* SRR timedout */ | ||
284 | BNX2FC_IO_DBG(srr_req, "srr timed out, abort " | ||
285 | "orig_io - 0x%x\n", | ||
286 | orig_io_req->xid); | ||
287 | rc = bnx2fc_initiate_abts(srr_req); | ||
288 | if (rc != SUCCESS) { | ||
289 | BNX2FC_IO_DBG(srr_req, "srr_compl: initiate_abts " | ||
290 | "failed. issue cleanup\n"); | ||
291 | bnx2fc_initiate_cleanup(srr_req); | ||
292 | } | ||
293 | orig_io_req->srr_retry++; | ||
294 | if (orig_io_req->srr_retry <= SRR_RETRY_COUNT) { | ||
295 | struct bnx2fc_rport *tgt = orig_io_req->tgt; | ||
296 | spin_unlock_bh(&tgt->tgt_lock); | ||
297 | rc = bnx2fc_send_srr(orig_io_req, | ||
298 | orig_io_req->srr_offset, | ||
299 | orig_io_req->srr_rctl); | ||
300 | spin_lock_bh(&tgt->tgt_lock); | ||
301 | if (!rc) | ||
302 | goto srr_compl_done; | ||
303 | } | ||
304 | |||
305 | rc = bnx2fc_initiate_abts(orig_io_req); | ||
306 | if (rc != SUCCESS) { | ||
307 | BNX2FC_IO_DBG(srr_req, "srr_compl: initiate_abts " | ||
308 | "failed xid = 0x%x. issue cleanup\n", | ||
309 | orig_io_req->xid); | ||
310 | bnx2fc_initiate_cleanup(orig_io_req); | ||
311 | } | ||
312 | goto srr_compl_done; | ||
313 | } | ||
314 | mp_req = &(srr_req->mp_req); | ||
315 | fc_hdr = &(mp_req->resp_fc_hdr); | ||
316 | resp_len = mp_req->resp_len; | ||
317 | resp_buf = mp_req->resp_buf; | ||
318 | |||
319 | hdr_len = sizeof(*fc_hdr); | ||
320 | buf = kzalloc(PAGE_SIZE, GFP_ATOMIC); | ||
321 | if (!buf) { | ||
322 | printk(KERN_ERR PFX "srr buf: mem alloc failure\n"); | ||
323 | goto srr_compl_done; | ||
324 | } | ||
325 | memcpy(buf, fc_hdr, hdr_len); | ||
326 | memcpy(buf + hdr_len, resp_buf, resp_len); | ||
327 | |||
328 | fp = fc_frame_alloc(NULL, resp_len); | ||
329 | if (!fp) { | ||
330 | printk(KERN_ERR PFX "fc_frame_alloc failure\n"); | ||
331 | goto free_buf; | ||
332 | } | ||
333 | |||
334 | fh = (struct fc_frame_header *) fc_frame_header_get(fp); | ||
335 | /* Copy FC Frame header and payload into the frame */ | ||
336 | memcpy(fh, buf, hdr_len + resp_len); | ||
337 | |||
338 | opcode = fc_frame_payload_op(fp); | ||
339 | switch (opcode) { | ||
340 | case ELS_LS_ACC: | ||
341 | BNX2FC_IO_DBG(srr_req, "SRR success\n"); | ||
342 | break; | ||
343 | case ELS_LS_RJT: | ||
344 | BNX2FC_IO_DBG(srr_req, "SRR rejected\n"); | ||
345 | rc = bnx2fc_initiate_abts(orig_io_req); | ||
346 | if (rc != SUCCESS) { | ||
347 | BNX2FC_IO_DBG(srr_req, "srr_compl: initiate_abts " | ||
348 | "failed xid = 0x%x. issue cleanup\n", | ||
349 | orig_io_req->xid); | ||
350 | bnx2fc_initiate_cleanup(orig_io_req); | ||
351 | } | ||
352 | break; | ||
353 | default: | ||
354 | BNX2FC_IO_DBG(srr_req, "srr compl - invalid opcode = %d\n", | ||
355 | opcode); | ||
356 | break; | ||
357 | } | ||
358 | fc_frame_free(fp); | ||
359 | free_buf: | ||
360 | kfree(buf); | ||
361 | srr_compl_done: | ||
362 | kref_put(&orig_io_req->refcount, bnx2fc_cmd_release); | ||
363 | } | ||
364 | |||
365 | void bnx2fc_rec_compl(struct bnx2fc_els_cb_arg *cb_arg) | ||
366 | { | ||
367 | struct bnx2fc_cmd *orig_io_req, *new_io_req; | ||
368 | struct bnx2fc_cmd *rec_req; | ||
369 | struct bnx2fc_mp_req *mp_req; | ||
370 | struct fc_frame_header *fc_hdr, *fh; | ||
371 | struct fc_els_ls_rjt *rjt; | ||
372 | struct fc_els_rec_acc *acc; | ||
373 | struct bnx2fc_rport *tgt; | ||
374 | struct fcoe_err_report_entry *err_entry; | ||
375 | struct scsi_cmnd *sc_cmd; | ||
376 | enum fc_rctl r_ctl; | ||
377 | unsigned char *buf; | ||
378 | void *resp_buf; | ||
379 | struct fc_frame *fp; | ||
380 | u8 opcode; | ||
381 | u32 offset; | ||
382 | u32 e_stat; | ||
383 | u32 resp_len, hdr_len; | ||
384 | int rc = 0; | ||
385 | bool send_seq_clnp = false; | ||
386 | bool abort_io = false; | ||
387 | |||
388 | BNX2FC_MISC_DBG("Entered rec_compl callback\n"); | ||
389 | rec_req = cb_arg->io_req; | ||
390 | orig_io_req = cb_arg->aborted_io_req; | ||
391 | BNX2FC_IO_DBG(rec_req, "rec_compl: orig xid = 0x%x", orig_io_req->xid); | ||
392 | tgt = orig_io_req->tgt; | ||
393 | |||
394 | if (test_bit(BNX2FC_FLAG_IO_COMPL, &orig_io_req->req_flags)) { | ||
395 | BNX2FC_IO_DBG(rec_req, "completed" | ||
396 | "orig_io - 0x%x\n", | ||
397 | orig_io_req->xid); | ||
398 | goto rec_compl_done; | ||
399 | } | ||
400 | if (test_bit(BNX2FC_FLAG_ISSUE_ABTS, &orig_io_req->req_flags)) { | ||
401 | BNX2FC_IO_DBG(rec_req, "abts in prog " | ||
402 | "orig_io - 0x%x\n", | ||
403 | orig_io_req->xid); | ||
404 | goto rec_compl_done; | ||
405 | } | ||
406 | /* Handle REC timeout case */ | ||
407 | if (test_and_clear_bit(BNX2FC_FLAG_ELS_TIMEOUT, &rec_req->req_flags)) { | ||
408 | BNX2FC_IO_DBG(rec_req, "timed out, abort " | ||
409 | "orig_io - 0x%x\n", | ||
410 | orig_io_req->xid); | ||
411 | /* els req is timed out. send abts for els */ | ||
412 | rc = bnx2fc_initiate_abts(rec_req); | ||
413 | if (rc != SUCCESS) { | ||
414 | BNX2FC_IO_DBG(rec_req, "rec_compl: initiate_abts " | ||
415 | "failed. issue cleanup\n"); | ||
416 | bnx2fc_initiate_cleanup(rec_req); | ||
417 | } | ||
418 | orig_io_req->rec_retry++; | ||
419 | /* REC timedout. send ABTS to the orig IO req */ | ||
420 | if (orig_io_req->rec_retry <= REC_RETRY_COUNT) { | ||
421 | spin_unlock_bh(&tgt->tgt_lock); | ||
422 | rc = bnx2fc_send_rec(orig_io_req); | ||
423 | spin_lock_bh(&tgt->tgt_lock); | ||
424 | if (!rc) | ||
425 | goto rec_compl_done; | ||
426 | } | ||
427 | rc = bnx2fc_initiate_abts(orig_io_req); | ||
428 | if (rc != SUCCESS) { | ||
429 | BNX2FC_IO_DBG(rec_req, "rec_compl: initiate_abts " | ||
430 | "failed xid = 0x%x. issue cleanup\n", | ||
431 | orig_io_req->xid); | ||
432 | bnx2fc_initiate_cleanup(orig_io_req); | ||
433 | } | ||
434 | goto rec_compl_done; | ||
435 | } | ||
436 | mp_req = &(rec_req->mp_req); | ||
437 | fc_hdr = &(mp_req->resp_fc_hdr); | ||
438 | resp_len = mp_req->resp_len; | ||
439 | acc = resp_buf = mp_req->resp_buf; | ||
440 | |||
441 | hdr_len = sizeof(*fc_hdr); | ||
442 | |||
443 | buf = kzalloc(PAGE_SIZE, GFP_ATOMIC); | ||
444 | if (!buf) { | ||
445 | printk(KERN_ERR PFX "rec buf: mem alloc failure\n"); | ||
446 | goto rec_compl_done; | ||
447 | } | ||
448 | memcpy(buf, fc_hdr, hdr_len); | ||
449 | memcpy(buf + hdr_len, resp_buf, resp_len); | ||
450 | |||
451 | fp = fc_frame_alloc(NULL, resp_len); | ||
452 | if (!fp) { | ||
453 | printk(KERN_ERR PFX "fc_frame_alloc failure\n"); | ||
454 | goto free_buf; | ||
455 | } | ||
456 | |||
457 | fh = (struct fc_frame_header *) fc_frame_header_get(fp); | ||
458 | /* Copy FC Frame header and payload into the frame */ | ||
459 | memcpy(fh, buf, hdr_len + resp_len); | ||
460 | |||
461 | opcode = fc_frame_payload_op(fp); | ||
462 | if (opcode == ELS_LS_RJT) { | ||
463 | BNX2FC_IO_DBG(rec_req, "opcode is RJT\n"); | ||
464 | rjt = fc_frame_payload_get(fp, sizeof(*rjt)); | ||
465 | if ((rjt->er_reason == ELS_RJT_LOGIC || | ||
466 | rjt->er_reason == ELS_RJT_UNAB) && | ||
467 | rjt->er_explan == ELS_EXPL_OXID_RXID) { | ||
468 | BNX2FC_IO_DBG(rec_req, "handle CMD LOST case\n"); | ||
469 | new_io_req = bnx2fc_cmd_alloc(tgt); | ||
470 | if (!new_io_req) | ||
471 | goto abort_io; | ||
472 | new_io_req->sc_cmd = orig_io_req->sc_cmd; | ||
473 | /* cleanup orig_io_req that is with the FW */ | ||
474 | set_bit(BNX2FC_FLAG_CMD_LOST, | ||
475 | &orig_io_req->req_flags); | ||
476 | bnx2fc_initiate_cleanup(orig_io_req); | ||
477 | /* Post a new IO req with the same sc_cmd */ | ||
478 | BNX2FC_IO_DBG(rec_req, "Post IO request again\n"); | ||
479 | spin_unlock_bh(&tgt->tgt_lock); | ||
480 | rc = bnx2fc_post_io_req(tgt, new_io_req); | ||
481 | spin_lock_bh(&tgt->tgt_lock); | ||
482 | if (!rc) | ||
483 | goto free_frame; | ||
484 | BNX2FC_IO_DBG(rec_req, "REC: io post err\n"); | ||
485 | } | ||
486 | abort_io: | ||
487 | rc = bnx2fc_initiate_abts(orig_io_req); | ||
488 | if (rc != SUCCESS) { | ||
489 | BNX2FC_IO_DBG(rec_req, "rec_compl: initiate_abts " | ||
490 | "failed. issue cleanup\n"); | ||
491 | bnx2fc_initiate_cleanup(orig_io_req); | ||
492 | } | ||
493 | } else if (opcode == ELS_LS_ACC) { | ||
494 | /* REVISIT: Check if the exchange is already aborted */ | ||
495 | offset = ntohl(acc->reca_fc4value); | ||
496 | e_stat = ntohl(acc->reca_e_stat); | ||
497 | if (e_stat & ESB_ST_SEQ_INIT) { | ||
498 | BNX2FC_IO_DBG(rec_req, "target has the seq init\n"); | ||
499 | goto free_frame; | ||
500 | } | ||
501 | BNX2FC_IO_DBG(rec_req, "e_stat = 0x%x, offset = 0x%x\n", | ||
502 | e_stat, offset); | ||
503 | /* Seq initiative is with us */ | ||
504 | err_entry = (struct fcoe_err_report_entry *) | ||
505 | &orig_io_req->err_entry; | ||
506 | sc_cmd = orig_io_req->sc_cmd; | ||
507 | if (sc_cmd->sc_data_direction == DMA_TO_DEVICE) { | ||
508 | /* SCSI WRITE command */ | ||
509 | if (offset == orig_io_req->data_xfer_len) { | ||
510 | BNX2FC_IO_DBG(rec_req, "WRITE - resp lost\n"); | ||
511 | /* FCP_RSP lost */ | ||
512 | r_ctl = FC_RCTL_DD_CMD_STATUS; | ||
513 | offset = 0; | ||
514 | } else { | ||
515 | /* start transmitting from offset */ | ||
516 | BNX2FC_IO_DBG(rec_req, "XFER_RDY/DATA lost\n"); | ||
517 | send_seq_clnp = true; | ||
518 | r_ctl = FC_RCTL_DD_DATA_DESC; | ||
519 | if (bnx2fc_initiate_seq_cleanup(orig_io_req, | ||
520 | offset, r_ctl)) | ||
521 | abort_io = true; | ||
522 | /* XFER_RDY */ | ||
523 | } | ||
524 | } else { | ||
525 | /* SCSI READ command */ | ||
526 | if (err_entry->data.rx_buf_off == | ||
527 | orig_io_req->data_xfer_len) { | ||
528 | /* FCP_RSP lost */ | ||
529 | BNX2FC_IO_DBG(rec_req, "READ - resp lost\n"); | ||
530 | r_ctl = FC_RCTL_DD_CMD_STATUS; | ||
531 | offset = 0; | ||
532 | } else { | ||
533 | /* request retransmission from this offset */ | ||
534 | send_seq_clnp = true; | ||
535 | offset = err_entry->data.rx_buf_off; | ||
536 | BNX2FC_IO_DBG(rec_req, "RD DATA lost\n"); | ||
537 | /* FCP_DATA lost */ | ||
538 | r_ctl = FC_RCTL_DD_SOL_DATA; | ||
539 | if (bnx2fc_initiate_seq_cleanup(orig_io_req, | ||
540 | offset, r_ctl)) | ||
541 | abort_io = true; | ||
542 | } | ||
543 | } | ||
544 | if (abort_io) { | ||
545 | rc = bnx2fc_initiate_abts(orig_io_req); | ||
546 | if (rc != SUCCESS) { | ||
547 | BNX2FC_IO_DBG(rec_req, "rec_compl:initiate_abts" | ||
548 | " failed. issue cleanup\n"); | ||
549 | bnx2fc_initiate_cleanup(orig_io_req); | ||
550 | } | ||
551 | } else if (!send_seq_clnp) { | ||
552 | BNX2FC_IO_DBG(rec_req, "Send SRR - FCP_RSP\n"); | ||
553 | spin_unlock_bh(&tgt->tgt_lock); | ||
554 | rc = bnx2fc_send_srr(orig_io_req, offset, r_ctl); | ||
555 | spin_lock_bh(&tgt->tgt_lock); | ||
556 | |||
557 | if (rc) { | ||
558 | BNX2FC_IO_DBG(rec_req, "Unable to send SRR" | ||
559 | " IO will abort\n"); | ||
560 | } | ||
561 | } | ||
562 | } | ||
563 | free_frame: | ||
564 | fc_frame_free(fp); | ||
565 | free_buf: | ||
566 | kfree(buf); | ||
567 | rec_compl_done: | ||
568 | kref_put(&orig_io_req->refcount, bnx2fc_cmd_release); | ||
569 | kfree(cb_arg); | ||
570 | } | ||
571 | |||
256 | int bnx2fc_send_rec(struct bnx2fc_cmd *orig_io_req) | 572 | int bnx2fc_send_rec(struct bnx2fc_cmd *orig_io_req) |
257 | { | 573 | { |
258 | /* | 574 | struct fc_els_rec rec; |
259 | * Dummy function to enable compiling individual patches. Real function | 575 | struct bnx2fc_rport *tgt = orig_io_req->tgt; |
260 | * is in the next patch. | 576 | struct fc_lport *lport = tgt->rdata->local_port; |
261 | */ | 577 | struct bnx2fc_els_cb_arg *cb_arg = NULL; |
262 | return 0; | 578 | u32 sid = tgt->sid; |
579 | u32 r_a_tov = lport->r_a_tov; | ||
580 | int rc; | ||
581 | |||
582 | BNX2FC_IO_DBG(orig_io_req, "Sending REC\n"); | ||
583 | memset(&rec, 0, sizeof(rec)); | ||
584 | |||
585 | cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_ATOMIC); | ||
586 | if (!cb_arg) { | ||
587 | printk(KERN_ERR PFX "Unable to allocate cb_arg for REC\n"); | ||
588 | rc = -ENOMEM; | ||
589 | goto rec_err; | ||
590 | } | ||
591 | kref_get(&orig_io_req->refcount); | ||
592 | |||
593 | cb_arg->aborted_io_req = orig_io_req; | ||
594 | |||
595 | rec.rec_cmd = ELS_REC; | ||
596 | hton24(rec.rec_s_id, sid); | ||
597 | rec.rec_ox_id = htons(orig_io_req->xid); | ||
598 | rec.rec_rx_id = htons(orig_io_req->task->rxwr_txrd.var_ctx.rx_id); | ||
599 | |||
600 | rc = bnx2fc_initiate_els(tgt, ELS_REC, &rec, sizeof(rec), | ||
601 | bnx2fc_rec_compl, cb_arg, | ||
602 | r_a_tov); | ||
603 | rec_err: | ||
604 | if (rc) { | ||
605 | BNX2FC_IO_DBG(orig_io_req, "REC failed - release\n"); | ||
606 | spin_lock_bh(&tgt->tgt_lock); | ||
607 | kref_put(&orig_io_req->refcount, bnx2fc_cmd_release); | ||
608 | spin_unlock_bh(&tgt->tgt_lock); | ||
609 | kfree(cb_arg); | ||
610 | } | ||
611 | return rc; | ||
263 | } | 612 | } |
264 | 613 | ||
265 | int bnx2fc_send_srr(struct bnx2fc_cmd *orig_io_req, u32 offset, u8 r_ctl) | 614 | int bnx2fc_send_srr(struct bnx2fc_cmd *orig_io_req, u32 offset, u8 r_ctl) |
266 | { | 615 | { |
267 | /* | 616 | struct fcp_srr srr; |
268 | * Dummy function to enable compiling individual patches. Real function | 617 | struct bnx2fc_rport *tgt = orig_io_req->tgt; |
269 | * is in the next patch. | 618 | struct fc_lport *lport = tgt->rdata->local_port; |
270 | */ | 619 | struct bnx2fc_els_cb_arg *cb_arg = NULL; |
271 | return 0; | 620 | u32 r_a_tov = lport->r_a_tov; |
272 | } | 621 | int rc; |
273 | 622 | ||
623 | BNX2FC_IO_DBG(orig_io_req, "Sending SRR\n"); | ||
624 | memset(&srr, 0, sizeof(srr)); | ||
274 | 625 | ||
626 | cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_ATOMIC); | ||
627 | if (!cb_arg) { | ||
628 | printk(KERN_ERR PFX "Unable to allocate cb_arg for SRR\n"); | ||
629 | rc = -ENOMEM; | ||
630 | goto srr_err; | ||
631 | } | ||
632 | kref_get(&orig_io_req->refcount); | ||
633 | |||
634 | cb_arg->aborted_io_req = orig_io_req; | ||
635 | |||
636 | srr.srr_op = ELS_SRR; | ||
637 | srr.srr_ox_id = htons(orig_io_req->xid); | ||
638 | srr.srr_rx_id = htons(orig_io_req->task->rxwr_txrd.var_ctx.rx_id); | ||
639 | srr.srr_rel_off = htonl(offset); | ||
640 | srr.srr_r_ctl = r_ctl; | ||
641 | orig_io_req->srr_offset = offset; | ||
642 | orig_io_req->srr_rctl = r_ctl; | ||
643 | |||
644 | rc = bnx2fc_initiate_els(tgt, ELS_SRR, &srr, sizeof(srr), | ||
645 | bnx2fc_srr_compl, cb_arg, | ||
646 | r_a_tov); | ||
647 | srr_err: | ||
648 | if (rc) { | ||
649 | BNX2FC_IO_DBG(orig_io_req, "SRR failed - release\n"); | ||
650 | spin_lock_bh(&tgt->tgt_lock); | ||
651 | kref_put(&orig_io_req->refcount, bnx2fc_cmd_release); | ||
652 | spin_unlock_bh(&tgt->tgt_lock); | ||
653 | kfree(cb_arg); | ||
654 | } else | ||
655 | set_bit(BNX2FC_FLAG_SRR_SENT, &orig_io_req->req_flags); | ||
656 | |||
657 | return rc; | ||
658 | } | ||
275 | 659 | ||
276 | static int bnx2fc_initiate_els(struct bnx2fc_rport *tgt, unsigned int op, | 660 | static int bnx2fc_initiate_els(struct bnx2fc_rport *tgt, unsigned int op, |
277 | void *data, u32 data_len, | 661 | void *data, u32 data_len, |
@@ -362,9 +746,14 @@ static int bnx2fc_initiate_els(struct bnx2fc_rport *tgt, unsigned int op, | |||
362 | did = tgt->rport->port_id; | 746 | did = tgt->rport->port_id; |
363 | sid = tgt->sid; | 747 | sid = tgt->sid; |
364 | 748 | ||
365 | __fc_fill_fc_hdr(fc_hdr, FC_RCTL_ELS_REQ, did, sid, | 749 | if (op == ELS_SRR) |
366 | FC_TYPE_ELS, FC_FC_FIRST_SEQ | FC_FC_END_SEQ | | 750 | __fc_fill_fc_hdr(fc_hdr, FC_RCTL_ELS4_REQ, did, sid, |
367 | FC_FC_SEQ_INIT, 0); | 751 | FC_TYPE_FCP, FC_FC_FIRST_SEQ | |
752 | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); | ||
753 | else | ||
754 | __fc_fill_fc_hdr(fc_hdr, FC_RCTL_ELS_REQ, did, sid, | ||
755 | FC_TYPE_ELS, FC_FC_FIRST_SEQ | | ||
756 | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); | ||
368 | 757 | ||
369 | /* Obtain exchange id */ | 758 | /* Obtain exchange id */ |
370 | xid = els_req->xid; | 759 | xid = els_req->xid; |
diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c index 9820d3060cd8..797b0051b6ff 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_io.c +++ b/drivers/scsi/bnx2fc/bnx2fc_io.c | |||
@@ -18,8 +18,6 @@ static int bnx2fc_split_bd(struct bnx2fc_cmd *io_req, u64 addr, int sg_len, | |||
18 | int bd_index); | 18 | int bd_index); |
19 | static int bnx2fc_map_sg(struct bnx2fc_cmd *io_req); | 19 | static int bnx2fc_map_sg(struct bnx2fc_cmd *io_req); |
20 | static void bnx2fc_build_bd_list_from_sg(struct bnx2fc_cmd *io_req); | 20 | static void bnx2fc_build_bd_list_from_sg(struct bnx2fc_cmd *io_req); |
21 | static int bnx2fc_post_io_req(struct bnx2fc_rport *tgt, | ||
22 | struct bnx2fc_cmd *io_req); | ||
23 | static void bnx2fc_unmap_sg_list(struct bnx2fc_cmd *io_req); | 21 | static void bnx2fc_unmap_sg_list(struct bnx2fc_cmd *io_req); |
24 | static void bnx2fc_free_mp_resc(struct bnx2fc_cmd *io_req); | 22 | static void bnx2fc_free_mp_resc(struct bnx2fc_cmd *io_req); |
25 | static void bnx2fc_parse_fcp_rsp(struct bnx2fc_cmd *io_req, | 23 | static void bnx2fc_parse_fcp_rsp(struct bnx2fc_cmd *io_req, |
@@ -218,6 +216,11 @@ static void bnx2fc_scsi_done(struct bnx2fc_cmd *io_req, int err_code) | |||
218 | return; | 216 | return; |
219 | 217 | ||
220 | BNX2FC_IO_DBG(io_req, "scsi_done. err_code = 0x%x\n", err_code); | 218 | BNX2FC_IO_DBG(io_req, "scsi_done. err_code = 0x%x\n", err_code); |
219 | if (test_bit(BNX2FC_FLAG_CMD_LOST, &io_req->req_flags)) { | ||
220 | /* Do not call scsi done for this IO */ | ||
221 | return; | ||
222 | } | ||
223 | |||
221 | bnx2fc_unmap_sg_list(io_req); | 224 | bnx2fc_unmap_sg_list(io_req); |
222 | io_req->sc_cmd = NULL; | 225 | io_req->sc_cmd = NULL; |
223 | if (!sc_cmd) { | 226 | if (!sc_cmd) { |
@@ -1902,7 +1905,7 @@ void bnx2fc_process_scsi_cmd_compl(struct bnx2fc_cmd *io_req, | |||
1902 | kref_put(&io_req->refcount, bnx2fc_cmd_release); | 1905 | kref_put(&io_req->refcount, bnx2fc_cmd_release); |
1903 | } | 1906 | } |
1904 | 1907 | ||
1905 | static int bnx2fc_post_io_req(struct bnx2fc_rport *tgt, | 1908 | int bnx2fc_post_io_req(struct bnx2fc_rport *tgt, |
1906 | struct bnx2fc_cmd *io_req) | 1909 | struct bnx2fc_cmd *io_req) |
1907 | { | 1910 | { |
1908 | struct fcoe_task_ctx_entry *task; | 1911 | struct fcoe_task_ctx_entry *task; |