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 <[email protected]>
---

 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;

_______________________________________________
devel mailing list
[email protected]
http://www.open-fcoe.org/mailman/listinfo/devel

Reply via email to