aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/atm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/atm')
-rw-r--r--drivers/usb/atm/cxacru.c411
-rw-r--r--drivers/usb/atm/ueagle-atm.c1
-rw-r--r--drivers/usb/atm/usbatm.c27
3 files changed, 423 insertions, 16 deletions
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
index 3dfa3e40e148..30b7bfbc985a 100644
--- a/drivers/usb/atm/cxacru.c
+++ b/drivers/usb/atm/cxacru.c
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (C) 2004 David Woodhouse, Duncan Sands, Roman Kagan 5 * Copyright (C) 2004 David Woodhouse, Duncan Sands, Roman Kagan
6 * Copyright (C) 2005 Duncan Sands, Roman Kagan (rkagan % mail ! ru) 6 * Copyright (C) 2005 Duncan Sands, Roman Kagan (rkagan % mail ! ru)
7 * Copyright (C) 2007 Simon Arlott
7 * 8 *
8 * This program is free software; you can redistribute it and/or modify it 9 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free 10 * under the terms of the GNU General Public License as published by the Free
@@ -34,14 +35,14 @@
34#include <linux/errno.h> 35#include <linux/errno.h>
35#include <linux/slab.h> 36#include <linux/slab.h>
36#include <linux/init.h> 37#include <linux/init.h>
37#include <linux/device.h> /* FIXME: linux/firmware.h should include it itself */ 38#include <linux/device.h>
38#include <linux/firmware.h> 39#include <linux/firmware.h>
39#include <linux/mutex.h> 40#include <linux/mutex.h>
40 41
41#include "usbatm.h" 42#include "usbatm.h"
42 43
43#define DRIVER_AUTHOR "Roman Kagan, David Woodhouse, Duncan Sands" 44#define DRIVER_AUTHOR "Roman Kagan, David Woodhouse, Duncan Sands, Simon Arlott"
44#define DRIVER_VERSION "0.2" 45#define DRIVER_VERSION "0.3"
45#define DRIVER_DESC "Conexant AccessRunner ADSL USB modem driver" 46#define DRIVER_DESC "Conexant AccessRunner ADSL USB modem driver"
46 47
47static const char cxacru_driver_name[] = "cxacru"; 48static const char cxacru_driver_name[] = "cxacru";
@@ -64,7 +65,7 @@ static const char cxacru_driver_name[] = "cxacru";
64#define SDRAM_ENA 0x1 65#define SDRAM_ENA 0x1
65 66
66#define CMD_TIMEOUT 2000 /* msecs */ 67#define CMD_TIMEOUT 2000 /* msecs */
67#define POLL_INTERVAL 5000 /* msecs */ 68#define POLL_INTERVAL 1 /* secs */
68 69
69/* commands for interaction with the modem through the control channel before 70/* commands for interaction with the modem through the control channel before
70 * firmware is loaded */ 71 * firmware is loaded */
@@ -146,6 +147,13 @@ enum cxacru_info_idx {
146 CXINF_MAX = 0x1c, 147 CXINF_MAX = 0x1c,
147}; 148};
148 149
150enum cxacru_poll_state {
151 CXPOLL_STOPPING,
152 CXPOLL_STOPPED,
153 CXPOLL_POLLING,
154 CXPOLL_SHUTDOWN
155};
156
149struct cxacru_modem_type { 157struct cxacru_modem_type {
150 u32 pll_f_clk; 158 u32 pll_f_clk;
151 u32 pll_b_clk; 159 u32 pll_b_clk;
@@ -158,7 +166,12 @@ struct cxacru_data {
158 const struct cxacru_modem_type *modem_type; 166 const struct cxacru_modem_type *modem_type;
159 167
160 int line_status; 168 int line_status;
169 struct mutex adsl_state_serialize;
170 int adsl_status;
161 struct delayed_work poll_work; 171 struct delayed_work poll_work;
172 u32 card_info[CXINF_MAX];
173 struct mutex poll_state_serialize;
174 int poll_state;
162 175
163 /* contol handles */ 176 /* contol handles */
164 struct mutex cm_serialize; 177 struct mutex cm_serialize;
@@ -170,6 +183,275 @@ struct cxacru_data {
170 struct completion snd_done; 183 struct completion snd_done;
171}; 184};
172 185
186static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm,
187 u8 *wdata, int wsize, u8 *rdata, int rsize);
188static void cxacru_poll_status(struct work_struct *work);
189
190/* Card info exported through sysfs */
191#define CXACRU__ATTR_INIT(_name) \
192static DEVICE_ATTR(_name, S_IRUGO, cxacru_sysfs_show_##_name, NULL)
193
194#define CXACRU_CMD_INIT(_name) \
195static DEVICE_ATTR(_name, S_IWUSR | S_IRUGO, \
196 cxacru_sysfs_show_##_name, cxacru_sysfs_store_##_name)
197
198#define CXACRU_ATTR_INIT(_value, _type, _name) \
199static ssize_t cxacru_sysfs_show_##_name(struct device *dev, \
200 struct device_attribute *attr, char *buf) \
201{ \
202 struct usb_interface *intf = to_usb_interface(dev); \
203 struct usbatm_data *usbatm_instance = usb_get_intfdata(intf); \
204 struct cxacru_data *instance = usbatm_instance->driver_data; \
205 return cxacru_sysfs_showattr_##_type(instance->card_info[_value], buf); \
206} \
207CXACRU__ATTR_INIT(_name)
208
209#define CXACRU_ATTR_CREATE(_v, _t, _name) CXACRU_DEVICE_CREATE_FILE(_name)
210#define CXACRU_CMD_CREATE(_name) CXACRU_DEVICE_CREATE_FILE(_name)
211#define CXACRU__ATTR_CREATE(_name) CXACRU_DEVICE_CREATE_FILE(_name)
212
213#define CXACRU_ATTR_REMOVE(_v, _t, _name) CXACRU_DEVICE_REMOVE_FILE(_name)
214#define CXACRU_CMD_REMOVE(_name) CXACRU_DEVICE_REMOVE_FILE(_name)
215#define CXACRU__ATTR_REMOVE(_name) CXACRU_DEVICE_REMOVE_FILE(_name)
216
217static ssize_t cxacru_sysfs_showattr_u32(u32 value, char *buf)
218{
219 return snprintf(buf, PAGE_SIZE, "%u\n", value);
220}
221
222static ssize_t cxacru_sysfs_showattr_s8(s8 value, char *buf)
223{
224 return snprintf(buf, PAGE_SIZE, "%d\n", value);
225}
226
227static ssize_t cxacru_sysfs_showattr_dB(s16 value, char *buf)
228{
229 if (unlikely(value < 0)) {
230 return snprintf(buf, PAGE_SIZE, "%d.%02u\n",
231 value / 100, -value % 100);
232 } else {
233 return snprintf(buf, PAGE_SIZE, "%d.%02u\n",
234 value / 100, value % 100);
235 }
236}
237
238static ssize_t cxacru_sysfs_showattr_bool(u32 value, char *buf)
239{
240 switch (value) {
241 case 0: return snprintf(buf, PAGE_SIZE, "no\n");
242 case 1: return snprintf(buf, PAGE_SIZE, "yes\n");
243 default: return 0;
244 }
245}
246
247static ssize_t cxacru_sysfs_showattr_LINK(u32 value, char *buf)
248{
249 switch (value) {
250 case 1: return snprintf(buf, PAGE_SIZE, "not connected\n");
251 case 2: return snprintf(buf, PAGE_SIZE, "connected\n");
252 case 3: return snprintf(buf, PAGE_SIZE, "lost\n");
253 default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value);
254 }
255}
256
257static ssize_t cxacru_sysfs_showattr_LINE(u32 value, char *buf)
258{
259 switch (value) {
260 case 0: return snprintf(buf, PAGE_SIZE, "down\n");
261 case 1: return snprintf(buf, PAGE_SIZE, "attempting to activate\n");
262 case 2: return snprintf(buf, PAGE_SIZE, "training\n");
263 case 3: return snprintf(buf, PAGE_SIZE, "channel analysis\n");
264 case 4: return snprintf(buf, PAGE_SIZE, "exchange\n");
265 case 5: return snprintf(buf, PAGE_SIZE, "up\n");
266 case 6: return snprintf(buf, PAGE_SIZE, "waiting\n");
267 case 7: return snprintf(buf, PAGE_SIZE, "initialising\n");
268 default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value);
269 }
270}
271
272static ssize_t cxacru_sysfs_showattr_MODU(u32 value, char *buf)
273{
274 switch (value) {
275 case 0: return 0;
276 case 1: return snprintf(buf, PAGE_SIZE, "ANSI T1.413\n");
277 case 2: return snprintf(buf, PAGE_SIZE, "ITU-T G.992.1 (G.DMT)\n");
278 case 3: return snprintf(buf, PAGE_SIZE, "ITU-T G.992.2 (G.LITE)\n");
279 default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value);
280 }
281}
282
283/*
284 * This could use MAC_ADDRESS_HIGH and MAC_ADDRESS_LOW, but since
285 * this data is already in atm_dev there's no point.
286 *
287 * MAC_ADDRESS_HIGH = 0x????5544
288 * MAC_ADDRESS_LOW = 0x33221100
289 * Where 00-55 are bytes 0-5 of the MAC.
290 */
291static ssize_t cxacru_sysfs_show_mac_address(struct device *dev,
292 struct device_attribute *attr, char *buf)
293{
294 struct usb_interface *intf = to_usb_interface(dev);
295 struct usbatm_data *usbatm_instance = usb_get_intfdata(intf);
296 struct atm_dev *atm_dev = usbatm_instance->atm_dev;
297
298 return snprintf(buf, PAGE_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x\n",
299 atm_dev->esi[0], atm_dev->esi[1], atm_dev->esi[2],
300 atm_dev->esi[3], atm_dev->esi[4], atm_dev->esi[5]);
301}
302
303static ssize_t cxacru_sysfs_show_adsl_state(struct device *dev,
304 struct device_attribute *attr, char *buf)
305{
306 struct usb_interface *intf = to_usb_interface(dev);
307 struct usbatm_data *usbatm_instance = usb_get_intfdata(intf);
308 struct cxacru_data *instance = usbatm_instance->driver_data;
309 u32 value = instance->card_info[CXINF_LINE_STARTABLE];
310
311 switch (value) {
312 case 0: return snprintf(buf, PAGE_SIZE, "running\n");
313 case 1: return snprintf(buf, PAGE_SIZE, "stopped\n");
314 default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value);
315 }
316}
317
318static ssize_t cxacru_sysfs_store_adsl_state(struct device *dev,
319 struct device_attribute *attr, const char *buf, size_t count)
320{
321 struct usb_interface *intf = to_usb_interface(dev);
322 struct usbatm_data *usbatm_instance = usb_get_intfdata(intf);
323 struct cxacru_data *instance = usbatm_instance->driver_data;
324 int ret;
325 int poll = -1;
326 char str_cmd[8];
327 int len = strlen(buf);
328
329 if (!capable(CAP_NET_ADMIN))
330 return -EACCES;
331
332 ret = sscanf(buf, "%7s", str_cmd);
333 if (ret != 1)
334 return -EINVAL;
335 ret = 0;
336
337 if (mutex_lock_interruptible(&instance->adsl_state_serialize))
338 return -ERESTARTSYS;
339
340 if (!strcmp(str_cmd, "stop") || !strcmp(str_cmd, "restart")) {
341 ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_STOP, NULL, 0, NULL, 0);
342 if (ret < 0) {
343 atm_err(usbatm_instance, "change adsl state:"
344 " CHIP_ADSL_LINE_STOP returned %d\n", ret);
345
346 ret = -EIO;
347 } else {
348 ret = len;
349 poll = CXPOLL_STOPPED;
350 }
351 }
352
353 /* Line status is only updated every second
354 * and the device appears to only react to
355 * START/STOP every second too. Wait 1.5s to
356 * be sure that restart will have an effect. */
357 if (!strcmp(str_cmd, "restart"))
358 msleep(1500);
359
360 if (!strcmp(str_cmd, "start") || !strcmp(str_cmd, "restart")) {
361 ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_START, NULL, 0, NULL, 0);
362 if (ret < 0) {
363 atm_err(usbatm_instance, "change adsl state:"
364 " CHIP_ADSL_LINE_START returned %d\n", ret);
365
366 ret = -EIO;
367 } else {
368 ret = len;
369 poll = CXPOLL_POLLING;
370 }
371 }
372
373 if (!strcmp(str_cmd, "poll")) {
374 ret = len;
375 poll = CXPOLL_POLLING;
376 }
377
378 if (ret == 0) {
379 ret = -EINVAL;
380 poll = -1;
381 }
382
383 if (poll == CXPOLL_POLLING) {
384 mutex_lock(&instance->poll_state_serialize);
385 switch (instance->poll_state) {
386 case CXPOLL_STOPPED:
387 /* start polling */
388 instance->poll_state = CXPOLL_POLLING;
389 break;
390
391 case CXPOLL_STOPPING:
392 /* abort stop request */
393 instance->poll_state = CXPOLL_POLLING;
394 case CXPOLL_POLLING:
395 case CXPOLL_SHUTDOWN:
396 /* don't start polling */
397 poll = -1;
398 }
399 mutex_unlock(&instance->poll_state_serialize);
400 } else if (poll == CXPOLL_STOPPED) {
401 mutex_lock(&instance->poll_state_serialize);
402 /* request stop */
403 if (instance->poll_state == CXPOLL_POLLING)
404 instance->poll_state = CXPOLL_STOPPING;
405 mutex_unlock(&instance->poll_state_serialize);
406 }
407
408 mutex_unlock(&instance->adsl_state_serialize);
409
410 if (poll == CXPOLL_POLLING)
411 cxacru_poll_status(&instance->poll_work.work);
412
413 return ret;
414}
415
416/*
417 * All device attributes are included in CXACRU_ALL_FILES
418 * so that the same list can be used multiple times:
419 * INIT (define the device attributes)
420 * CREATE (create all the device files)
421 * REMOVE (remove all the device files)
422 *
423 * With the last two being defined as needed in the functions
424 * they are used in before calling CXACRU_ALL_FILES()
425 */
426#define CXACRU_ALL_FILES(_action) \
427CXACRU_ATTR_##_action(CXINF_DOWNSTREAM_RATE, u32, downstream_rate); \
428CXACRU_ATTR_##_action(CXINF_UPSTREAM_RATE, u32, upstream_rate); \
429CXACRU_ATTR_##_action(CXINF_LINK_STATUS, LINK, link_status); \
430CXACRU_ATTR_##_action(CXINF_LINE_STATUS, LINE, line_status); \
431CXACRU__ATTR_##_action( mac_address); \
432CXACRU_ATTR_##_action(CXINF_UPSTREAM_SNR_MARGIN, dB, upstream_snr_margin); \
433CXACRU_ATTR_##_action(CXINF_DOWNSTREAM_SNR_MARGIN, dB, downstream_snr_margin); \
434CXACRU_ATTR_##_action(CXINF_UPSTREAM_ATTENUATION, dB, upstream_attenuation); \
435CXACRU_ATTR_##_action(CXINF_DOWNSTREAM_ATTENUATION, dB, downstream_attenuation); \
436CXACRU_ATTR_##_action(CXINF_TRANSMITTER_POWER, s8, transmitter_power); \
437CXACRU_ATTR_##_action(CXINF_UPSTREAM_BITS_PER_FRAME, u32, upstream_bits_per_frame); \
438CXACRU_ATTR_##_action(CXINF_DOWNSTREAM_BITS_PER_FRAME, u32, downstream_bits_per_frame); \
439CXACRU_ATTR_##_action(CXINF_STARTUP_ATTEMPTS, u32, startup_attempts); \
440CXACRU_ATTR_##_action(CXINF_UPSTREAM_CRC_ERRORS, u32, upstream_crc_errors); \
441CXACRU_ATTR_##_action(CXINF_DOWNSTREAM_CRC_ERRORS, u32, downstream_crc_errors); \
442CXACRU_ATTR_##_action(CXINF_UPSTREAM_FEC_ERRORS, u32, upstream_fec_errors); \
443CXACRU_ATTR_##_action(CXINF_DOWNSTREAM_FEC_ERRORS, u32, downstream_fec_errors); \
444CXACRU_ATTR_##_action(CXINF_UPSTREAM_HEC_ERRORS, u32, upstream_hec_errors); \
445CXACRU_ATTR_##_action(CXINF_DOWNSTREAM_HEC_ERRORS, u32, downstream_hec_errors); \
446CXACRU_ATTR_##_action(CXINF_LINE_STARTABLE, bool, line_startable); \
447CXACRU_ATTR_##_action(CXINF_MODULATION, MODU, modulation); \
448CXACRU_ATTR_##_action(CXINF_ADSL_HEADEND, u32, adsl_headend); \
449CXACRU_ATTR_##_action(CXINF_ADSL_HEADEND_ENVIRONMENT, u32, adsl_headend_environment); \
450CXACRU_ATTR_##_action(CXINF_CONTROLLER_VERSION, u32, adsl_controller_version); \
451CXACRU_CMD_##_action( adsl_state);
452
453CXACRU_ALL_FILES(INIT);
454
173/* the following three functions are stolen from drivers/usb/core/message.c */ 455/* the following three functions are stolen from drivers/usb/core/message.c */
174static void cxacru_blocking_completion(struct urb *urb) 456static void cxacru_blocking_completion(struct urb *urb)
175{ 457{
@@ -347,8 +629,6 @@ static int cxacru_card_status(struct cxacru_data *instance)
347 return 0; 629 return 0;
348} 630}
349 631
350static void cxacru_poll_status(struct work_struct *work);
351
352static int cxacru_atm_start(struct usbatm_data *usbatm_instance, 632static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
353 struct atm_dev *atm_dev) 633 struct atm_dev *atm_dev)
354{ 634{
@@ -357,6 +637,7 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
357 struct atm_dev *atm_dev = usbatm_instance->atm_dev; 637 struct atm_dev *atm_dev = usbatm_instance->atm_dev;
358 */ 638 */
359 int ret; 639 int ret;
640 int start_polling = 1;
360 641
361 dbg("cxacru_atm_start"); 642 dbg("cxacru_atm_start");
362 643
@@ -369,14 +650,35 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
369 } 650 }
370 651
371 /* start ADSL */ 652 /* start ADSL */
653 mutex_lock(&instance->adsl_state_serialize);
372 ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_START, NULL, 0, NULL, 0); 654 ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_START, NULL, 0, NULL, 0);
373 if (ret < 0) { 655 if (ret < 0) {
374 atm_err(usbatm_instance, "cxacru_atm_start: CHIP_ADSL_LINE_START returned %d\n", ret); 656 atm_err(usbatm_instance, "cxacru_atm_start: CHIP_ADSL_LINE_START returned %d\n", ret);
657 mutex_unlock(&instance->adsl_state_serialize);
375 return ret; 658 return ret;
376 } 659 }
377 660
378 /* Start status polling */ 661 /* Start status polling */
379 cxacru_poll_status(&instance->poll_work.work); 662 mutex_lock(&instance->poll_state_serialize);
663 switch (instance->poll_state) {
664 case CXPOLL_STOPPED:
665 /* start polling */
666 instance->poll_state = CXPOLL_POLLING;
667 break;
668
669 case CXPOLL_STOPPING:
670 /* abort stop request */
671 instance->poll_state = CXPOLL_POLLING;
672 case CXPOLL_POLLING:
673 case CXPOLL_SHUTDOWN:
674 /* don't start polling */
675 start_polling = 0;
676 }
677 mutex_unlock(&instance->poll_state_serialize);
678 mutex_unlock(&instance->adsl_state_serialize);
679
680 if (start_polling)
681 cxacru_poll_status(&instance->poll_work.work);
380 return 0; 682 return 0;
381} 683}
382 684
@@ -387,14 +689,46 @@ static void cxacru_poll_status(struct work_struct *work)
387 u32 buf[CXINF_MAX] = {}; 689 u32 buf[CXINF_MAX] = {};
388 struct usbatm_data *usbatm = instance->usbatm; 690 struct usbatm_data *usbatm = instance->usbatm;
389 struct atm_dev *atm_dev = usbatm->atm_dev; 691 struct atm_dev *atm_dev = usbatm->atm_dev;
692 int keep_polling = 1;
390 int ret; 693 int ret;
391 694
392 ret = cxacru_cm_get_array(instance, CM_REQUEST_CARD_INFO_GET, buf, CXINF_MAX); 695 ret = cxacru_cm_get_array(instance, CM_REQUEST_CARD_INFO_GET, buf, CXINF_MAX);
393 if (ret < 0) { 696 if (ret < 0) {
394 atm_warn(usbatm, "poll status: error %d\n", ret); 697 if (ret != -ESHUTDOWN)
698 atm_warn(usbatm, "poll status: error %d\n", ret);
699
700 mutex_lock(&instance->poll_state_serialize);
701 if (instance->poll_state != CXPOLL_SHUTDOWN) {
702 instance->poll_state = CXPOLL_STOPPED;
703
704 if (ret != -ESHUTDOWN)
705 atm_warn(usbatm, "polling disabled, set adsl_state"
706 " to 'start' or 'poll' to resume\n");
707 }
708 mutex_unlock(&instance->poll_state_serialize);
395 goto reschedule; 709 goto reschedule;
396 } 710 }
397 711
712 memcpy(instance->card_info, buf, sizeof(instance->card_info));
713
714 if (instance->adsl_status != buf[CXINF_LINE_STARTABLE]) {
715 instance->adsl_status = buf[CXINF_LINE_STARTABLE];
716
717 switch (instance->adsl_status) {
718 case 0:
719 atm_printk(KERN_INFO, usbatm, "ADSL state: running\n");
720 break;
721
722 case 1:
723 atm_printk(KERN_INFO, usbatm, "ADSL state: stopped\n");
724 break;
725
726 default:
727 atm_printk(KERN_INFO, usbatm, "Unknown adsl status %02x\n", instance->adsl_status);
728 break;
729 }
730 }
731
398 if (instance->line_status == buf[CXINF_LINE_STATUS]) 732 if (instance->line_status == buf[CXINF_LINE_STATUS])
399 goto reschedule; 733 goto reschedule;
400 734
@@ -449,7 +783,20 @@ static void cxacru_poll_status(struct work_struct *work)
449 break; 783 break;
450 } 784 }
451reschedule: 785reschedule:
452 schedule_delayed_work(&instance->poll_work, msecs_to_jiffies(POLL_INTERVAL)); 786
787 mutex_lock(&instance->poll_state_serialize);
788 if (instance->poll_state == CXPOLL_STOPPING &&
789 instance->adsl_status == 1 && /* stopped */
790 instance->line_status == 0) /* down */
791 instance->poll_state = CXPOLL_STOPPED;
792
793 if (instance->poll_state == CXPOLL_STOPPED)
794 keep_polling = 0;
795 mutex_unlock(&instance->poll_state_serialize);
796
797 if (keep_polling)
798 schedule_delayed_work(&instance->poll_work,
799 round_jiffies_relative(POLL_INTERVAL*HZ));
453} 800}
454 801
455static int cxacru_fw(struct usb_device *usb_dev, enum cxacru_fw_request fw, 802static int cxacru_fw(struct usb_device *usb_dev, enum cxacru_fw_request fw,
@@ -684,6 +1031,14 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance,
684 1031
685 instance->usbatm = usbatm_instance; 1032 instance->usbatm = usbatm_instance;
686 instance->modem_type = (struct cxacru_modem_type *) id->driver_info; 1033 instance->modem_type = (struct cxacru_modem_type *) id->driver_info;
1034 memset(instance->card_info, 0, sizeof(instance->card_info));
1035
1036 mutex_init(&instance->poll_state_serialize);
1037 instance->poll_state = CXPOLL_STOPPED;
1038 instance->line_status = -1;
1039 instance->adsl_status = -1;
1040
1041 mutex_init(&instance->adsl_state_serialize);
687 1042
688 instance->rcv_buf = (u8 *) __get_free_page(GFP_KERNEL); 1043 instance->rcv_buf = (u8 *) __get_free_page(GFP_KERNEL);
689 if (!instance->rcv_buf) { 1044 if (!instance->rcv_buf) {
@@ -710,6 +1065,13 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance,
710 goto fail; 1065 goto fail;
711 } 1066 }
712 1067
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
713 usb_fill_int_urb(instance->rcv_urb, 1075 usb_fill_int_urb(instance->rcv_urb,
714 usb_dev, usb_rcvintpipe(usb_dev, CXACRU_EP_CMD), 1076 usb_dev, usb_rcvintpipe(usb_dev, CXACRU_EP_CMD),
715 instance->rcv_buf, PAGE_SIZE, 1077 instance->rcv_buf, PAGE_SIZE,
@@ -730,6 +1092,14 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance,
730 1092
731 return 0; 1093 return 0;
732 1094
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
733 fail: 1103 fail:
734 free_page((unsigned long) instance->snd_buf); 1104 free_page((unsigned long) instance->snd_buf);
735 free_page((unsigned long) instance->rcv_buf); 1105 free_page((unsigned long) instance->rcv_buf);
@@ -744,6 +1114,7 @@ static void cxacru_unbind(struct usbatm_data *usbatm_instance,
744 struct usb_interface *intf) 1114 struct usb_interface *intf)
745{ 1115{
746 struct cxacru_data *instance = usbatm_instance->driver_data; 1116 struct cxacru_data *instance = usbatm_instance->driver_data;
1117 int is_polling = 1;
747 1118
748 dbg("cxacru_unbind entered"); 1119 dbg("cxacru_unbind entered");
749 1120
@@ -752,8 +1123,20 @@ static void cxacru_unbind(struct usbatm_data *usbatm_instance,
752 return; 1123 return;
753 } 1124 }
754 1125
755 while (!cancel_delayed_work(&instance->poll_work)) 1126 mutex_lock(&instance->poll_state_serialize);
756 flush_scheduled_work(); 1127 BUG_ON(instance->poll_state == CXPOLL_SHUTDOWN);
1128
1129 /* ensure that status polling continues unless
1130 * it has already stopped */
1131 if (instance->poll_state == CXPOLL_STOPPED)
1132 is_polling = 0;
1133
1134 /* stop polling from being stopped or started */
1135 instance->poll_state = CXPOLL_SHUTDOWN;
1136 mutex_unlock(&instance->poll_state_serialize);
1137
1138 if (is_polling)
1139 cancel_rearming_delayed_work(&instance->poll_work);
757 1140
758 usb_kill_urb(instance->snd_urb); 1141 usb_kill_urb(instance->snd_urb);
759 usb_kill_urb(instance->rcv_urb); 1142 usb_kill_urb(instance->rcv_urb);
@@ -762,6 +1145,12 @@ static void cxacru_unbind(struct usbatm_data *usbatm_instance,
762 1145
763 free_page((unsigned long) instance->snd_buf); 1146 free_page((unsigned long) instance->snd_buf);
764 free_page((unsigned long) instance->rcv_buf); 1147 free_page((unsigned long) instance->rcv_buf);
1148
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
765 kfree(instance); 1154 kfree(instance);
766 1155
767 usbatm_instance->driver_data = NULL; 1156 usbatm_instance->driver_data = NULL;
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
index dae4ef1e8fe5..4973e147bc79 100644
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -61,6 +61,7 @@
61#include <linux/usb.h> 61#include <linux/usb.h>
62#include <linux/firmware.h> 62#include <linux/firmware.h>
63#include <linux/ctype.h> 63#include <linux/ctype.h>
64#include <linux/sched.h>
64#include <linux/kthread.h> 65#include <linux/kthread.h>
65#include <linux/version.h> 66#include <linux/version.h>
66#include <linux/mutex.h> 67#include <linux/mutex.h>
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
index ec63b0ee0743..b3f779f5933a 100644
--- a/drivers/usb/atm/usbatm.c
+++ b/drivers/usb/atm/usbatm.c
@@ -274,6 +274,9 @@ static void usbatm_complete(struct urb *urb)
274 (!(channel->usbatm->flags & UDSL_IGNORE_EILSEQ) || 274 (!(channel->usbatm->flags & UDSL_IGNORE_EILSEQ) ||
275 urb->status != -EILSEQ )) 275 urb->status != -EILSEQ ))
276 { 276 {
277 if (urb->status == -ESHUTDOWN)
278 return;
279
277 if (printk_ratelimit()) 280 if (printk_ratelimit())
278 atm_warn(channel->usbatm, "%s: urb 0x%p failed (%d)!\n", 281 atm_warn(channel->usbatm, "%s: urb 0x%p failed (%d)!\n",
279 __func__, urb, urb->status); 282 __func__, urb, urb->status);
@@ -343,7 +346,7 @@ static void usbatm_extract_one_cell(struct usbatm_data *instance, unsigned char
343 UDSL_ASSERT(sarb->tail + ATM_CELL_PAYLOAD <= sarb->end); 346 UDSL_ASSERT(sarb->tail + ATM_CELL_PAYLOAD <= sarb->end);
344 } 347 }
345 348
346 memcpy(sarb->tail, source + ATM_CELL_HEADER, ATM_CELL_PAYLOAD); 349 memcpy(skb_tail_pointer(sarb), source + ATM_CELL_HEADER, ATM_CELL_PAYLOAD);
347 __skb_put(sarb, ATM_CELL_PAYLOAD); 350 __skb_put(sarb, ATM_CELL_PAYLOAD);
348 351
349 if (pti & 1) { 352 if (pti & 1) {
@@ -370,7 +373,7 @@ static void usbatm_extract_one_cell(struct usbatm_data *instance, unsigned char
370 goto out; 373 goto out;
371 } 374 }
372 375
373 if (crc32_be(~0, sarb->tail - pdu_length, pdu_length) != 0xc704dd7b) { 376 if (crc32_be(~0, skb_tail_pointer(sarb) - pdu_length, pdu_length) != 0xc704dd7b) {
374 atm_rldbg(instance, "%s: packet failed crc check (vcc: 0x%p)!\n", 377 atm_rldbg(instance, "%s: packet failed crc check (vcc: 0x%p)!\n",
375 __func__, vcc); 378 __func__, vcc);
376 atomic_inc(&vcc->stats->rx_err); 379 atomic_inc(&vcc->stats->rx_err);
@@ -396,7 +399,9 @@ static void usbatm_extract_one_cell(struct usbatm_data *instance, unsigned char
396 goto out; /* atm_charge increments rx_drop */ 399 goto out; /* atm_charge increments rx_drop */
397 } 400 }
398 401
399 memcpy(skb->data, sarb->tail - pdu_length, length); 402 skb_copy_to_linear_data(skb,
403 skb_tail_pointer(sarb) - pdu_length,
404 length);
400 __skb_put(skb, length); 405 __skb_put(skb, length);
401 406
402 vdbg("%s: sending skb 0x%p, skb->len %u, skb->truesize %u", 407 vdbg("%s: sending skb 0x%p, skb->len %u, skb->truesize %u",
@@ -484,7 +489,7 @@ static unsigned int usbatm_write_cells(struct usbatm_data *instance,
484 ptr[4] = 0xec; 489 ptr[4] = 0xec;
485 ptr += ATM_CELL_HEADER; 490 ptr += ATM_CELL_HEADER;
486 491
487 memcpy(ptr, skb->data, data_len); 492 skb_copy_from_linear_data(skb, ptr, data_len);
488 ptr += data_len; 493 ptr += data_len;
489 __skb_pull(skb, data_len); 494 __skb_pull(skb, data_len);
490 495
@@ -966,6 +971,14 @@ static int usbatm_atm_init(struct usbatm_data *instance)
966 /* temp init ATM device, set to 128kbit */ 971 /* temp init ATM device, set to 128kbit */
967 atm_dev->link_rate = 128 * 1000 / 424; 972 atm_dev->link_rate = 128 * 1000 / 424;
968 973
974 ret = sysfs_create_link(&atm_dev->class_dev.kobj,
975 &instance->usb_intf->dev.kobj, "device");
976 if (ret) {
977 atm_err(instance, "%s: sysfs_create_link failed: %d\n",
978 __func__, ret);
979 goto fail_sysfs;
980 }
981
969 if (instance->driver->atm_start && ((ret = instance->driver->atm_start(instance, atm_dev)) < 0)) { 982 if (instance->driver->atm_start && ((ret = instance->driver->atm_start(instance, atm_dev)) < 0)) {
970 atm_err(instance, "%s: atm_start failed: %d!\n", __func__, ret); 983 atm_err(instance, "%s: atm_start failed: %d!\n", __func__, ret);
971 goto fail; 984 goto fail;
@@ -984,6 +997,8 @@ static int usbatm_atm_init(struct usbatm_data *instance)
984 return 0; 997 return 0;
985 998
986 fail: 999 fail:
1000 sysfs_remove_link(&atm_dev->class_dev.kobj, "device");
1001 fail_sysfs:
987 instance->atm_dev = NULL; 1002 instance->atm_dev = NULL;
988 atm_dev_deregister(atm_dev); /* usbatm_atm_dev_close will eventually be called */ 1003 atm_dev_deregister(atm_dev); /* usbatm_atm_dev_close will eventually be called */
989 return ret; 1004 return ret;
@@ -1316,8 +1331,10 @@ void usbatm_usb_disconnect(struct usb_interface *intf)
1316 kfree(instance->cell_buf); 1331 kfree(instance->cell_buf);
1317 1332
1318 /* ATM finalize */ 1333 /* ATM finalize */
1319 if (instance->atm_dev) 1334 if (instance->atm_dev) {
1335 sysfs_remove_link(&instance->atm_dev->class_dev.kobj, "device");
1320 atm_dev_deregister(instance->atm_dev); 1336 atm_dev_deregister(instance->atm_dev);
1337 }
1321 1338
1322 usbatm_put_instance(instance); /* taken in usbatm_usb_probe */ 1339 usbatm_put_instance(instance); /* taken in usbatm_usb_probe */
1323} 1340}