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
