aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/fcoe/fcoe.c16
-rw-r--r--drivers/scsi/fcoe/libfcoe.c2
-rw-r--r--drivers/scsi/fnic/fnic_fcs.c2
-rw-r--r--drivers/scsi/fnic/fnic_main.c20
-rw-r--r--drivers/scsi/libfc/fc_exch.c191
-rw-r--r--include/scsi/libfc.h48
6 files changed, 142 insertions, 137 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 719a99d4a438..ebf2e20370d7 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -423,11 +423,8 @@ static int fcoe_shost_config(struct fc_lport *lp, struct Scsi_Host *shost,
423 */ 423 */
424static inline int fcoe_em_config(struct fc_lport *lp) 424static inline int fcoe_em_config(struct fc_lport *lp)
425{ 425{
426 BUG_ON(lp->emp); 426 if (!fc_exch_mgr_alloc(lp, FC_CLASS_3, FCOE_MIN_XID,
427 427 FCOE_MAX_XID, NULL))
428 lp->emp = fc_exch_mgr_alloc(lp, FC_CLASS_3,
429 FCOE_MIN_XID, FCOE_MAX_XID);
430 if (!lp->emp)
431 return -ENOMEM; 428 return -ENOMEM;
432 429
433 return 0; 430 return 0;
@@ -478,8 +475,7 @@ static int fcoe_if_destroy(struct net_device *netdev)
478 scsi_remove_host(lp->host); 475 scsi_remove_host(lp->host);
479 476
480 /* There are no more rports or I/O, free the EM */ 477 /* There are no more rports or I/O, free the EM */
481 if (lp->emp) 478 fc_exch_mgr_free(lp);
482 fc_exch_mgr_free(lp->emp);
483 479
484 /* Free existing skbs */ 480 /* Free existing skbs */
485 fcoe_clean_pending_queue(lp); 481 fcoe_clean_pending_queue(lp);
@@ -634,7 +630,7 @@ static int fcoe_if_create(struct net_device *netdev)
634 return rc; 630 return rc;
635 631
636out_lp_destroy: 632out_lp_destroy:
637 fc_exch_mgr_free(lp->emp); /* Free the EM */ 633 fc_exch_mgr_free(lp);
638out_netdev_cleanup: 634out_netdev_cleanup:
639 fcoe_netdev_cleanup(fc); 635 fcoe_netdev_cleanup(fc);
640out_host_put: 636out_host_put:
@@ -1277,7 +1273,7 @@ int fcoe_percpu_receive_thread(void *arg)
1277 fh = fc_frame_header_get(fp); 1273 fh = fc_frame_header_get(fp);
1278 if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA && 1274 if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA &&
1279 fh->fh_type == FC_TYPE_FCP) { 1275 fh->fh_type == FC_TYPE_FCP) {
1280 fc_exch_recv(lp, lp->emp, fp); 1276 fc_exch_recv(lp, fp);
1281 continue; 1277 continue;
1282 } 1278 }
1283 if (fr_flags(fp) & FCPHF_CRC_UNCHECKED) { 1279 if (fr_flags(fp) & FCPHF_CRC_UNCHECKED) {
@@ -1298,7 +1294,7 @@ int fcoe_percpu_receive_thread(void *arg)
1298 fc_frame_free(fp); 1294 fc_frame_free(fp);
1299 continue; 1295 continue;
1300 } 1296 }
1301 fc_exch_recv(lp, lp->emp, fp); 1297 fc_exch_recv(lp, fp);
1302 } 1298 }
1303 return 0; 1299 return 0;
1304} 1300}
diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c
index 78caa6be1130..4db719d6ada1 100644
--- a/drivers/scsi/fcoe/libfcoe.c
+++ b/drivers/scsi/fcoe/libfcoe.c
@@ -885,7 +885,7 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb)
885 stats->RxFrames++; 885 stats->RxFrames++;
886 stats->RxWords += skb->len / FIP_BPW; 886 stats->RxWords += skb->len / FIP_BPW;
887 887
888 fc_exch_recv(lp, lp->emp, fp); 888 fc_exch_recv(lp, fp);
889 return; 889 return;
890 890
891len_err: 891len_err:
diff --git a/drivers/scsi/fnic/fnic_fcs.c b/drivers/scsi/fnic/fnic_fcs.c
index 07e6eedb83ce..50db3e36a619 100644
--- a/drivers/scsi/fnic/fnic_fcs.c
+++ b/drivers/scsi/fnic/fnic_fcs.c
@@ -115,7 +115,7 @@ void fnic_handle_frame(struct work_struct *work)
115 } 115 }
116 spin_unlock_irqrestore(&fnic->fnic_lock, flags); 116 spin_unlock_irqrestore(&fnic->fnic_lock, flags);
117 117
118 fc_exch_recv(lp, lp->emp, fp); 118 fc_exch_recv(lp, fp);
119 } 119 }
120 120
121} 121}
diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c
index 2c266c01dc5a..71c7bbe26d05 100644
--- a/drivers/scsi/fnic/fnic_main.c
+++ b/drivers/scsi/fnic/fnic_main.c
@@ -671,14 +671,6 @@ static int __devinit fnic_probe(struct pci_dev *pdev,
671 lp->link_up = 0; 671 lp->link_up = 0;
672 lp->tt = fnic_transport_template; 672 lp->tt = fnic_transport_template;
673 673
674 lp->emp = fc_exch_mgr_alloc(lp, FC_CLASS_3,
675 FCPIO_HOST_EXCH_RANGE_START,
676 FCPIO_HOST_EXCH_RANGE_END);
677 if (!lp->emp) {
678 err = -ENOMEM;
679 goto err_out_remove_scsi_host;
680 }
681
682 lp->max_retry_count = fnic->config.flogi_retries; 674 lp->max_retry_count = fnic->config.flogi_retries;
683 lp->max_rport_retry_count = fnic->config.plogi_retries; 675 lp->max_rport_retry_count = fnic->config.plogi_retries;
684 lp->service_params = (FCP_SPPF_INIT_FCN | FCP_SPPF_RD_XRDY_DIS | 676 lp->service_params = (FCP_SPPF_INIT_FCN | FCP_SPPF_RD_XRDY_DIS |
@@ -693,12 +685,18 @@ static int __devinit fnic_probe(struct pci_dev *pdev,
693 fc_set_wwnn(lp, fnic->config.node_wwn); 685 fc_set_wwnn(lp, fnic->config.node_wwn);
694 fc_set_wwpn(lp, fnic->config.port_wwn); 686 fc_set_wwpn(lp, fnic->config.port_wwn);
695 687
696 fc_exch_init(lp);
697 fc_lport_init(lp); 688 fc_lport_init(lp);
689 fc_exch_init(lp);
698 fc_elsct_init(lp); 690 fc_elsct_init(lp);
699 fc_rport_init(lp); 691 fc_rport_init(lp);
700 fc_disc_init(lp); 692 fc_disc_init(lp);
701 693
694 if (!fc_exch_mgr_alloc(lp, FC_CLASS_3, FCPIO_HOST_EXCH_RANGE_START,
695 FCPIO_HOST_EXCH_RANGE_END, NULL)) {
696 err = -ENOMEM;
697 goto err_out_remove_scsi_host;
698 }
699
702 fc_lport_config(lp); 700 fc_lport_config(lp);
703 701
704 if (fc_set_mfs(lp, fnic->config.maxdatafieldsize + 702 if (fc_set_mfs(lp, fnic->config.maxdatafieldsize +
@@ -738,7 +736,7 @@ static int __devinit fnic_probe(struct pci_dev *pdev,
738 return 0; 736 return 0;
739 737
740err_out_free_exch_mgr: 738err_out_free_exch_mgr:
741 fc_exch_mgr_free(lp->emp); 739 fc_exch_mgr_free(lp);
742err_out_remove_scsi_host: 740err_out_remove_scsi_host:
743 fc_remove_host(fnic->lport->host); 741 fc_remove_host(fnic->lport->host);
744 scsi_remove_host(fnic->lport->host); 742 scsi_remove_host(fnic->lport->host);
@@ -827,7 +825,7 @@ static void __devexit fnic_remove(struct pci_dev *pdev)
827 825
828 fc_remove_host(fnic->lport->host); 826 fc_remove_host(fnic->lport->host);
829 scsi_remove_host(fnic->lport->host); 827 scsi_remove_host(fnic->lport->host);
830 fc_exch_mgr_free(fnic->lport->emp); 828 fc_exch_mgr_free(fnic->lport);
831 vnic_dev_notify_unset(fnic->vdev); 829 vnic_dev_notify_unset(fnic->vdev);
832 fnic_free_vnic_resources(fnic); 830 fnic_free_vnic_resources(fnic);
833 fnic_free_intr(fnic); 831 fnic_free_intr(fnic);
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 3ad7f88e7ae3..324589a5cc03 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -65,7 +65,6 @@ struct fc_exch_mgr {
65 u16 last_read; /* last xid allocated for read */ 65 u16 last_read; /* last xid allocated for read */
66 u32 total_exches; /* total allocated exchanges */ 66 u32 total_exches; /* total allocated exchanges */
67 struct list_head ex_list; /* allocated exchanges list */ 67 struct list_head ex_list; /* allocated exchanges list */
68 struct fc_lport *lp; /* fc device instance */
69 mempool_t *ep_pool; /* reserve ep's */ 68 mempool_t *ep_pool; /* reserve ep's */
70 69
71 /* 70 /*
@@ -275,8 +274,6 @@ static void fc_exch_release(struct fc_exch *ep)
275 mp = ep->em; 274 mp = ep->em;
276 if (ep->destructor) 275 if (ep->destructor)
277 ep->destructor(&ep->seq, ep->arg); 276 ep->destructor(&ep->seq, ep->arg);
278 if (ep->lp->tt.exch_put)
279 ep->lp->tt.exch_put(ep->lp, mp, ep->xid);
280 WARN_ON(!(ep->esb_stat & ESB_ST_COMPLETE)); 277 WARN_ON(!(ep->esb_stat & ESB_ST_COMPLETE));
281 mempool_free(ep, mp->ep_pool); 278 mempool_free(ep, mp->ep_pool);
282 } 279 }
@@ -513,17 +510,20 @@ static u16 fc_em_alloc_xid(struct fc_exch_mgr *mp, const struct fc_frame *fp)
513 return xid; 510 return xid;
514} 511}
515 512
516/* 513/**
517 * fc_exch_alloc - allocate an exchange. 514 * fc_exch_em_alloc() - allocate an exchange from a specified EM.
518 * @mp : ptr to the exchange manager 515 * @lport: ptr to the local port
519 * @xid: input xid 516 * @mp: ptr to the exchange manager
517 * @fp: ptr to the FC frame
518 * @xid: input xid
520 * 519 *
521 * if xid is supplied zero then assign next free exchange ID 520 * if xid is supplied zero then assign next free exchange ID
522 * from exchange manager, otherwise use supplied xid. 521 * from exchange manager, otherwise use supplied xid.
523 * Returns with exch lock held. 522 * Returns with exch lock held.
524 */ 523 */
525struct fc_exch *fc_exch_alloc(struct fc_exch_mgr *mp, 524static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport,
526 struct fc_frame *fp, u16 xid) 525 struct fc_exch_mgr *mp,
526 struct fc_frame *fp, u16 xid)
527{ 527{
528 struct fc_exch *ep; 528 struct fc_exch *ep;
529 529
@@ -566,7 +566,7 @@ struct fc_exch *fc_exch_alloc(struct fc_exch_mgr *mp,
566 */ 566 */
567 ep->oxid = ep->xid = xid; 567 ep->oxid = ep->xid = xid;
568 ep->em = mp; 568 ep->em = mp;
569 ep->lp = mp->lp; 569 ep->lp = lport;
570 ep->f_ctl = FC_FC_FIRST_SEQ; /* next seq is first seq */ 570 ep->f_ctl = FC_FC_FIRST_SEQ; /* next seq is first seq */
571 ep->rxid = FC_XID_UNKNOWN; 571 ep->rxid = FC_XID_UNKNOWN;
572 ep->class = mp->class; 572 ep->class = mp->class;
@@ -579,6 +579,31 @@ err:
579 mempool_free(ep, mp->ep_pool); 579 mempool_free(ep, mp->ep_pool);
580 return NULL; 580 return NULL;
581} 581}
582
583/**
584 * fc_exch_alloc() - allocate an exchange.
585 * @lport: ptr to the local port
586 * @fp: ptr to the FC frame
587 *
588 * This function walks the list of the exchange manager(EM)
589 * anchors to select a EM for new exchange allocation. The
590 * EM is selected having either a NULL match function pointer
591 * or call to match function returning true.
592 */
593struct fc_exch *fc_exch_alloc(struct fc_lport *lport, struct fc_frame *fp)
594{
595 struct fc_exch_mgr_anchor *ema;
596 struct fc_exch *ep;
597
598 list_for_each_entry(ema, &lport->ema_list, ema_list) {
599 if (!ema->match || ema->match(fp)) {
600 ep = fc_exch_em_alloc(lport, ema->mp, fp, 0);
601 if (ep)
602 return ep;
603 }
604 }
605 return NULL;
606}
582EXPORT_SYMBOL(fc_exch_alloc); 607EXPORT_SYMBOL(fc_exch_alloc);
583 608
584/* 609/*
@@ -617,12 +642,14 @@ EXPORT_SYMBOL(fc_exch_done);
617 * Allocate a new exchange as responder. 642 * Allocate a new exchange as responder.
618 * Sets the responder ID in the frame header. 643 * Sets the responder ID in the frame header.
619 */ 644 */
620static struct fc_exch *fc_exch_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) 645static struct fc_exch *fc_exch_resp(struct fc_lport *lport,
646 struct fc_exch_mgr *mp,
647 struct fc_frame *fp)
621{ 648{
622 struct fc_exch *ep; 649 struct fc_exch *ep;
623 struct fc_frame_header *fh; 650 struct fc_frame_header *fh;
624 651
625 ep = mp->lp->tt.exch_get(mp->lp, fp); 652 ep = fc_exch_alloc(lport, fp);
626 if (ep) { 653 if (ep) {
627 ep->class = fc_frame_class(fp); 654 ep->class = fc_frame_class(fp);
628 655
@@ -648,7 +675,7 @@ static struct fc_exch *fc_exch_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
648 ep->esb_stat &= ~ESB_ST_SEQ_INIT; 675 ep->esb_stat &= ~ESB_ST_SEQ_INIT;
649 676
650 fc_exch_hold(ep); /* hold for caller */ 677 fc_exch_hold(ep); /* hold for caller */
651 spin_unlock_bh(&ep->ex_lock); /* lock from exch_get */ 678 spin_unlock_bh(&ep->ex_lock); /* lock from fc_exch_alloc */
652 } 679 }
653 return ep; 680 return ep;
654} 681}
@@ -658,7 +685,8 @@ static struct fc_exch *fc_exch_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
658 * If fc_pf_rjt_reason is FC_RJT_NONE then this function will have a hold 685 * If fc_pf_rjt_reason is FC_RJT_NONE then this function will have a hold
659 * on the ep that should be released by the caller. 686 * on the ep that should be released by the caller.
660 */ 687 */
661static enum fc_pf_rjt_reason fc_seq_lookup_recip(struct fc_exch_mgr *mp, 688static enum fc_pf_rjt_reason fc_seq_lookup_recip(struct fc_lport *lport,
689 struct fc_exch_mgr *mp,
662 struct fc_frame *fp) 690 struct fc_frame *fp)
663{ 691{
664 struct fc_frame_header *fh = fc_frame_header_get(fp); 692 struct fc_frame_header *fh = fc_frame_header_get(fp);
@@ -712,7 +740,7 @@ static enum fc_pf_rjt_reason fc_seq_lookup_recip(struct fc_exch_mgr *mp,
712 reject = FC_RJT_RX_ID; 740 reject = FC_RJT_RX_ID;
713 goto rel; 741 goto rel;
714 } 742 }
715 ep = fc_exch_resp(mp, fp); 743 ep = fc_exch_resp(lport, mp, fp);
716 if (!ep) { 744 if (!ep) {
717 reject = FC_RJT_EXCH_EST; /* XXX */ 745 reject = FC_RJT_EXCH_EST; /* XXX */
718 goto out; 746 goto out;
@@ -1103,7 +1131,7 @@ static void fc_exch_recv_req(struct fc_lport *lp, struct fc_exch_mgr *mp,
1103 enum fc_pf_rjt_reason reject; 1131 enum fc_pf_rjt_reason reject;
1104 1132
1105 fr_seq(fp) = NULL; 1133 fr_seq(fp) = NULL;
1106 reject = fc_seq_lookup_recip(mp, fp); 1134 reject = fc_seq_lookup_recip(lp, mp, fp);
1107 if (reject == FC_RJT_NONE) { 1135 if (reject == FC_RJT_NONE) {
1108 sp = fr_seq(fp); /* sequence will be held */ 1136 sp = fr_seq(fp); /* sequence will be held */
1109 ep = fc_seq_exch(sp); 1137 ep = fc_seq_exch(sp);
@@ -1467,29 +1495,34 @@ void fc_exch_mgr_reset(struct fc_lport *lp, u32 sid, u32 did)
1467{ 1495{
1468 struct fc_exch *ep; 1496 struct fc_exch *ep;
1469 struct fc_exch *next; 1497 struct fc_exch *next;
1470 struct fc_exch_mgr *mp = lp->emp; 1498 struct fc_exch_mgr *mp;
1499 struct fc_exch_mgr_anchor *ema;
1471 1500
1472 spin_lock_bh(&mp->em_lock); 1501 list_for_each_entry(ema, &lp->ema_list, ema_list) {
1502 mp = ema->mp;
1503 spin_lock_bh(&mp->em_lock);
1473restart: 1504restart:
1474 list_for_each_entry_safe(ep, next, &mp->ex_list, ex_list) { 1505 list_for_each_entry_safe(ep, next, &mp->ex_list, ex_list) {
1475 if ((sid == 0 || sid == ep->sid) && 1506 if ((lp == ep->lp) &&
1476 (did == 0 || did == ep->did)) { 1507 (sid == 0 || sid == ep->sid) &&
1477 fc_exch_hold(ep); 1508 (did == 0 || did == ep->did)) {
1478 spin_unlock_bh(&mp->em_lock); 1509 fc_exch_hold(ep);
1479 1510 spin_unlock_bh(&mp->em_lock);
1480 fc_exch_reset(ep); 1511
1481 1512 fc_exch_reset(ep);
1482 fc_exch_release(ep); 1513
1483 spin_lock_bh(&mp->em_lock); 1514 fc_exch_release(ep);
1484 1515 spin_lock_bh(&mp->em_lock);
1485 /* 1516
1486 * must restart loop incase while lock was down 1517 /*
1487 * multiple eps were released. 1518 * must restart loop incase while lock
1488 */ 1519 * was down multiple eps were released.
1489 goto restart; 1520 */
1521 goto restart;
1522 }
1490 } 1523 }
1524 spin_unlock_bh(&mp->em_lock);
1491 } 1525 }
1492 spin_unlock_bh(&mp->em_lock);
1493} 1526}
1494EXPORT_SYMBOL(fc_exch_mgr_reset); 1527EXPORT_SYMBOL(fc_exch_mgr_reset);
1495 1528
@@ -1778,7 +1811,8 @@ EXPORT_SYMBOL(fc_exch_mgr_del);
1778 1811
1779struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp, 1812struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
1780 enum fc_class class, 1813 enum fc_class class,
1781 u16 min_xid, u16 max_xid) 1814 u16 min_xid, u16 max_xid,
1815 bool (*match)(struct fc_frame *))
1782{ 1816{
1783 struct fc_exch_mgr *mp; 1817 struct fc_exch_mgr *mp;
1784 size_t len; 1818 size_t len;
@@ -1803,7 +1837,6 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
1803 mp->class = class; 1837 mp->class = class;
1804 mp->total_exches = 0; 1838 mp->total_exches = 0;
1805 mp->exches = (struct fc_exch **)(mp + 1); 1839 mp->exches = (struct fc_exch **)(mp + 1);
1806 mp->lp = lp;
1807 /* adjust em exch xid range for offload */ 1840 /* adjust em exch xid range for offload */
1808 mp->min_xid = min_xid; 1841 mp->min_xid = min_xid;
1809 mp->max_xid = max_xid; 1842 mp->max_xid = max_xid;
@@ -1826,6 +1859,18 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
1826 if (!mp->ep_pool) 1859 if (!mp->ep_pool)
1827 goto free_mp; 1860 goto free_mp;
1828 1861
1862 kref_init(&mp->kref);
1863 if (!fc_exch_mgr_add(lp, mp, match)) {
1864 mempool_destroy(mp->ep_pool);
1865 goto free_mp;
1866 }
1867
1868 /*
1869 * Above kref_init() sets mp->kref to 1 and then
1870 * call to fc_exch_mgr_add incremented mp->kref again,
1871 * so adjust that extra increment.
1872 */
1873 kref_put(&mp->kref, fc_exch_mgr_destroy);
1829 return mp; 1874 return mp;
1830 1875
1831free_mp: 1876free_mp:
@@ -1834,27 +1879,15 @@ free_mp:
1834} 1879}
1835EXPORT_SYMBOL(fc_exch_mgr_alloc); 1880EXPORT_SYMBOL(fc_exch_mgr_alloc);
1836 1881
1837void fc_exch_mgr_free(struct fc_exch_mgr *mp) 1882void fc_exch_mgr_free(struct fc_lport *lport)
1838{ 1883{
1839 WARN_ON(!mp); 1884 struct fc_exch_mgr_anchor *ema, *next;
1840 /* 1885
1841 * The total exch count must be zero 1886 list_for_each_entry_safe(ema, next, &lport->ema_list, ema_list)
1842 * before freeing exchange manager. 1887 fc_exch_mgr_del(ema);
1843 */
1844 WARN_ON(mp->total_exches != 0);
1845 mempool_destroy(mp->ep_pool);
1846 kfree(mp);
1847} 1888}
1848EXPORT_SYMBOL(fc_exch_mgr_free); 1889EXPORT_SYMBOL(fc_exch_mgr_free);
1849 1890
1850struct fc_exch *fc_exch_get(struct fc_lport *lp, struct fc_frame *fp)
1851{
1852 if (!lp || !lp->emp)
1853 return NULL;
1854
1855 return fc_exch_alloc(lp->emp, fp, 0);
1856}
1857EXPORT_SYMBOL(fc_exch_get);
1858 1891
1859struct fc_seq *fc_exch_seq_send(struct fc_lport *lp, 1892struct fc_seq *fc_exch_seq_send(struct fc_lport *lp,
1860 struct fc_frame *fp, 1893 struct fc_frame *fp,
@@ -1869,7 +1902,7 @@ struct fc_seq *fc_exch_seq_send(struct fc_lport *lp,
1869 struct fc_frame_header *fh; 1902 struct fc_frame_header *fh;
1870 int rc = 1; 1903 int rc = 1;
1871 1904
1872 ep = lp->tt.exch_get(lp, fp); 1905 ep = fc_exch_alloc(lp, fp);
1873 if (!ep) { 1906 if (!ep) {
1874 fc_frame_free(fp); 1907 fc_frame_free(fp);
1875 return NULL; 1908 return NULL;
@@ -1914,24 +1947,44 @@ EXPORT_SYMBOL(fc_exch_seq_send);
1914/* 1947/*
1915 * Receive a frame 1948 * Receive a frame
1916 */ 1949 */
1917void fc_exch_recv(struct fc_lport *lp, struct fc_exch_mgr *mp, 1950void fc_exch_recv(struct fc_lport *lp, struct fc_frame *fp)
1918 struct fc_frame *fp)
1919{ 1951{
1920 struct fc_frame_header *fh = fc_frame_header_get(fp); 1952 struct fc_frame_header *fh = fc_frame_header_get(fp);
1921 u32 f_ctl; 1953 struct fc_exch_mgr_anchor *ema;
1954 u32 f_ctl, found = 0;
1955 u16 oxid;
1922 1956
1923 /* lport lock ? */ 1957 /* lport lock ? */
1924 if (!lp || !mp || lp->state == LPORT_ST_DISABLED) { 1958 if (!lp || lp->state == LPORT_ST_DISABLED) {
1925 FC_LPORT_DBG(lp, "Receiving frames for an lport that " 1959 FC_LPORT_DBG(lp, "Receiving frames for an lport that "
1926 "has not been initialized correctly\n"); 1960 "has not been initialized correctly\n");
1927 fc_frame_free(fp); 1961 fc_frame_free(fp);
1928 return; 1962 return;
1929 } 1963 }
1930 1964
1965 f_ctl = ntoh24(fh->fh_f_ctl);
1966 oxid = ntohs(fh->fh_ox_id);
1967 if (f_ctl & FC_FC_EX_CTX) {
1968 list_for_each_entry(ema, &lp->ema_list, ema_list) {
1969 if ((oxid >= ema->mp->min_xid) &&
1970 (oxid <= ema->mp->max_xid)) {
1971 found = 1;
1972 break;
1973 }
1974 }
1975
1976 if (!found) {
1977 FC_LPORT_DBG(lp, "Received response for out "
1978 "of range oxid:%hx\n", oxid);
1979 fc_frame_free(fp);
1980 return;
1981 }
1982 } else
1983 ema = list_entry(lp->ema_list.prev, typeof(*ema), ema_list);
1984
1931 /* 1985 /*
1932 * If frame is marked invalid, just drop it. 1986 * If frame is marked invalid, just drop it.
1933 */ 1987 */
1934 f_ctl = ntoh24(fh->fh_f_ctl);
1935 switch (fr_eof(fp)) { 1988 switch (fr_eof(fp)) {
1936 case FC_EOF_T: 1989 case FC_EOF_T:
1937 if (f_ctl & FC_FC_END_SEQ) 1990 if (f_ctl & FC_FC_END_SEQ)
@@ -1939,34 +1992,24 @@ void fc_exch_recv(struct fc_lport *lp, struct fc_exch_mgr *mp,
1939 /* fall through */ 1992 /* fall through */
1940 case FC_EOF_N: 1993 case FC_EOF_N:
1941 if (fh->fh_type == FC_TYPE_BLS) 1994 if (fh->fh_type == FC_TYPE_BLS)
1942 fc_exch_recv_bls(mp, fp); 1995 fc_exch_recv_bls(ema->mp, fp);
1943 else if ((f_ctl & (FC_FC_EX_CTX | FC_FC_SEQ_CTX)) == 1996 else if ((f_ctl & (FC_FC_EX_CTX | FC_FC_SEQ_CTX)) ==
1944 FC_FC_EX_CTX) 1997 FC_FC_EX_CTX)
1945 fc_exch_recv_seq_resp(mp, fp); 1998 fc_exch_recv_seq_resp(ema->mp, fp);
1946 else if (f_ctl & FC_FC_SEQ_CTX) 1999 else if (f_ctl & FC_FC_SEQ_CTX)
1947 fc_exch_recv_resp(mp, fp); 2000 fc_exch_recv_resp(ema->mp, fp);
1948 else 2001 else
1949 fc_exch_recv_req(lp, mp, fp); 2002 fc_exch_recv_req(lp, ema->mp, fp);
1950 break; 2003 break;
1951 default: 2004 default:
1952 FC_LPORT_DBG(lp, "dropping invalid frame (eof %x)", fr_eof(fp)); 2005 FC_LPORT_DBG(lp, "dropping invalid frame (eof %x)", fr_eof(fp));
1953 fc_frame_free(fp); 2006 fc_frame_free(fp);
1954 break;
1955 } 2007 }
1956} 2008}
1957EXPORT_SYMBOL(fc_exch_recv); 2009EXPORT_SYMBOL(fc_exch_recv);
1958 2010
1959int fc_exch_init(struct fc_lport *lp) 2011int fc_exch_init(struct fc_lport *lp)
1960{ 2012{
1961 if (!lp->tt.exch_get) {
1962 /*
1963 * exch_put() should be NULL if
1964 * exch_get() is NULL
1965 */
1966 WARN_ON(lp->tt.exch_put);
1967 lp->tt.exch_get = fc_exch_get;
1968 }
1969
1970 if (!lp->tt.seq_start_next) 2013 if (!lp->tt.seq_start_next)
1971 lp->tt.seq_start_next = fc_seq_start_next; 2014 lp->tt.seq_start_next = fc_seq_start_next;
1972 2015
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index f1bde91f98a2..c2b928cfafb9 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -518,25 +518,6 @@ struct libfc_function_template {
518 void (*exch_done)(struct fc_seq *sp); 518 void (*exch_done)(struct fc_seq *sp);
519 519
520 /* 520 /*
521 * Assigns a EM and a free XID for an new exchange and then
522 * allocates a new exchange and sequence pair.
523 * The fp can be used to determine free XID.
524 *
525 * STATUS: OPTIONAL
526 */
527 struct fc_exch *(*exch_get)(struct fc_lport *lp, struct fc_frame *fp);
528
529 /*
530 * Release previously assigned XID by exch_get API.
531 * The LLD may implement this if XID is assigned by LLD
532 * in exch_get().
533 *
534 * STATUS: OPTIONAL
535 */
536 void (*exch_put)(struct fc_lport *lp, struct fc_exch_mgr *mp,
537 u16 ex_id);
538
539 /*
540 * Start a new sequence on the same exchange/sequence tuple. 521 * Start a new sequence on the same exchange/sequence tuple.
541 * 522 *
542 * STATUS: OPTIONAL 523 * STATUS: OPTIONAL
@@ -703,7 +684,6 @@ struct fc_lport {
703 684
704 /* Associations */ 685 /* Associations */
705 struct Scsi_Host *host; 686 struct Scsi_Host *host;
706 struct fc_exch_mgr *emp;
707 struct list_head ema_list; 687 struct list_head ema_list;
708 struct fc_rport *dns_rp; 688 struct fc_rport *dns_rp;
709 struct fc_rport *ptp_rp; 689 struct fc_rport *ptp_rp;
@@ -996,27 +976,25 @@ void fc_exch_mgr_del(struct fc_exch_mgr_anchor *ema);
996 * a new exchange. 976 * a new exchange.
997 * The LLD may choose to have multiple EMs, 977 * The LLD may choose to have multiple EMs,
998 * e.g. one EM instance per CPU receive thread in LLD. 978 * e.g. one EM instance per CPU receive thread in LLD.
999 * The LLD can use exch_get() of struct libfc_function_template
1000 * to specify XID for a new exchange within
1001 * a specified EM instance.
1002 * 979 *
1003 * The em_idx to uniquely identify an EM instance. 980 * Specified match function is used in allocating exchanges
981 * from newly allocated EM.
1004 */ 982 */
1005struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp, 983struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
1006 enum fc_class class, 984 enum fc_class class,
1007 u16 min_xid, 985 u16 min_xid,
1008 u16 max_xid); 986 u16 max_xid,
987 bool (*match)(struct fc_frame *));
1009 988
1010/* 989/*
1011 * Free an exchange manager. 990 * Free all exchange managers of a lport.
1012 */ 991 */
1013void fc_exch_mgr_free(struct fc_exch_mgr *mp); 992void fc_exch_mgr_free(struct fc_lport *lport);
1014 993
1015/* 994/*
1016 * Receive a frame on specified local port and exchange manager. 995 * Receive a frame on specified local port and exchange manager.
1017 */ 996 */
1018void fc_exch_recv(struct fc_lport *lp, struct fc_exch_mgr *mp, 997void fc_exch_recv(struct fc_lport *lp, struct fc_frame *fp);
1019 struct fc_frame *fp);
1020 998
1021/* 999/*
1022 * This function is for exch_seq_send function pointer in 1000 * This function is for exch_seq_send function pointer in
@@ -1058,19 +1036,9 @@ int fc_seq_exch_abort(const struct fc_seq *req_sp, unsigned int timer_msec);
1058void fc_exch_done(struct fc_seq *sp); 1036void fc_exch_done(struct fc_seq *sp);
1059 1037
1060/* 1038/*
1061 * Assigns a EM and XID for a frame and then allocates
1062 * a new exchange and sequence pair.
1063 * The fp can be used to determine free XID.
1064 */
1065struct fc_exch *fc_exch_get(struct fc_lport *lp, struct fc_frame *fp);
1066
1067/*
1068 * Allocate a new exchange and sequence pair. 1039 * Allocate a new exchange and sequence pair.
1069 * if ex_id is zero then next free exchange id
1070 * from specified exchange manger mp will be assigned.
1071 */ 1040 */
1072struct fc_exch *fc_exch_alloc(struct fc_exch_mgr *mp, 1041struct fc_exch *fc_exch_alloc(struct fc_lport *lport, struct fc_frame *fp);
1073 struct fc_frame *fp, u16 ex_id);
1074/* 1042/*
1075 * Start a new sequence on the same exchange as the supplied sequence. 1043 * Start a new sequence on the same exchange as the supplied sequence.
1076 */ 1044 */