Commit c0cebfa4 authored by Duncan Sands's avatar Duncan Sands Committed by Greg Kroah-Hartman

[PATCH] USB: turn speedtouch micro race into a nano race

  speedtouch: turn a micro race into a nano race.  The race is that an ATM device can
  be used the moment atm_dev_register returns, but you only get to fill out the
  atm_dev structure after atm_dev_register returns (this is a design flaw in the
  ATM layer).  Thus there is a small window during which you can be called with an
  incompletely set up data structure.  Workaround this by causing all ATM callbacks
  to fail if the dev_data field has not been set.  There is still a nano race if
  writing/reading the dev_data field is not atomic.  Is it atomic on all architectures?
parent 652c510a
......@@ -257,11 +257,16 @@ static struct sk_buff *udsl_atm_alloc_tx (struct atm_vcc *vcc, unsigned int size
return NULL;
}
static int udsl_atm_proc_read (struct atm_dev *atm_dev, loff_t * pos, char *page)
static int udsl_atm_proc_read (struct atm_dev *atm_dev, loff_t *pos, char *page)
{
struct udsl_instance_data *instance = atm_dev->dev_data;
int left = *pos;
if (!instance) {
PDEBUG ("NULL instance!\n");
return -ENODEV;
}
if (!left--)
return sprintf (page, "SpeedTouch USB %s-%s (%02x:%02x:%02x:%02x:%02x:%02x)\n",
instance->usb_dev->bus->bus_name, instance->usb_dev->devpath,
......@@ -302,8 +307,10 @@ static int udsl_atm_send (struct atm_vcc *vcc, struct sk_buff *skb)
PDEBUG ("udsl_atm_send called\n");
if (!dev_data)
if (!dev_data || !instance) {
PDEBUG ("NULL data!\n");
return -EINVAL;
}
switch (vcc->qos.aal) {
case ATM_AAL5:
......@@ -403,6 +410,11 @@ static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci)
PDEBUG ("udsl_atm_open called\n");
if (!instance) {
PDEBUG ("NULL instance!\n");
return -ENODEV;
}
/* at the moment only AAL5 support */
if (vcc->qos.aal != ATM_AAL5)
return -EINVAL;
......@@ -441,6 +453,11 @@ static void udsl_atm_close (struct atm_vcc *vcc)
PDEBUG ("udsl_atm_close called\n");
if (!dev_data || !instance) {
PDEBUG ("NULL data!\n");
return;
}
/* freeing resources */
/* cancel all sends on this vcc */
udsl_usb_cancelsends (instance, vcc);
......@@ -832,7 +849,6 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i
goto fail_atm;
}
instance->atm_dev->dev_data = instance;
instance->atm_dev->ci_range.vpi_bits = ATM_CI_MAX;
instance->atm_dev->ci_range.vci_bits = ATM_CI_MAX;
instance->atm_dev->signal = ATM_PHY_SIG_LOST;
......@@ -849,6 +865,10 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i
memcpy (instance->atm_dev->esi, mac, 6);
wmb ();
instance->atm_dev->dev_data = instance;
usb_set_intfdata (intf, instance);
return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment