aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVasu Dev <vasu.dev@intel.com>2009-07-29 20:05:00 -0400
committerJames Bottomley <James.Bottomley@suse.de>2009-08-22 18:52:07 -0400
commit96316099ac3cb259eac2d6891f3c75b38b29d26e (patch)
treef4ec7001462bd00340de19b3045063872652c5a6
parent201e5795b7b9582accb6d83316e30f24d7d40fd3 (diff)
[SCSI] fcoe, libfc: adds exchange manager(EM) anchor list per lport and related APIs
Adds EM list using a anchor struct fc_exch_mgr_anchor, anchor is used to allow same EM instance sharing across more than one lport on a eth device, this implementation is per discussed design posted at http://www.open-fcoe.org/pipermail/devel/2009-June/002566.html. The shared EM is required for multiple lports on eth device when using multiple VLANs or NPIV. Adds fc_exch_mgr_add API to add a EM to the lport and fc_exch_mgr_del API to delete previously added EM. Also adds function fc_exch_mgr_destroy() to destroy allocated EM. The kref is added to the EM to keep track of EM usage count, the EM is destroyed when no longer in use upon kref reaching to zero. The caller can specify match function to fc_exch_mgr_add, this will be used in determining exchange allocation from its EM or not. Moved calling of fcoe_em_config below fcoe_libfc_config calling, so that list head lp->ema_list is initialized before configuring 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>
-rw-r--r--drivers/scsi/fcoe/fcoe.c14
-rw-r--r--drivers/scsi/libfc/fc_exch.c48
-rw-r--r--drivers/scsi/libfc/fc_lport.c1
-rw-r--r--include/scsi/libfc.h24
4 files changed, 80 insertions, 7 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 14a4017a1535..719a99d4a438 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -603,18 +603,18 @@ static int fcoe_if_create(struct net_device *netdev)
603 goto out_netdev_cleanup; 603 goto out_netdev_cleanup;
604 } 604 }
605 605
606 /* lport exch manager allocation */ 606 /* Initialize the library */
607 rc = fcoe_em_config(lp); 607 rc = fcoe_libfc_config(lp, &fcoe_libfc_fcn_templ);
608 if (rc) { 608 if (rc) {
609 FCOE_NETDEV_DBG(netdev, "Could not configure the EM for the " 609 FCOE_NETDEV_DBG(netdev, "Could not configure libfc for the "
610 "interface\n"); 610 "interface\n");
611 goto out_netdev_cleanup; 611 goto out_lp_destroy;
612 } 612 }
613 613
614 /* Initialize the library */ 614 /* lport exch manager allocation */
615 rc = fcoe_libfc_config(lp, &fcoe_libfc_fcn_templ); 615 rc = fcoe_em_config(lp);
616 if (rc) { 616 if (rc) {
617 FCOE_NETDEV_DBG(netdev, "Could not configure libfc for the " 617 FCOE_NETDEV_DBG(netdev, "Could not configure the EM for the "
618 "interface\n"); 618 "interface\n");
619 goto out_lp_destroy; 619 goto out_lp_destroy;
620 } 620 }
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index cab54996375c..f1fa2b196e98 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -55,6 +55,7 @@ static struct kmem_cache *fc_em_cachep; /* cache for exchanges */
55 */ 55 */
56struct fc_exch_mgr { 56struct fc_exch_mgr {
57 enum fc_class class; /* default class for sequences */ 57 enum fc_class class; /* default class for sequences */
58 struct kref kref; /* exchange mgr reference count */
58 spinlock_t em_lock; /* exchange manager lock, 59 spinlock_t em_lock; /* exchange manager lock,
59 must be taken before ex_lock */ 60 must be taken before ex_lock */
60 u16 last_xid; /* last allocated exchange ID */ 61 u16 last_xid; /* last allocated exchange ID */
@@ -84,6 +85,12 @@ struct fc_exch_mgr {
84}; 85};
85#define fc_seq_exch(sp) container_of(sp, struct fc_exch, seq) 86#define fc_seq_exch(sp) container_of(sp, struct fc_exch, seq)
86 87
88struct fc_exch_mgr_anchor {
89 struct list_head ema_list;
90 struct fc_exch_mgr *mp;
91 bool (*match)(struct fc_frame *);
92};
93
87static void fc_exch_rrq(struct fc_exch *); 94static void fc_exch_rrq(struct fc_exch *);
88static void fc_seq_ls_acc(struct fc_seq *); 95static void fc_seq_ls_acc(struct fc_seq *);
89static void fc_seq_ls_rjt(struct fc_seq *, enum fc_els_rjt_reason, 96static void fc_seq_ls_rjt(struct fc_seq *, enum fc_els_rjt_reason,
@@ -1729,6 +1736,47 @@ reject:
1729 fc_frame_free(fp); 1736 fc_frame_free(fp);
1730} 1737}
1731 1738
1739struct fc_exch_mgr_anchor *fc_exch_mgr_add(struct fc_lport *lport,
1740 struct fc_exch_mgr *mp,
1741 bool (*match)(struct fc_frame *))
1742{
1743 struct fc_exch_mgr_anchor *ema;
1744
1745 ema = kmalloc(sizeof(*ema), GFP_ATOMIC);
1746 if (!ema)
1747 return ema;
1748
1749 ema->mp = mp;
1750 ema->match = match;
1751 /* add EM anchor to EM anchors list */
1752 list_add_tail(&ema->ema_list, &lport->ema_list);
1753 kref_get(&mp->kref);
1754 return ema;
1755}
1756EXPORT_SYMBOL(fc_exch_mgr_add);
1757
1758static void fc_exch_mgr_destroy(struct kref *kref)
1759{
1760 struct fc_exch_mgr *mp = container_of(kref, struct fc_exch_mgr, kref);
1761
1762 /*
1763 * The total exch count must be zero
1764 * before freeing exchange manager.
1765 */
1766 WARN_ON(mp->total_exches != 0);
1767 mempool_destroy(mp->ep_pool);
1768 kfree(mp);
1769}
1770
1771void fc_exch_mgr_del(struct fc_exch_mgr_anchor *ema)
1772{
1773 /* remove EM anchor from EM anchors list */
1774 list_del(&ema->ema_list);
1775 kref_put(&ema->mp->kref, fc_exch_mgr_destroy);
1776 kfree(ema);
1777}
1778EXPORT_SYMBOL(fc_exch_mgr_del);
1779
1732struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp, 1780struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
1733 enum fc_class class, 1781 enum fc_class class,
1734 u16 min_xid, u16 max_xid) 1782 u16 min_xid, u16 max_xid)
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index a430335ebf59..ca8ea264b684 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -1618,6 +1618,7 @@ int fc_lport_init(struct fc_lport *lport)
1618 if (lport->link_supported_speeds & FC_PORTSPEED_10GBIT) 1618 if (lport->link_supported_speeds & FC_PORTSPEED_10GBIT)
1619 fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_10GBIT; 1619 fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_10GBIT;
1620 1620
1621 INIT_LIST_HEAD(&lport->ema_list);
1621 return 0; 1622 return 0;
1622} 1623}
1623EXPORT_SYMBOL(fc_lport_init); 1624EXPORT_SYMBOL(fc_lport_init);
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 04db7a9e631b..b381b1ca9aec 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -348,6 +348,7 @@ static inline bool fc_fcp_is_read(const struct fc_fcp_pkt *fsp)
348 */ 348 */
349 349
350struct fc_exch_mgr; 350struct fc_exch_mgr;
351struct fc_exch_mgr_anchor;
351 352
352/* 353/*
353 * Sequence. 354 * Sequence.
@@ -709,6 +710,7 @@ struct fc_lport {
709 /* Associations */ 710 /* Associations */
710 struct Scsi_Host *host; 711 struct Scsi_Host *host;
711 struct fc_exch_mgr *emp; 712 struct fc_exch_mgr *emp;
713 struct list_head ema_list;
712 struct fc_rport *dns_rp; 714 struct fc_rport *dns_rp;
713 struct fc_rport *ptp_rp; 715 struct fc_rport *ptp_rp;
714 void *scsi_priv; 716 void *scsi_priv;
@@ -964,6 +966,28 @@ int fc_elsct_init(struct fc_lport *lp);
964int fc_exch_init(struct fc_lport *lp); 966int fc_exch_init(struct fc_lport *lp);
965 967
966/* 968/*
969 * Adds Exchange Manager (EM) mp to lport.
970 *
971 * Adds specified mp to lport using struct fc_exch_mgr_anchor,
972 * the struct fc_exch_mgr_anchor allows same EM sharing by
973 * more than one lport with their specified match function,
974 * the match function is used in allocating exchange from
975 * added mp.
976 */
977struct fc_exch_mgr_anchor *fc_exch_mgr_add(struct fc_lport *lport,
978 struct fc_exch_mgr *mp,
979 bool (*match)(struct fc_frame *));
980
981/*
982 * Deletes Exchange Manager (EM) from lport by removing
983 * its anchor ema from lport.
984 *
985 * If removed anchor ema was the last user of its associated EM
986 * then also destroys associated EM.
987 */
988void fc_exch_mgr_del(struct fc_exch_mgr_anchor *ema);
989
990/*
967 * Allocates an Exchange Manager (EM). 991 * Allocates an Exchange Manager (EM).
968 * 992 *
969 * The EM manages exchanges for their allocation and 993 * The EM manages exchanges for their allocation and