aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/fcoe/fcoe.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/fcoe/fcoe.c')
-rw-r--r--drivers/scsi/fcoe/fcoe.c67
1 files changed, 65 insertions, 2 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 86410b9a30c3..0306aa95eb34 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -415,6 +415,17 @@ static int fcoe_shost_config(struct fc_lport *lp, struct Scsi_Host *shost,
415 return 0; 415 return 0;
416} 416}
417 417
418/*
419 * fcoe_oem_match() - match for read types IO
420 * @fp: the fc_frame for new IO.
421 *
422 * Returns : true for read types IO, otherwise returns false.
423 */
424bool fcoe_oem_match(struct fc_frame *fp)
425{
426 return fc_fcp_is_read(fr_fsp(fp));
427}
428
418/** 429/**
419 * fcoe_em_config() - allocates em for this lport 430 * fcoe_em_config() - allocates em for this lport
420 * @lp: the port that em is to allocated for 431 * @lp: the port that em is to allocated for
@@ -425,9 +436,61 @@ static int fcoe_shost_config(struct fc_lport *lp, struct Scsi_Host *shost,
425 */ 436 */
426static inline int fcoe_em_config(struct fc_lport *lp) 437static inline int fcoe_em_config(struct fc_lport *lp)
427{ 438{
428 if (!fc_exch_mgr_alloc(lp, FC_CLASS_3, FCOE_MIN_XID, 439 struct fcoe_softc *fc = lport_priv(lp);
429 FCOE_MAX_XID, NULL)) 440 struct fcoe_softc *oldfc = NULL;
441 u16 min_xid = FCOE_MIN_XID;
442 u16 max_xid = FCOE_MAX_XID;
443
444 /*
445 * Check if need to allocate an em instance for
446 * offload exchange ids to be shared across all VN_PORTs/lport.
447 */
448 if (!lp->lro_enabled || !lp->lro_xid || (lp->lro_xid >= max_xid)) {
449 lp->lro_xid = 0;
450 goto skip_oem;
451 }
452
453 /*
454 * Reuse existing offload em instance in case
455 * it is already allocated on phys_dev.
456 */
457 list_for_each_entry(oldfc, &fcoe_hostlist, list) {
458 if (oldfc->phys_dev == fc->phys_dev) {
459 fc->oem = oldfc->oem;
460 break;
461 }
462 }
463
464 if (fc->oem) {
465 if (!fc_exch_mgr_add(lp, fc->oem, fcoe_oem_match)) {
466 printk(KERN_ERR "fcoe_em_config: failed to add "
467 "offload em:%p on interface:%s\n",
468 fc->oem, fc->real_dev->name);
469 return -ENOMEM;
470 }
471 } else {
472 fc->oem = fc_exch_mgr_alloc(lp, FC_CLASS_3,
473 FCOE_MIN_XID, lp->lro_xid,
474 fcoe_oem_match);
475 if (!fc->oem) {
476 printk(KERN_ERR "fcoe_em_config: failed to allocate "
477 "em for offload exches on interface:%s\n",
478 fc->real_dev->name);
479 return -ENOMEM;
480 }
481 }
482
483 /*
484 * Exclude offload EM xid range from next EM xid range.
485 */
486 min_xid += lp->lro_xid + 1;
487
488skip_oem:
489 if (!fc_exch_mgr_alloc(lp, FC_CLASS_3, min_xid, max_xid, NULL)) {
490 printk(KERN_ERR "fcoe_em_config: failed to "
491 "allocate em on interface %s\n", fc->real_dev->name);
430 return -ENOMEM; 492 return -ENOMEM;
493 }
431 494
432 return 0; 495 return 0;
433} 496}