aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libfc/fc_exch.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/libfc/fc_exch.c')
-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;