aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libfc
diff options
context:
space:
mode:
authorVasu Dev <vasu.dev@intel.com>2009-07-29 20:05:21 -0400
committerJames Bottomley <James.Bottomley@suse.de>2009-08-22 18:52:09 -0400
commitd7179680d04f1e196b7a5f70e7f93bb1850407c6 (patch)
treee31aaf450afcd7cba0d719178424ece5013964f8 /drivers/scsi/libfc
parente8af4d4380babc89d193c16163f070a6418f033b (diff)
[SCSI] fcoe, libfc: adds offload EM per eth device with only single xid range per EM
Updates fcoe_em_config to allocate a single instance of sharable offload EM for supported lp->lro_xid per eth device, and then share this EM for subsequently more lports creation on same eth device (e.g when using VLAN). Adds tiny fcoe_oem_match function for offload EM to return true for read types IO to have read IO exchanges allocated from offload shared EM. Removes fc_em_alloc_xid function completely which was needed to manage two xid ranges within a EM, this is not needed any more with allocation of separate sharable offload EM per eth device. Instead this patch adds simple xid allocation logic to manage single xid range. Adds fc_exch_em_alloc with mp->next_xid as cursor to allocate new xid from single xid range of EM, uses mp->next_xid instead removed mp->last_xid which slightly increase probability of finding empty xid on exch allocation. Removes restriction of not allowing use of xid zero along with changing two xid range change to single xid range. Makes fc_fcp_ddp_setup calling conditional to only xid allocated from shared offload EM. Signed-off-by: Vasu Dev <vasu.dev@intel.com> Signed-off-by: Robert Love <robert.w.love@intel.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/libfc')
-rw-r--r--drivers/scsi/libfc/fc_exch.c94
1 files changed, 18 insertions, 76 deletions
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;