[Open-FCoE] [RFC PATCH 5/6] libfc: allocates dedicated EM for offload xid range

Vasu Dev vasu.dev at intel.com
Wed Apr 29 15:15:19 UTC 2009


Adds offload exchange manager(oemp) to fcoe_softc and then have oemp
shared by all VN_PORTs/lports on eth device fcoe_softc->phys_dev,
this mean oemp is allocated only once for a eth device and to
ensure this its allocation and free is protected by fcoe_hostlist_lock
with adding and removing fcoe_softc to fcoe_hostlist under same
fcoe_hostlist_lock.

Signed-off-by: Vasu Dev <vasu.dev at intel.com>
---

 drivers/scsi/fcoe/fcoe.c |  106 +++++++++++++++++++++++-----------------------
 drivers/scsi/fcoe/fcoe.h |    1 
 2 files changed, 55 insertions(+), 52 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 8dfaa31..6fe1662 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -67,8 +67,6 @@ static void fcoe_percpu_clean(struct fc_lport *lp);
 static int fcoe_link_ok(struct fc_lport *lp);
 
 static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *);
-static int fcoe_hostlist_add(const struct fc_lport *);
-static int fcoe_hostlist_remove(const struct fc_lport *);
 
 static void fcoe_check_wait_queue(struct fc_lport *, struct sk_buff *);
 static int fcoe_device_notification(struct notifier_block *, ulong, void *);
@@ -326,13 +324,57 @@ static int fcoe_shost_config(struct fc_lport *lp, struct Scsi_Host *shost,
  */
 static inline int fcoe_em_alloc(struct fc_lport *lp)
 {
+	struct fcoe_softc *fc = lport_priv(lp);
+	struct fcoe_softc *oldfc = NULL;
+	int rc = 0;
+
 	BUG_ON(lp->emp);
 
+	write_lock(&fcoe_hostlist_lock);
+	/*
+	 * Check if need to allocate an em instance for
+	 * offload exchange ids to be shared across all VN_PORTs/lport.
+	 */
+	if (!lp->lro_enabled || !lp->lro_xid || (lp->lro_xid >= FCOE_MAX_XID)) {
+		lp->lro_xid = 0;
+		goto skip_oem;
+	}
+
+	/*
+	 * Reuse exitsing offload em instance in case
+	 * it is already allocated on phys_dev
+	 */
+	list_for_each_entry(oldfc, &fcoe_hostlist, list) {
+		if (oldfc->phys_dev == fc->phys_dev) {
+			fc->oemp = oldfc->oemp;
+			break;
+		}
+	}
+
+	fc->oemp = fc_exch_mgr_alloc(lp, fc->oemp, FC_CLASS_3,
+				     FCOE_MIN_XID, lp->lro_xid);
+
+	if (!fc->oemp) {
+		printk(KERN_ERR "fcoe_em_alloc: failed to "
+		       "allocate em for offload%s\n", fc->real_dev->name);
+		rc = -ENOMEM;
+		goto out;
+	}
+
+skip_oem:
 	lp->emp = fc_exch_mgr_alloc(lp, NULL, FC_CLASS_3,
-				    FCOE_MIN_XID, FCOE_MAX_XID);
-	if (!lp->emp)
-		return -ENOMEM;
+				    FCOE_MIN_XID + lp->lro_xid,
+				    FCOE_MAX_XID);
 
+	if (!lp->emp) {
+		printk(KERN_ERR "fcoe_em_alloc: failed to "
+		       "allocate em for %s\n", fc->real_dev->name);
+		rc = -ENOMEM;
+		goto out;
+	}
+	list_add_tail(&fc->list, &fcoe_hostlist);
+out:
+	write_unlock(&fcoe_hostlist_lock);
 	return 0;
 }
 
@@ -344,7 +386,14 @@ static inline int fcoe_em_alloc(struct fc_lport *lp)
  */
 static inline int fcoe_em_free(struct fc_lport *lp)
 {
+	struct fcoe_softc *fc = lport_priv(lp);
+
+	write_lock(&fcoe_hostlist_lock);
+	list_del(&fc->list);
+	if (fc->oemp)
+		fc_exch_mgr_free(fc->oemp);
 	fc_exch_mgr_free(lp->emp);
+	write_unlock(&fcoe_hostlist_lock);
 	return 0;
 }
 
@@ -374,9 +423,6 @@ static int fcoe_if_destroy(struct net_device *netdev)
 	/* Logout of the fabric */
 	fc_fabric_logoff(lp);
 
-	/* Remove the instance from fcoe's list */
-	fcoe_hostlist_remove(lp);
-
 	/* Don't listen for Ethernet packets anymore */
 	dev_remove_pack(&fc->fcoe_packet_type);
 	dev_remove_pack(&fc->fip_packet_type);
@@ -598,9 +644,6 @@ static int fcoe_if_create(struct net_device *netdev)
 		goto out_lp_destroy;
 	}
 
-	/* add to lports list */
-	fcoe_hostlist_add(lp);
-
 	lp->boot_time = jiffies;
 
 	fc_fabric_login(lp);
@@ -1755,47 +1798,6 @@ struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev)
 EXPORT_SYMBOL_GPL(fcoe_hostlist_lookup);
 
 /**
- * fcoe_hostlist_add() - Add a lport to lports list
- * @lp: ptr to the fc_lport to badded
- *
- * Returns: 0 for success
- */
-int fcoe_hostlist_add(const struct fc_lport *lp)
-{
-	struct fcoe_softc *fc;
-
-	fc = fcoe_hostlist_lookup_softc(fcoe_netdev(lp));
-	if (!fc) {
-		fc = lport_priv(lp);
-		write_lock_bh(&fcoe_hostlist_lock);
-		list_add_tail(&fc->list, &fcoe_hostlist);
-		write_unlock_bh(&fcoe_hostlist_lock);
-	}
-	return 0;
-}
-EXPORT_SYMBOL_GPL(fcoe_hostlist_add);
-
-/**
- * fcoe_hostlist_remove() - remove a lport from lports list
- * @lp: ptr to the fc_lport to badded
- *
- * Returns: 0 for success
- */
-int fcoe_hostlist_remove(const struct fc_lport *lp)
-{
-	struct fcoe_softc *fc;
-
-	fc = fcoe_hostlist_lookup_softc(fcoe_netdev(lp));
-	BUG_ON(!fc);
-	write_lock_bh(&fcoe_hostlist_lock);
-	list_del(&fc->list);
-	write_unlock_bh(&fcoe_hostlist_lock);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(fcoe_hostlist_remove);
-
-/**
  * fcoe_init() - fcoe module loading initialization
  *
  * Returns 0 on success, negative on failure
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h
index a1eb8c1..95d90d9 100644
--- a/drivers/scsi/fcoe/fcoe.h
+++ b/drivers/scsi/fcoe/fcoe.h
@@ -57,6 +57,7 @@ struct fcoe_softc {
 	struct list_head list;
 	struct net_device *real_dev;
 	struct net_device *phys_dev;		/* device with ethtool_ops */
+	struct fc_exch_mgr *oemp;		/* offload exchane manager */
 	struct packet_type  fcoe_packet_type;
 	struct packet_type  fip_packet_type;
 	struct sk_buff_head fcoe_pending_queue;




More information about the devel mailing list