diff --git a/drivers/staging/vme/vme.c b/drivers/staging/vme/vme.c index 4ca9d02cc2c8..b2968f8588ff 100644 --- a/drivers/staging/vme/vme.c +++ b/drivers/staging/vme/vme.c @@ -34,9 +34,10 @@ #include "vme.h" #include "vme_bridge.h" -/* Bitmask and mutex to keep track of bridge numbers */ +/* Bitmask and list of registered buses both protected by common mutex */ static unsigned int vme_bus_numbers; -static DEFINE_MUTEX(vme_bus_num_mtx); +static LIST_HEAD(vme_bus_list); +static DEFINE_MUTEX(vme_buses_lock); static void __exit vme_exit(void); static int __init vme_init(void); @@ -1309,27 +1310,32 @@ EXPORT_SYMBOL(vme_slot_get); /* - Bridge Registration --------------------------------------------------- */ -static int vme_alloc_bus_num(void) +static int vme_add_bus(struct vme_bridge *bridge) { int i; + int ret = -1; - mutex_lock(&vme_bus_num_mtx); + mutex_lock(&vme_buses_lock); for (i = 0; i < sizeof(vme_bus_numbers) * 8; i++) { - if (((vme_bus_numbers >> i) & 0x1) == 0) { - vme_bus_numbers |= (0x1 << i); + if ((vme_bus_numbers & (1 << i)) == 0) { + vme_bus_numbers |= (1 << i); + bridge->num = i; + list_add_tail(&bridge->bus_list, &vme_bus_list); + ret = 0; break; } } - mutex_unlock(&vme_bus_num_mtx); + mutex_unlock(&vme_buses_lock); - return i; + return ret; } -static void vme_free_bus_num(int bus) +static void vme_remove_bus(struct vme_bridge *bridge) { - mutex_lock(&vme_bus_num_mtx); - vme_bus_numbers &= ~(0x1 << bus); - mutex_unlock(&vme_bus_num_mtx); + mutex_lock(&vme_buses_lock); + vme_bus_numbers &= ~(1 << bridge->num); + list_del(&bridge->bus_list); + mutex_unlock(&vme_buses_lock); } int vme_register_bridge(struct vme_bridge *bridge) @@ -1338,7 +1344,9 @@ int vme_register_bridge(struct vme_bridge *bridge) int retval; int i; - bridge->num = vme_alloc_bus_num(); + retval = vme_add_bus(bridge); + if (retval) + return retval; /* This creates 32 vme "slot" devices. This equates to a slot for each * ID available in a system conforming to the ANSI/VITA 1-1994 @@ -1370,7 +1378,7 @@ err_reg: dev = &bridge->dev[i]; device_unregister(dev); } - vme_free_bus_num(bridge->num); + vme_remove_bus(bridge); return retval; } EXPORT_SYMBOL(vme_register_bridge); @@ -1385,7 +1393,7 @@ void vme_unregister_bridge(struct vme_bridge *bridge) dev = &bridge->dev[i]; device_unregister(dev); } - vme_free_bus_num(bridge->num); + vme_remove_bus(bridge); } EXPORT_SYMBOL(vme_unregister_bridge); diff --git a/drivers/staging/vme/vme_bridge.h b/drivers/staging/vme/vme_bridge.h index a9084f0f34e7..895967058297 100644 --- a/drivers/staging/vme/vme_bridge.h +++ b/drivers/staging/vme/vme_bridge.h @@ -112,6 +112,7 @@ struct vme_bridge { /* Bridge Info - XXX Move to private structure? */ struct device *parent; /* Parent device (eg. pdev->dev for PCI) */ void *driver_priv; /* Private pointer for the bridge driver */ + struct list_head bus_list; /* list of VME buses */ struct device dev[VME_SLOTS_MAX]; /* Device registered with * device model on VME bus