diff options
| author | Simon Arlott <simon@fire.lp0.eu> | 2007-05-11 02:04:12 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-06-08 19:24:31 -0400 |
| commit | da1f82b5543738d4c127a449490bc0d55e121fe8 (patch) | |
| tree | 88562272ac2a5a28f682eee1f44272890f42db52 | |
| parent | 64b85006f5d473fefc181dece9473710b55966e0 (diff) | |
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>
| -rw-r--r-- | drivers/usb/atm/cxacru.c | 45 |
1 files changed, 25 insertions, 20 deletions
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index 30b7bfbc985a..68cf582fd4fa 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c | |||
| @@ -629,10 +629,22 @@ static int cxacru_card_status(struct cxacru_data *instance) | |||
| 629 | return 0; | 629 | return 0; |
| 630 | } | 630 | } |
| 631 | 631 | ||
| 632 | static void cxacru_remove_device_files(struct usbatm_data *usbatm_instance, | ||
| 633 | struct atm_dev *atm_dev) | ||
| 634 | { | ||
| 635 | struct usb_interface *intf = usbatm_instance->usb_intf; | ||
| 636 | |||
| 637 | #define CXACRU_DEVICE_REMOVE_FILE(_name) \ | ||
| 638 | device_remove_file(&intf->dev, &dev_attr_##_name); | ||
| 639 | CXACRU_ALL_FILES(REMOVE); | ||
| 640 | #undef CXACRU_DEVICE_REMOVE_FILE | ||
| 641 | } | ||
| 642 | |||
| 632 | static int cxacru_atm_start(struct usbatm_data *usbatm_instance, | 643 | static int cxacru_atm_start(struct usbatm_data *usbatm_instance, |
| 633 | struct atm_dev *atm_dev) | 644 | struct atm_dev *atm_dev) |
| 634 | { | 645 | { |
| 635 | struct cxacru_data *instance = usbatm_instance->driver_data; | 646 | struct cxacru_data *instance = usbatm_instance->driver_data; |
| 647 | struct usb_interface *intf = usbatm_instance->usb_intf; | ||
| 636 | /* | 648 | /* |
| 637 | struct atm_dev *atm_dev = usbatm_instance->atm_dev; | 649 | struct atm_dev *atm_dev = usbatm_instance->atm_dev; |
| 638 | */ | 650 | */ |
| @@ -649,6 +661,13 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance, | |||
| 649 | return ret; | 661 | return ret; |
| 650 | } | 662 | } |
| 651 | 663 | ||
| 664 | #define CXACRU_DEVICE_CREATE_FILE(_name) \ | ||
| 665 | ret = device_create_file(&intf->dev, &dev_attr_##_name); \ | ||
| 666 | if (unlikely(ret)) \ | ||
| 667 | goto fail_sysfs; | ||
| 668 | CXACRU_ALL_FILES(CREATE); | ||
| 669 | #undef CXACRU_DEVICE_CREATE_FILE | ||
| 670 | |||
| 652 | /* start ADSL */ | 671 | /* start ADSL */ |
| 653 | mutex_lock(&instance->adsl_state_serialize); | 672 | mutex_lock(&instance->adsl_state_serialize); |
| 654 | ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_START, NULL, 0, NULL, 0); | 673 | 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, | |||
| 680 | if (start_polling) | 699 | if (start_polling) |
| 681 | cxacru_poll_status(&instance->poll_work.work); | 700 | cxacru_poll_status(&instance->poll_work.work); |
| 682 | return 0; | 701 | return 0; |
| 702 | |||
| 703 | fail_sysfs: | ||
| 704 | usb_err(usbatm_instance, "cxacru_atm_start: device_create_file failed (%d)\n", ret); | ||
| 705 | cxacru_remove_device_files(usbatm_instance, atm_dev); | ||
| 706 | return ret; | ||
| 683 | } | 707 | } |
| 684 | 708 | ||
| 685 | static void cxacru_poll_status(struct work_struct *work) | 709 | static void cxacru_poll_status(struct work_struct *work) |
| @@ -1065,13 +1089,6 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance, | |||
| 1065 | goto fail; | 1089 | goto fail; |
| 1066 | } | 1090 | } |
| 1067 | 1091 | ||
| 1068 | #define CXACRU_DEVICE_CREATE_FILE(_name) \ | ||
| 1069 | ret = device_create_file(&intf->dev, &dev_attr_##_name); \ | ||
| 1070 | if (unlikely(ret)) \ | ||
| 1071 | goto fail_sysfs; | ||
| 1072 | CXACRU_ALL_FILES(CREATE); | ||
| 1073 | #undef CXACRU_DEVICE_CREATE_FILE | ||
| 1074 | |||
| 1075 | usb_fill_int_urb(instance->rcv_urb, | 1092 | usb_fill_int_urb(instance->rcv_urb, |
| 1076 | usb_dev, usb_rcvintpipe(usb_dev, CXACRU_EP_CMD), | 1093 | usb_dev, usb_rcvintpipe(usb_dev, CXACRU_EP_CMD), |
| 1077 | instance->rcv_buf, PAGE_SIZE, | 1094 | instance->rcv_buf, PAGE_SIZE, |
| @@ -1092,14 +1109,6 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance, | |||
| 1092 | 1109 | ||
| 1093 | return 0; | 1110 | return 0; |
| 1094 | 1111 | ||
| 1095 | fail_sysfs: | ||
| 1096 | dbg("cxacru_bind: device_create_file failed (%d)\n", ret); | ||
| 1097 | |||
| 1098 | #define CXACRU_DEVICE_REMOVE_FILE(_name) \ | ||
| 1099 | device_remove_file(&intf->dev, &dev_attr_##_name); | ||
| 1100 | CXACRU_ALL_FILES(REMOVE); | ||
| 1101 | #undef CXACRU_DEVICE_REVOVE_FILE | ||
| 1102 | |||
| 1103 | fail: | 1112 | fail: |
| 1104 | free_page((unsigned long) instance->snd_buf); | 1113 | free_page((unsigned long) instance->snd_buf); |
| 1105 | free_page((unsigned long) instance->rcv_buf); | 1114 | free_page((unsigned long) instance->rcv_buf); |
| @@ -1146,11 +1155,6 @@ static void cxacru_unbind(struct usbatm_data *usbatm_instance, | |||
| 1146 | free_page((unsigned long) instance->snd_buf); | 1155 | free_page((unsigned long) instance->snd_buf); |
| 1147 | free_page((unsigned long) instance->rcv_buf); | 1156 | free_page((unsigned long) instance->rcv_buf); |
| 1148 | 1157 | ||
| 1149 | #define CXACRU_DEVICE_REMOVE_FILE(_name) \ | ||
| 1150 | device_remove_file(&intf->dev, &dev_attr_##_name); | ||
| 1151 | CXACRU_ALL_FILES(REMOVE); | ||
| 1152 | #undef CXACRU_DEVICE_REVOVE_FILE | ||
| 1153 | |||
| 1154 | kfree(instance); | 1158 | kfree(instance); |
| 1155 | 1159 | ||
| 1156 | usbatm_instance->driver_data = NULL; | 1160 | usbatm_instance->driver_data = NULL; |
| @@ -1231,6 +1235,7 @@ static struct usbatm_driver cxacru_driver = { | |||
| 1231 | .heavy_init = cxacru_heavy_init, | 1235 | .heavy_init = cxacru_heavy_init, |
| 1232 | .unbind = cxacru_unbind, | 1236 | .unbind = cxacru_unbind, |
| 1233 | .atm_start = cxacru_atm_start, | 1237 | .atm_start = cxacru_atm_start, |
| 1238 | .atm_stop = cxacru_remove_device_files, | ||
| 1234 | .bulk_in = CXACRU_EP_DATA, | 1239 | .bulk_in = CXACRU_EP_DATA, |
| 1235 | .bulk_out = CXACRU_EP_DATA, | 1240 | .bulk_out = CXACRU_EP_DATA, |
| 1236 | .rx_padding = 3, | 1241 | .rx_padding = 3, |
