[SCSI] fcoe: modifies fcoe_hostlist_lock uses as prep work to add shared offload EM

Modifies fcoe_hostlist_lock uses such that a new EM allocation in
fcoe_em_config and adding new fcoe_softc using fcoe_hostlist_add
are atomic, this is to ensure that a shared offload EM gets allocated
only once per eth device for its all lports.

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>
This commit is contained in:
Vasu Dev 2009-07-29 17:05:15 -07:00 committed by James Bottomley
parent 52ff878c91
commit e8af4d4380

View File

@ -419,6 +419,8 @@ static int fcoe_shost_config(struct fc_lport *lp, struct Scsi_Host *shost,
* fcoe_em_config() - allocates em for this lport * fcoe_em_config() - allocates em for this lport
* @lp: the port that em is to allocated for * @lp: the port that em is to allocated for
* *
* Called with write fcoe_hostlist_lock held.
*
* Returns : 0 on success * Returns : 0 on success
*/ */
static inline int fcoe_em_config(struct fc_lport *lp) static inline int fcoe_em_config(struct fc_lport *lp)
@ -607,6 +609,13 @@ static int fcoe_if_create(struct net_device *netdev)
goto out_lp_destroy; goto out_lp_destroy;
} }
/*
* fcoe_em_alloc() and fcoe_hostlist_add() both
* need to be atomic under fcoe_hostlist_lock
* since fcoe_em_alloc() looks for an existing EM
* instance on host list updated by fcoe_hostlist_add().
*/
write_lock(&fcoe_hostlist_lock);
/* lport exch manager allocation */ /* lport exch manager allocation */
rc = fcoe_em_config(lp); rc = fcoe_em_config(lp);
if (rc) { if (rc) {
@ -617,6 +626,7 @@ static int fcoe_if_create(struct net_device *netdev)
/* add to lports list */ /* add to lports list */
fcoe_hostlist_add(lp); fcoe_hostlist_add(lp);
write_unlock(&fcoe_hostlist_lock);
lp->boot_time = jiffies; lp->boot_time = jiffies;
@ -1720,6 +1730,8 @@ int fcoe_reset(struct Scsi_Host *shost)
* fcoe_hostlist_lookup_softc() - find the corresponding lport by a given device * fcoe_hostlist_lookup_softc() - find the corresponding lport by a given device
* @dev: this is currently ptr to net_device * @dev: this is currently ptr to net_device
* *
* Called with fcoe_hostlist_lock held.
*
* Returns: NULL or the located fcoe_softc * Returns: NULL or the located fcoe_softc
*/ */
static struct fcoe_softc * static struct fcoe_softc *
@ -1727,14 +1739,10 @@ fcoe_hostlist_lookup_softc(const struct net_device *dev)
{ {
struct fcoe_softc *fc; struct fcoe_softc *fc;
read_lock(&fcoe_hostlist_lock);
list_for_each_entry(fc, &fcoe_hostlist, list) { list_for_each_entry(fc, &fcoe_hostlist, list) {
if (fc->real_dev == dev) { if (fc->real_dev == dev)
read_unlock(&fcoe_hostlist_lock);
return fc; return fc;
}
} }
read_unlock(&fcoe_hostlist_lock);
return NULL; return NULL;
} }
@ -1748,7 +1756,9 @@ struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev)
{ {
struct fcoe_softc *fc; struct fcoe_softc *fc;
read_lock(&fcoe_hostlist_lock);
fc = fcoe_hostlist_lookup_softc(netdev); fc = fcoe_hostlist_lookup_softc(netdev);
read_unlock(&fcoe_hostlist_lock);
return (fc) ? fc->ctlr.lp : NULL; return (fc) ? fc->ctlr.lp : NULL;
} }
@ -1757,6 +1767,8 @@ struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev)
* fcoe_hostlist_add() - Add a lport to lports list * fcoe_hostlist_add() - Add a lport to lports list
* @lp: ptr to the fc_lport to be added * @lp: ptr to the fc_lport to be added
* *
* Called with write fcoe_hostlist_lock held.
*
* Returns: 0 for success * Returns: 0 for success
*/ */
int fcoe_hostlist_add(const struct fc_lport *lp) int fcoe_hostlist_add(const struct fc_lport *lp)
@ -1766,9 +1778,7 @@ int fcoe_hostlist_add(const struct fc_lport *lp)
fc = fcoe_hostlist_lookup_softc(fcoe_netdev(lp)); fc = fcoe_hostlist_lookup_softc(fcoe_netdev(lp));
if (!fc) { if (!fc) {
fc = lport_priv(lp); fc = lport_priv(lp);
write_lock_bh(&fcoe_hostlist_lock);
list_add_tail(&fc->list, &fcoe_hostlist); list_add_tail(&fc->list, &fcoe_hostlist);
write_unlock_bh(&fcoe_hostlist_lock);
} }
return 0; return 0;
} }
@ -1783,9 +1793,9 @@ int fcoe_hostlist_remove(const struct fc_lport *lp)
{ {
struct fcoe_softc *fc; struct fcoe_softc *fc;
write_lock_bh(&fcoe_hostlist_lock);
fc = fcoe_hostlist_lookup_softc(fcoe_netdev(lp)); fc = fcoe_hostlist_lookup_softc(fcoe_netdev(lp));
BUG_ON(!fc); BUG_ON(!fc);
write_lock_bh(&fcoe_hostlist_lock);
list_del(&fc->list); list_del(&fc->list);
write_unlock_bh(&fcoe_hostlist_lock); write_unlock_bh(&fcoe_hostlist_lock);