Commit 50f732ee authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/usb-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/usb-2.6: (78 commits)
  USB: update MAINAINERS and CREDITS for Freescale USB driver
  USB: update gadget files for fsl_usb2_udc driver
  USB: add Freescale high-speed USB SOC device controller driver
  USB: quirk for broken suspend of IT8152F/G
  USB: iowarrior.c: timeouts too small in usb_control_msg calls
  USB: dell device id for option.c
  USB: Remove Huawei unusual_devs entry
  USB: CP2101 New Device IDs
  USB: add picdem device to ldusb
  usbfs micro optimitation
  USB: remove ancient/broken CRIS hcd
  usb ethernet gadget, workaround network stack API glitch
  USB: add "busnum" attribute for USB devices
  USB: cxacru: ADSL state management
  usbatm: Detect usb device shutdown and ignore failed urbs
  USB: Remove duplicate define of OHCI_QUIRK_ZFMICRO
  USB: BandRich BandLuxe HSDPA Data Card Driver
  USB gadget rndis: fix struct rndis_packet_msg_type unaligned bug
  USB Elan FTDI: check for driver registration status
  USB: sierra: add more checks on shutdown
  ...
parents aa5bc2b5 a7205b30
......@@ -3301,6 +3301,14 @@ S: 12725 SW Millikan Way, Suite 400
S: Beaverton, Oregon 97005
S: USA
N: Li Yang
E: leoli@freescale.com
D: Freescale Highspeed USB device driver
D: Freescale QE SoC support and Ethernet driver
S: B-1206 Jingmao Guojigongyu
S: 16 Baliqiao Nanjie, Beijing 101100
S: People's Repulic of China
N: Marcelo Tosatti
E: marcelo@kvack.org
D: v2.4 kernel maintainer
......
What: /sys/bus/usb/devices/.../power/autosuspend
Date: March 2007
KernelVersion: 2.6.21
Contact: Alan Stern <stern@rowland.harvard.edu>
Description:
Each USB device directory will contain a file named
power/autosuspend. This file holds the time (in seconds)
the device must be idle before it will be autosuspended.
0 means the device will be autosuspended as soon as
possible. Negative values will prevent the device from
being autosuspended at all, and writing a negative value
will resume the device if it is already suspended.
The autosuspend delay for newly-created devices is set to
the value of the usbcore.autosuspend module parameter.
What: /sys/bus/usb/devices/.../power/level
Date: March 2007
KernelVersion: 2.6.21
Contact: Alan Stern <stern@rowland.harvard.edu>
Description:
Each USB device directory will contain a file named
power/level. This file holds a power-level setting for
the device, one of "on", "auto", or "suspend".
"on" means that the device is not allowed to autosuspend,
although normal suspends for system sleep will still
be honored. "auto" means the device will autosuspend
and autoresume in the usual manner, according to the
capabilities of its driver. "suspend" means the device
is forced into a suspended state and it will not autoresume
in response to I/O requests. However remote-wakeup requests
from the device may still be enabled (the remote-wakeup
setting is controlled separately by the power/wakeup
attribute).
During normal use, devices should be left in the "auto"
level. The other levels are meant for administrative uses.
If you want to suspend a device immediately but leave it
free to wake up in response to I/O requests, you should
write "0" to power/autosuspend.
......@@ -1792,7 +1792,7 @@ and is between 256 and 4096 characters. It is defined in the file
for newly-detected USB devices (default 2). This
is the time required before an idle device will be
autosuspended. Devices for which the delay is set
to 0 won't be autosuspended at all.
to a negative value won't be autosuspended at all.
usbhid.mousepoll=
[USBHID] The interval which mice are to be polled at.
......
......@@ -16,7 +16,7 @@ situation as with tcpdump.
Unlike the packet socket, usbmon has an interface which provides traces
in a text format. This is used for two purposes. First, it serves as a
common trace exchange format for tools while most sophisticated formats
common trace exchange format for tools while more sophisticated formats
are finalized. Second, humans can read it in case tools are not available.
To collect a raw text trace, execute following steps.
......@@ -34,7 +34,7 @@ if usbmon is built into the kernel.
Verify that bus sockets are present.
# ls /sys/kernel/debug/usbmon
1s 1t 2s 2t 3s 3t 4s 4t
1s 1t 1u 2s 2t 2u 3s 3t 3u 4s 4t 4u
#
2. Find which bus connects to the desired device
......@@ -54,7 +54,7 @@ Bus=03 means it's bus 3.
3. Start 'cat'
# cat /sys/kernel/debug/usbmon/3t > /tmp/1.mon.out
# cat /sys/kernel/debug/usbmon/3u > /tmp/1.mon.out
This process will be reading until killed. Naturally, the output can be
redirected to a desirable location. This is preferred, because it is going
......@@ -75,46 +75,80 @@ that the file size is not excessive for your favourite editor.
* Raw text data format
The '1t' type data consists of a stream of events, such as URB submission,
Two formats are supported currently: the original, or '1t' format, and
the '1u' format. The '1t' format is deprecated in kernel 2.6.21. The '1u'
format adds a few fields, such as ISO frame descriptors, interval, etc.
It produces slightly longer lines, but otherwise is a perfect superset
of '1t' format.
If it is desired to recognize one from the other in a program, look at the
"address" word (see below), where '1u' format adds a bus number. If 2 colons
are present, it's the '1t' format, otherwise '1u'.
Any text format data consists of a stream of events, such as URB submission,
URB callback, submission error. Every event is a text line, which consists
of whitespace separated words. The number or position of words may depend
on the event type, but there is a set of words, common for all types.
Here is the list of words, from left to right:
- URB Tag. This is used to identify URBs is normally a kernel mode address
of the URB structure in hexadecimal.
- Timestamp in microseconds, a decimal number. The timestamp's resolution
depends on available clock, and so it can be much worse than a microsecond
(if the implementation uses jiffies, for example).
- Event Type. This type refers to the format of the event, not URB type.
Available types are: S - submission, C - callback, E - submission error.
- "Pipe". The pipe concept is deprecated. This is a composite word, used to
be derived from information in pipes. It consists of three fields, separated
by colons: URB type and direction, Device address, Endpoint number.
- "Address" word (formerly a "pipe"). It consists of four fields, separated by
colons: URB type and direction, Bus number, Device address, Endpoint number.
Type and direction are encoded with two bytes in the following manner:
Ci Co Control input and output
Zi Zo Isochronous input and output
Ii Io Interrupt input and output
Bi Bo Bulk input and output
Device address and Endpoint number are 3-digit and 2-digit (respectively)
decimal numbers, with leading zeroes.
- URB Status. In most cases, this field contains a number, sometimes negative,
which represents a "status" field of the URB. This field makes no sense for
submissions, but is present anyway to help scripts with parsing. When an
error occurs, the field contains the error code. In case of a submission of
a Control packet, this field contains a Setup Tag instead of an error code.
It is easy to tell whether the Setup Tag is present because it is never a
number. Thus if scripts find a number in this field, they proceed to read
Data Length. If they find something else, like a letter, they read the setup
packet before reading the Data Length.
Bus number, Device address, and Endpoint are decimal numbers, but they may
have leading zeros, for the sake of human readers.
- URB Status word. This is either a letter, or several numbers separated
by colons: URB status, interval, start frame, and error count. Unlike the
"address" word, all fields save the status are optional. Interval is printed
only for interrupt and isochronous URBs. Start frame is printed only for
isochronous URBs. Error count is printed only for isochronous callback
events.
The status field is a decimal number, sometimes negative, which represents
a "status" field of the URB. This field makes no sense for submissions, but
is present anyway to help scripts with parsing. When an error occurs, the
field contains the error code.
In case of a submission of a Control packet, this field contains a Setup Tag
instead of an group of numbers. It is easy to tell whether the Setup Tag is
present because it is never a number. Thus if scripts find a set of numbers
in this word, they proceed to read Data Length (except for isochronous URBs).
If they find something else, like a letter, they read the setup packet before
reading the Data Length or isochronous descriptors.
- Setup packet, if present, consists of 5 words: one of each for bmRequestType,
bRequest, wValue, wIndex, wLength, as specified by the USB Specification 2.0.
These words are safe to decode if Setup Tag was 's'. Otherwise, the setup
packet was present, but not captured, and the fields contain filler.
- Number of isochronous frame descriptors and descriptors themselves.
If an Isochronous transfer event has a set of descriptors, a total number
of them in an URB is printed first, then a word per descriptor, up to a
total of 5. The word consists of 3 colon-separated decimal numbers for
status, offset, and length respectively. For submissions, initial length
is reported. For callbacks, actual length is reported.
- Data Length. For submissions, this is the requested length. For callbacks,
this is the actual length.
- Data tag. The usbmon may not always capture data, even if length is nonzero.
The data words are present only if this tag is '='.
- Data words follow, in big endian hexadecimal format. Notice that they are
not machine words, but really just a byte stream split into words to make
it easier to read. Thus, the last word may contain from one to four bytes.
......@@ -153,20 +187,18 @@ class ParsedLine {
}
}
This format may be changed in the future.
Examples:
An input control transfer to get a port status.
d5ea89a0 3575914555 S Ci:001:00 s a3 00 0000 0003 0004 4 <
d5ea89a0 3575914560 C Ci:001:00 0 4 = 01050000
d5ea89a0 3575914555 S Ci:1:001:0 s a3 00 0000 0003 0004 4 <
d5ea89a0 3575914560 C Ci:1:001:0 0 4 = 01050000
An output bulk transfer to send a SCSI command 0x5E in a 31-byte Bulk wrapper
to a storage device at address 5:
dd65f0e8 4128379752 S Bo:005:02 -115 31 = 55534243 5e000000 00000000 00000600 00000000 00000000 00000000 000000
dd65f0e8 4128379808 C Bo:005:02 0 31 >
dd65f0e8 4128379752 S Bo:1:005:2 -115 31 = 55534243 5e000000 00000000 00000600 00000000 00000000 00000000 000000
dd65f0e8 4128379808 C Bo:1:005:2 0 31 >
* Raw binary format and API
......
......@@ -981,6 +981,11 @@ M: mhw@wittsend.com
W: http://www.wittsend.com/computone.html
S: Maintained
CONEXANT ACCESSRUNNER USB DRIVER
P: Simon Arlott
M: cxacru@fire.lp0.eu
S: Maintained
COSA/SRP SYNC SERIAL DRIVER
P: Jan "Yenya" Kasprzak
M: kas@fi.muni.cz
......@@ -1389,6 +1394,13 @@ L: linuxppc-embedded@ozlabs.org
L: netdev@vger.kernel.org
S: Maintained
FREESCALE HIGHSPEED USB DEVICE DRIVER
P: Li Yang
M: leoli@freescale.com
L: linux-usb-devel@lists.sourceforge.net
L: linuxppc-embedded@ozlabs.org
S: Maintained
FILE LOCKING (flock() and fcntl()/lockf())
P: Matthew Wilcox
M: matthew@wil.cx
......
......@@ -2132,10 +2132,13 @@ static int ub_get_pipes(struct ub_dev *sc, struct usb_device *dev,
if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
== USB_ENDPOINT_XFER_BULK) {
/* BULK in or out? */
if (ep->bEndpointAddress & USB_DIR_IN)
ep_in = ep;
else
ep_out = ep;
if (ep->bEndpointAddress & USB_DIR_IN) {
if (ep_in == NULL)
ep_in = ep;
} else {
if (ep_out == NULL)
ep_out = ep;
}
}
}
......
......@@ -15,7 +15,6 @@ obj-$(CONFIG_USB_OHCI_HCD) += host/
obj-$(CONFIG_USB_UHCI_HCD) += host/
obj-$(CONFIG_USB_SL811_HCD) += host/
obj-$(CONFIG_USB_U132_HCD) += host/
obj-$(CONFIG_ETRAX_USB_HOST) += host/
obj-$(CONFIG_USB_OHCI_AT91) += host/
obj-$(CONFIG_USB_ACM) += class/
......
......@@ -4,6 +4,7 @@
*
* Copyright (C) 2004 David Woodhouse, Duncan Sands, Roman Kagan
* Copyright (C) 2005 Duncan Sands, Roman Kagan (rkagan % mail ! ru)
* Copyright (C) 2007 Simon Arlott
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
......@@ -34,14 +35,14 @@
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/device.h> /* FIXME: linux/firmware.h should include it itself */
#include <linux/device.h>
#include <linux/firmware.h>
#include <linux/mutex.h>
#include "usbatm.h"
#define DRIVER_AUTHOR "Roman Kagan, David Woodhouse, Duncan Sands"
#define DRIVER_VERSION "0.2"
#define DRIVER_AUTHOR "Roman Kagan, David Woodhouse, Duncan Sands, Simon Arlott"
#define DRIVER_VERSION "0.3"
#define DRIVER_DESC "Conexant AccessRunner ADSL USB modem driver"
static const char cxacru_driver_name[] = "cxacru";
......@@ -64,7 +65,7 @@ static const char cxacru_driver_name[] = "cxacru";
#define SDRAM_ENA 0x1
#define CMD_TIMEOUT 2000 /* msecs */
#define POLL_INTERVAL 5000 /* msecs */
#define POLL_INTERVAL 1 /* secs */
/* commands for interaction with the modem through the control channel before
* firmware is loaded */
......@@ -146,6 +147,13 @@ enum cxacru_info_idx {
CXINF_MAX = 0x1c,
};
enum cxacru_poll_state {
CXPOLL_STOPPING,
CXPOLL_STOPPED,
CXPOLL_POLLING,
CXPOLL_SHUTDOWN
};
struct cxacru_modem_type {
u32 pll_f_clk;
u32 pll_b_clk;
......@@ -158,7 +166,12 @@ struct cxacru_data {
const struct cxacru_modem_type *modem_type;
int line_status;
struct mutex adsl_state_serialize;
int adsl_status;
struct delayed_work poll_work;
u32 card_info[CXINF_MAX];
struct mutex poll_state_serialize;
int poll_state;
/* contol handles */
struct mutex cm_serialize;
......@@ -170,6 +183,275 @@ struct cxacru_data {
struct completion snd_done;
};
static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm,
u8 *wdata, int wsize, u8 *rdata, int rsize);
static void cxacru_poll_status(struct work_struct *work);
/* Card info exported through sysfs */
#define CXACRU__ATTR_INIT(_name) \
static DEVICE_ATTR(_name, S_IRUGO, cxacru_sysfs_show_##_name, NULL)
#define CXACRU_CMD_INIT(_name) \
static DEVICE_ATTR(_name, S_IWUSR | S_IRUGO, \
cxacru_sysfs_show_##_name, cxacru_sysfs_store_##_name)
#define CXACRU_ATTR_INIT(_value, _type, _name) \
static ssize_t cxacru_sysfs_show_##_name(struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
struct usb_interface *intf = to_usb_interface(dev); \
struct usbatm_data *usbatm_instance = usb_get_intfdata(intf); \
struct cxacru_data *instance = usbatm_instance->driver_data; \
return cxacru_sysfs_showattr_##_type(instance->card_info[_value], buf); \
} \
CXACRU__ATTR_INIT(_name)
#define CXACRU_ATTR_CREATE(_v, _t, _name) CXACRU_DEVICE_CREATE_FILE(_name)
#define CXACRU_CMD_CREATE(_name) CXACRU_DEVICE_CREATE_FILE(_name)
#define CXACRU__ATTR_CREATE(_name) CXACRU_DEVICE_CREATE_FILE(_name)
#define CXACRU_ATTR_REMOVE(_v, _t, _name) CXACRU_DEVICE_REMOVE_FILE(_name)
#define CXACRU_CMD_REMOVE(_name) CXACRU_DEVICE_REMOVE_FILE(_name)
#define CXACRU__ATTR_REMOVE(_name) CXACRU_DEVICE_REMOVE_FILE(_name)
static ssize_t cxacru_sysfs_showattr_u32(u32 value, char *buf)
{
return snprintf(buf, PAGE_SIZE, "%u\n", value);
}
static ssize_t cxacru_sysfs_showattr_s8(s8 value, char *buf)
{
return snprintf(buf, PAGE_SIZE, "%d\n", value);
}
static ssize_t cxacru_sysfs_showattr_dB(s16 value, char *buf)
{
if (unlikely(value < 0)) {
return snprintf(buf, PAGE_SIZE, "%d.%02u\n",
value / 100, -value % 100);
} else {
return snprintf(buf, PAGE_SIZE, "%d.%02u\n",
value / 100, value % 100);
}
}
static ssize_t cxacru_sysfs_showattr_bool(u32 value, char *buf)
{
switch (value) {
case 0: return snprintf(buf, PAGE_SIZE, "no\n");
case 1: return snprintf(buf, PAGE_SIZE, "yes\n");
default: return 0;
}
}
static ssize_t cxacru_sysfs_showattr_LINK(u32 value, char *buf)
{
switch (value) {
case 1: return snprintf(buf, PAGE_SIZE, "not connected\n");
case 2: return snprintf(buf, PAGE_SIZE, "connected\n");
case 3: return snprintf(buf, PAGE_SIZE, "lost\n");
default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value);
}
}
static ssize_t cxacru_sysfs_showattr_LINE(u32 value, char *buf)
{
switch (value) {
case 0: return snprintf(buf, PAGE_SIZE, "down\n");
case 1: return snprintf(buf, PAGE_SIZE, "attempting to activate\n");
case 2: return snprintf(buf, PAGE_SIZE, "training\n");
case 3: return snprintf(buf, PAGE_SIZE, "channel analysis\n");
case 4: return snprintf(buf, PAGE_SIZE, "exchange\n");
case 5: return snprintf(buf, PAGE_SIZE, "up\n");
case 6: return snprintf(buf, PAGE_SIZE, "waiting\n");
case 7: return snprintf(buf, PAGE_SIZE, "initialising\n");
default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value);
}
}
static ssize_t cxacru_sysfs_showattr_MODU(u32 value, char *buf)
{
switch (value) {
case 0: return 0;
case 1: return snprintf(buf, PAGE_SIZE, "ANSI T1.413\n");
case 2: return snprintf(buf, PAGE_SIZE, "ITU-T G.992.1 (G.DMT)\n");
case 3: return snprintf(buf, PAGE_SIZE, "ITU-T G.992.2 (G.LITE)\n");
default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value);
}
}
/*
* This could use MAC_ADDRESS_HIGH and MAC_ADDRESS_LOW, but since
* this data is already in atm_dev there's no point.
*
* MAC_ADDRESS_HIGH = 0x????5544
* MAC_ADDRESS_LOW = 0x33221100
* Where 00-55 are bytes 0-5 of the MAC.
*/
static ssize_t cxacru_sysfs_show_mac_address(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct usb_interface *intf = to_usb_interface(dev);
struct usbatm_data *usbatm_instance = usb_get_intfdata(intf);
struct atm_dev *atm_dev = usbatm_instance->atm_dev;
return snprintf(buf, PAGE_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x\n",
atm_dev->esi[0], atm_dev->esi[1], atm_dev->esi[2],
atm_dev->esi[3], atm_dev->esi[4], atm_dev->esi[5]);
}
static ssize_t cxacru_sysfs_show_adsl_state(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct usb_interface *intf = to_usb_interface(dev);
struct usbatm_data *usbatm_instance = usb_get_intfdata(intf);
struct cxacru_data *instance = usbatm_instance->driver_data;
u32 value = instance->card_info[CXINF_LINE_STARTABLE];
switch (value) {
case 0: return snprintf(buf, PAGE_SIZE, "running\n");
case 1: return snprintf(buf, PAGE_SIZE, "stopped\n");
default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value);
}
}
static ssize_t cxacru_sysfs_store_adsl_state(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct usb_interface *intf = to_usb_interface(dev);
struct usbatm_data *usbatm_instance = usb_get_intfdata(intf);
struct cxacru_data *instance = usbatm_instance->driver_data;
int ret;
int poll = -1;
char str_cmd[8];
int len = strlen(buf);
if (!capable(CAP_NET_ADMIN))
return -EACCES;
ret = sscanf(buf, "%7s", str_cmd);
if (ret != 1)
return -EINVAL;
ret = 0;
if (mutex_lock_interruptible(&instance->adsl_state_serialize))
return -ERESTARTSYS;
if (!strcmp(str_cmd, "stop") || !strcmp(str_cmd, "restart")) {
ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_STOP, NULL, 0, NULL, 0);
if (ret < 0) {
atm_err(usbatm_instance, "change adsl state:"
" CHIP_ADSL_LINE_STOP returned %d\n", ret);
ret = -EIO;
} else {
ret = len;
poll = CXPOLL_STOPPED;
}
}
/* Line status is only updated every second
* and the device appears to only react to
* START/STOP every second too. Wait 1.5s to
* be sure that restart will have an effect. */
if (!strcmp(str_cmd, "restart"))
msleep(1500);
if (!strcmp(str_cmd, "start") || !strcmp(str_cmd, "restart")) {
ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_START, NULL, 0, NULL, 0);
if (ret < 0) {
atm_err(usbatm_instance, "change adsl state:"
" CHIP_ADSL_LINE_START returned %d\n", ret);
ret = -EIO;
} else {
ret = len;
poll = CXPOLL_POLLING;
}
}
if (!strcmp(str_cmd, "poll")) {
ret = len;
poll = CXPOLL_POLLING;
}
if (ret == 0) {
ret = -EINVAL;
poll = -1;
}
if (poll == CXPOLL_POLLING) {
mutex_lock(&instance->poll_state_serialize);
switch (instance->poll_state) {
case CXPOLL_STOPPED:
/* start polling */
instance->poll_state = CXPOLL_POLLING;
break;
case CXPOLL_STOPPING:
/* abort stop request */
instance->poll_state = CXPOLL_POLLING;
case CXPOLL_POLLING:
case CXPOLL_SHUTDOWN:
/* don't start polling */
poll = -1;
}
mutex_unlock(&instance->poll_state_serialize);
} else if (poll == CXPOLL_STOPPED) {
mutex_lock(&instance->poll_state_serialize);
/* request stop */
if (instance->poll_state == CXPOLL_POLLING)
instance->poll_state = CXPOLL_STOPPING;
mutex_unlock(&instance->poll_state_serialize);
}
mutex_unlock(&instance->adsl_state_serialize);
if (poll == CXPOLL_POLLING)
cxacru_poll_status(&instance->poll_work.work);
return ret;
}
/*
* All device attributes are included in CXACRU_ALL_FILES
* so that the same list can be used multiple times:
* INIT (define the device attributes)
* CREATE (create all the device files)
* REMOVE (remove all the device files)
*
* With the last two being defined as needed in the functions
* they are used in before calling CXACRU_ALL_FILES()
*/
#define CXACRU_ALL_FILES(_action) \
CXACRU_ATTR_##_action(CXINF_DOWNSTREAM_RATE, u32, downstream_rate); \
CXACRU_ATTR_##_action(CXINF_UPSTREAM_RATE, u32, upstream_rate); \
CXACRU_ATTR_##_action(CXINF_LINK_STATUS, LINK, link_status); \
CXACRU_ATTR_##_action(CXINF_LINE_STATUS, LINE, line_status); \
CXACRU__ATTR_##_action( mac_address); \
CXACRU_ATTR_##_action(CXINF_UPSTREAM_SNR_MARGIN, dB, upstream_snr_margin); \
CXACRU_ATTR_##_action(CXINF_DOWNSTREAM_SNR_MARGIN, dB, downstream_snr_margin); \
CXACRU_ATTR_##_action(CXINF_UPSTREAM_ATTENUATION, dB, upstream_attenuation); \
CXACRU_ATTR_##_action(CXINF_DOWNSTREAM_ATTENUATION, dB, downstream_attenuation); \
CXACRU_ATTR_##_action(CXINF_TRANSMITTER_POWER, s8, transmitter_power); \
CXACRU_ATTR_##_action(CXINF_UPSTREAM_BITS_PER_FRAME, u32, upstream_bits_per_frame); \
CXACRU_ATTR_##_action(CXINF_DOWNSTREAM_BITS_PER_FRAME, u32, downstream_bits_per_frame); \
CXACRU_ATTR_##_action(CXINF_STARTUP_ATTEMPTS, u32, startup_attempts); \
CXACRU_ATTR_##_action(CXINF_UPSTREAM_CRC_ERRORS, u32, upstream_crc_errors); \
CXACRU_ATTR_##_action(CXINF_DOWNSTREAM_CRC_ERRORS, u32, downstream_crc_errors); \
CXACRU_ATTR_##_action(CXINF_UPSTREAM_FEC_ERRORS, u32, upstream_fec_errors); \
CXACRU_ATTR_##_action(CXINF_DOWNSTREAM_FEC_ERRORS, u32, downstream_fec_errors); \
CXACRU_ATTR_##_action(CXINF_UPSTREAM_HEC_ERRORS, u32, upstream_hec_errors); \
CXACRU_ATTR_##_action(CXINF_DOWNSTREAM_HEC_ERRORS, u32, downstream_hec_errors); \
CXACRU_ATTR_##_action(CXINF_LINE_STARTABLE, bool, line_startable); \
CXACRU_ATTR_##_action(CXINF_MODULATION, MODU, modulation); \
CXACRU_ATTR_##_action(CXINF_ADSL_HEADEND, u32, adsl_headend); \
CXACRU_ATTR_##_action(CXINF_ADSL_HEADEND_ENVIRONMENT, u32, adsl_headend_environment); \
CXACRU_ATTR_##_action(CXINF_CONTROLLER_VERSION, u32, adsl_controller_version); \
CXACRU_CMD_##_action( adsl_state);
CXACRU_ALL_FILES(INIT);
/* the following three functions are stolen from drivers/usb/core/message.c */
static void cxacru_blocking_completion(struct urb *urb)
{
......@@ -347,8 +629,6 @@ static int cxacru_card_status(struct cxacru_data *instance)
return 0;
}
static void cxacru_poll_status(struct work_struct *work);
static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
struct atm_dev *atm_dev)
{
......@@ -357,6 +637,7 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
struct atm_dev *atm_dev = usbatm_instance->atm_dev;
*/
int ret;
int start_polling = 1;
dbg("cxacru_atm_start");
......@@ -369,14 +650,35 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
}
/* start ADSL */
mutex_lock(&instance->adsl_state_serialize);
ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_START, NULL, 0, NULL, 0);
if (ret < 0) {