aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/fcoe/fcoe.c67
-rw-r--r--drivers/scsi/fcoe/fcoe.h3
-rw-r--r--drivers/scsi/libfc/fc_exch.c94
3 files changed, 85 insertions, 79 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}
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h
index 0d724fa0898f..6905efc166bf 100644
--- a/drivers/scsi/fcoe/fcoe.h
+++ b/drivers/scsi/fcoe/fcoe.h
@@ -37,7 +37,7 @@
37 37
38#define FCOE_MAX_OUTSTANDING_COMMANDS 1024 38#define FCOE_MAX_OUTSTANDING_COMMANDS 1024
39 39
40#define FCOE_MIN_XID 0x0001 /* the min xid supported by fcoe_sw */ 40#define FCOE_MIN_XID 0x0000 /* the min xid supported by fcoe_sw */
41#define FCOE_MAX_XID 0x07ef /* the max xid supported by fcoe_sw */ 41#define FCOE_MAX_XID 0x07ef /* the max xid supported by fcoe_sw */
42 42
43unsigned int fcoe_debug_logging; 43unsigned int fcoe_debug_logging;
@@ -81,6 +81,7 @@ struct fcoe_softc {
81 struct list_head list; 81 struct list_head list;
82 struct net_device *real_dev; 82 struct net_device *real_dev;
83 struct net_device *phys_dev; /* device with ethtool_ops */ 83 struct net_device *phys_dev; /* device with ethtool_ops */
84 struct fc_exch_mgr *oem; /* offload exchange manger */
84 struct packet_type fcoe_packet_type; 85 struct packet_type fcoe_packet_type;
85 struct packet_type fip_packet_type; 86 struct packet_type fip_packet_type;
86 struct sk_buff_head fcoe_pending_queue; 87 struct sk_buff_head fcoe_pending_queue;
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 324589a5cc03..11ddd115efb6 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -58,7 +58,7 @@ struct fc_exch_mgr {
58 struct kref kref; /* exchange mgr reference count */ 58 struct kref kref; /* exchange mgr reference count */
59 spinlock_t em_lock; /* exchange manager lock, 59 spinlock_t em_lock; /* exchange manager lock,
60 must be taken before ex_lock */ 60 must be taken before ex_lock */
61 u16 last_xid; /* last allocated exchange ID */ 61 u16 next_xid; /* next possible free exchange ID */
62 u16 min_xid; /* min exchange ID */ 62 u16 min_xid; /* min exchange ID */
63 u16 max_xid; /* max exchange ID */ 63 u16 max_xid; /* max exchange ID */
64 u16 max_read; /* max exchange ID for read */ 64 u16 max_read; /* max exchange ID for read */
@@ -464,68 +464,21 @@ static struct fc_seq *fc_seq_alloc(struct fc_exch *ep, u8 seq_id)
464 return sp; 464 return sp;
465} 465}
466 466
467/*
468 * fc_em_alloc_xid - returns an xid based on request type
469 * @lp : ptr to associated lport
470 * @fp : ptr to the assocated frame
471 *
472 * check the associated fc_fsp_pkt to get scsi command type and
473 * command direction to decide from which range this exch id
474 * will be allocated from.
475 *
476 * Returns : 0 or an valid xid
477 */
478static u16 fc_em_alloc_xid(struct fc_exch_mgr *mp, const struct fc_frame *fp)
479{
480 u16 xid, min, max;
481 u16 *plast;
482 struct fc_exch *ep = NULL;
483
484 if (mp->max_read) {
485 if (fc_fcp_is_read(fr_fsp(fp))) {
486 min = mp->min_xid;
487 max = mp->max_read;
488 plast = &mp->last_read;
489 } else {
490 min = mp->max_read + 1;
491 max = mp->max_xid;
492 plast = &mp->last_xid;
493 }
494 } else {
495 min = mp->min_xid;
496 max = mp->max_xid;
497 plast = &mp->last_xid;
498 }
499 xid = *plast;
500 do {
501 xid = (xid == max) ? min : xid + 1;
502 ep = mp->exches[xid - mp->min_xid];
503 } while ((ep != NULL) && (xid != *plast));
504
505 if (unlikely(ep))
506 xid = 0;
507 else
508 *plast = xid;
509
510 return xid;
511}
512
513/** 467/**
514 * fc_exch_em_alloc() - allocate an exchange from a specified EM. 468 * fc_exch_em_alloc() - allocate an exchange from a specified EM.
515 * @lport: ptr to the local port 469 * @lport: ptr to the local port
516 * @mp: ptr to the exchange manager 470 * @mp: ptr to the exchange manager
517 * @fp: ptr to the FC frame
518 * @xid: input xid
519 * 471 *
520 * if xid is supplied zero then assign next free exchange ID 472 * Returns pointer to allocated fc_exch with exch lock held.
521 * from exchange manager, otherwise use supplied xid.
522 * Returns with exch lock held.
523 */ 473 */
524static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport, 474static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport,
525 struct fc_exch_mgr *mp, 475 struct fc_exch_mgr *mp)
526 struct fc_frame *fp, u16 xid)
527{ 476{
528 struct fc_exch *ep; 477 struct fc_exch *ep;
478 u16 min, max, xid;
479
480 min = mp->min_xid;
481 max = mp->max_xid;
529 482
530 /* allocate memory for exchange */ 483 /* allocate memory for exchange */
531 ep = mempool_alloc(mp->ep_pool, GFP_ATOMIC); 484 ep = mempool_alloc(mp->ep_pool, GFP_ATOMIC);
@@ -536,15 +489,14 @@ static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport,
536 memset(ep, 0, sizeof(*ep)); 489 memset(ep, 0, sizeof(*ep));
537 490
538 spin_lock_bh(&mp->em_lock); 491 spin_lock_bh(&mp->em_lock);
539 /* alloc xid if input xid 0 */ 492 xid = mp->next_xid;
540 if (!xid) { 493 /* alloc a new xid */
541 /* alloc a new xid */ 494 while (mp->exches[xid - min]) {
542 xid = fc_em_alloc_xid(mp, fp); 495 xid = (xid == max) ? min : xid + 1;
543 if (!xid) { 496 if (xid == mp->next_xid)
544 printk(KERN_WARNING "libfc: Failed to allocate an exhange\n");
545 goto err; 497 goto err;
546 }
547 } 498 }
499 mp->next_xid = (xid == max) ? min : xid + 1;
548 500
549 fc_exch_hold(ep); /* hold for exch in mp */ 501 fc_exch_hold(ep); /* hold for exch in mp */
550 spin_lock_init(&ep->ex_lock); 502 spin_lock_init(&ep->ex_lock);
@@ -597,7 +549,7 @@ struct fc_exch *fc_exch_alloc(struct fc_lport *lport, struct fc_frame *fp)
597 549
598 list_for_each_entry(ema, &lport->ema_list, ema_list) { 550 list_for_each_entry(ema, &lport->ema_list, ema_list) {
599 if (!ema->match || ema->match(fp)) { 551 if (!ema->match || ema->match(fp)) {
600 ep = fc_exch_em_alloc(lport, ema->mp, fp, 0); 552 ep = fc_exch_em_alloc(lport, ema->mp);
601 if (ep) 553 if (ep)
602 return ep; 554 return ep;
603 } 555 }
@@ -1817,7 +1769,7 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
1817 struct fc_exch_mgr *mp; 1769 struct fc_exch_mgr *mp;
1818 size_t len; 1770 size_t len;
1819 1771
1820 if (max_xid <= min_xid || min_xid == 0 || max_xid == FC_XID_UNKNOWN) { 1772 if (max_xid <= min_xid || max_xid == FC_XID_UNKNOWN) {
1821 FC_LPORT_DBG(lp, "Invalid min_xid 0x:%x and max_xid 0x:%x\n", 1773 FC_LPORT_DBG(lp, "Invalid min_xid 0x:%x and max_xid 0x:%x\n",
1822 min_xid, max_xid); 1774 min_xid, max_xid);
1823 return NULL; 1775 return NULL;
@@ -1826,7 +1778,6 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
1826 /* 1778 /*
1827 * Memory need for EM 1779 * Memory need for EM
1828 */ 1780 */
1829#define xid_ok(i, m1, m2) (((i) >= (m1)) && ((i) <= (m2)))
1830 len = (max_xid - min_xid + 1) * (sizeof(struct fc_exch *)); 1781 len = (max_xid - min_xid + 1) * (sizeof(struct fc_exch *));
1831 len += sizeof(struct fc_exch_mgr); 1782 len += sizeof(struct fc_exch_mgr);
1832 1783
@@ -1840,17 +1791,7 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
1840 /* adjust em exch xid range for offload */ 1791 /* adjust em exch xid range for offload */
1841 mp->min_xid = min_xid; 1792 mp->min_xid = min_xid;
1842 mp->max_xid = max_xid; 1793 mp->max_xid = max_xid;
1843 mp->last_xid = min_xid - 1; 1794 mp->next_xid = min_xid;
1844 mp->max_read = 0;
1845 mp->last_read = 0;
1846 if (lp->lro_enabled && xid_ok(lp->lro_xid, min_xid, max_xid)) {
1847 mp->max_read = lp->lro_xid;
1848 mp->last_read = min_xid - 1;
1849 mp->last_xid = mp->max_read;
1850 } else {
1851 /* disable lro if no xid control over read */
1852 lp->lro_enabled = 0;
1853 }
1854 1795
1855 INIT_LIST_HEAD(&mp->ex_list); 1796 INIT_LIST_HEAD(&mp->ex_list);
1856 spin_lock_init(&mp->em_lock); 1797 spin_lock_init(&mp->em_lock);
@@ -1922,7 +1863,8 @@ struct fc_seq *fc_exch_seq_send(struct fc_lport *lp,
1922 fc_exch_setup_hdr(ep, fp, ep->f_ctl); 1863 fc_exch_setup_hdr(ep, fp, ep->f_ctl);
1923 sp->cnt++; 1864 sp->cnt++;
1924 1865
1925 fc_fcp_ddp_setup(fr_fsp(fp), ep->xid); 1866 if (ep->xid <= lp->lro_xid)
1867 fc_fcp_ddp_setup(fr_fsp(fp), ep->xid);
1926 1868
1927 if (unlikely(lp->tt.frame_send(lp, fp))) 1869 if (unlikely(lp->tt.frame_send(lp, fp)))
1928 goto err; 1870 goto err;