USB: cxacru: create sysfs attributes in atm_start instead of bind

Since usbatm doesn't set the usb_interface driver data until after calling
bind and heavy_init, it would be NULL when the sysfs attributes are read.
Reading the MAC address from atm_dev before atm_dev exists would have been
be possible too.

Calling create_device_file in atm_start will avoid this problem, and the
data is useless until the first status poll runs.  However, it must be
ready before a status poll does a printk on line status change otherwise
userspace could react before the files exist.

For completeness I've moved remove_device_file to atm_stop so it's not
called in unbind when it's not needed.  There's no point starting ADSL if
atm_start could still fail either.

Signed-off-by: Simon Arlott <simon@fire.lp0.eu>
Cc: Duncan Sands <duncan.sands@math.u-psud.fr>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Simon Arlott 2007-05-10 23:04:12 -07:00 committed by Greg Kroah-Hartman
parent 64b85006f5
commit da1f82b554

View File

@ -629,10 +629,22 @@ static int cxacru_card_status(struct cxacru_data *instance)
return 0; return 0;
} }
static void cxacru_remove_device_files(struct usbatm_data *usbatm_instance,
struct atm_dev *atm_dev)
{
struct usb_interface *intf = usbatm_instance->usb_intf;
#define CXACRU_DEVICE_REMOVE_FILE(_name) \
device_remove_file(&intf->dev, &dev_attr_##_name);
CXACRU_ALL_FILES(REMOVE);
#undef CXACRU_DEVICE_REMOVE_FILE
}
static int cxacru_atm_start(struct usbatm_data *usbatm_instance, static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
struct atm_dev *atm_dev) struct atm_dev *atm_dev)
{ {
struct cxacru_data *instance = usbatm_instance->driver_data; struct cxacru_data *instance = usbatm_instance->driver_data;
struct usb_interface *intf = usbatm_instance->usb_intf;
/* /*
struct atm_dev *atm_dev = usbatm_instance->atm_dev; struct atm_dev *atm_dev = usbatm_instance->atm_dev;
*/ */
@ -649,6 +661,13 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
return ret; return ret;
} }
#define CXACRU_DEVICE_CREATE_FILE(_name) \
ret = device_create_file(&intf->dev, &dev_attr_##_name); \
if (unlikely(ret)) \
goto fail_sysfs;
CXACRU_ALL_FILES(CREATE);
#undef CXACRU_DEVICE_CREATE_FILE
/* start ADSL */ /* start ADSL */
mutex_lock(&instance->adsl_state_serialize); mutex_lock(&instance->adsl_state_serialize);
ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_START, NULL, 0, NULL, 0); ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_START, NULL, 0, NULL, 0);
@ -680,6 +699,11 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
if (start_polling) if (start_polling)
cxacru_poll_status(&instance->poll_work.work); cxacru_poll_status(&instance->poll_work.work);
return 0; return 0;
fail_sysfs:
usb_err(usbatm_instance, "cxacru_atm_start: device_create_file failed (%d)\n", ret);
cxacru_remove_device_files(usbatm_instance, atm_dev);
return ret;
} }
static void cxacru_poll_status(struct work_struct *work) static void cxacru_poll_status(struct work_struct *work)
@ -1065,13 +1089,6 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance,
goto fail; goto fail;
} }
#define CXACRU_DEVICE_CREATE_FILE(_name) \
ret = device_create_file(&intf->dev, &dev_attr_##_name); \
if (unlikely(ret)) \
goto fail_sysfs;
CXACRU_ALL_FILES(CREATE);
#undef CXACRU_DEVICE_CREATE_FILE
usb_fill_int_urb(instance->rcv_urb, usb_fill_int_urb(instance->rcv_urb,
usb_dev, usb_rcvintpipe(usb_dev, CXACRU_EP_CMD), usb_dev, usb_rcvintpipe(usb_dev, CXACRU_EP_CMD),
instance->rcv_buf, PAGE_SIZE, instance->rcv_buf, PAGE_SIZE,
@ -1092,14 +1109,6 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance,
return 0; return 0;
fail_sysfs:
dbg("cxacru_bind: device_create_file failed (%d)\n", ret);
#define CXACRU_DEVICE_REMOVE_FILE(_name) \
device_remove_file(&intf->dev, &dev_attr_##_name);
CXACRU_ALL_FILES(REMOVE);
#undef CXACRU_DEVICE_REVOVE_FILE
fail: fail:
free_page((unsigned long) instance->snd_buf); free_page((unsigned long) instance->snd_buf);
free_page((unsigned long) instance->rcv_buf); free_page((unsigned long) instance->rcv_buf);
@ -1146,11 +1155,6 @@ static void cxacru_unbind(struct usbatm_data *usbatm_instance,
free_page((unsigned long) instance->snd_buf); free_page((unsigned long) instance->snd_buf);
free_page((unsigned long) instance->rcv_buf); free_page((unsigned long) instance->rcv_buf);
#define CXACRU_DEVICE_REMOVE_FILE(_name) \
device_remove_file(&intf->dev, &dev_attr_##_name);
CXACRU_ALL_FILES(REMOVE);
#undef CXACRU_DEVICE_REVOVE_FILE
kfree(instance); kfree(instance);
usbatm_instance->driver_data = NULL; usbatm_instance->driver_data = NULL;
@ -1231,6 +1235,7 @@ static struct usbatm_driver cxacru_driver = {
.heavy_init = cxacru_heavy_init, .heavy_init = cxacru_heavy_init,
.unbind = cxacru_unbind, .unbind = cxacru_unbind,
.atm_start = cxacru_atm_start, .atm_start = cxacru_atm_start,
.atm_stop = cxacru_remove_device_files,
.bulk_in = CXACRU_EP_DATA, .bulk_in = CXACRU_EP_DATA,
.bulk_out = CXACRU_EP_DATA, .bulk_out = CXACRU_EP_DATA,
.rx_padding = 3, .rx_padding = 3,