diff --git a/Documentation/networking/00-INDEX b/Documentation/networking/00-INDEX index e06b6e3c1db5..153d84d281e6 100644 --- a/Documentation/networking/00-INDEX +++ b/Documentation/networking/00-INDEX @@ -32,6 +32,8 @@ cops.txt - info on the COPS LocalTalk Linux driver cs89x0.txt - the Crystal LAN (CS8900/20-based) Ethernet ISA adapter driver +cxacru.txt + - Conexant AccessRunner USB ADSL Modem de4x5.txt - the Digital EtherWORKS DE4?? and DE5?? PCI Ethernet driver decnet.txt diff --git a/Documentation/networking/cxacru.txt b/Documentation/networking/cxacru.txt new file mode 100644 index 000000000000..b074681a963e --- /dev/null +++ b/Documentation/networking/cxacru.txt @@ -0,0 +1,84 @@ +Firmware is required for this device: http://accessrunner.sourceforge.net/ + +While it is capable of managing/maintaining the ADSL connection without the +module loaded, the device will sometimes stop responding after unloading the +driver and it is necessary to unplug/remove power to the device to fix this. + +Detected devices will appear as ATM devices named "cxacru". In /sys/class/atm/ +these are directories named cxacruN where N is the device number. A symlink +named device points to the USB interface device's directory which contains +several sysfs attribute files for retrieving device statistics: + +* adsl_controller_version + +* adsl_headend +* adsl_headend_environment + Information about the remote headend. + +* downstream_attenuation (dB) +* downstream_bits_per_frame +* downstream_rate (kbps) +* downstream_snr_margin (dB) + Downstream stats. + +* upstream_attenuation (dB) +* upstream_bits_per_frame +* upstream_rate (kbps) +* upstream_snr_margin (dB) +* transmitter_power (dBm/Hz) + Upstream stats. + +* downstream_crc_errors +* downstream_fec_errors +* downstream_hec_errors +* upstream_crc_errors +* upstream_fec_errors +* upstream_hec_errors + Error counts. + +* line_startable + Indicates that ADSL support on the device + is/can be enabled, see adsl_start. + +* line_status + "initialising" + "down" + "attempting to activate" + "training" + "channel analysis" + "exchange" + "waiting" + "up" + + Changes between "down" and "attempting to activate" + if there is no signal. + +* link_status + "not connected" + "connected" + "lost" + +* mac_address + +* modulation + "ANSI T1.413" + "ITU-T G.992.1 (G.DMT)" + "ITU-T G.992.2 (G.LITE)" + +* startup_attempts + Count of total attempts to initialise ADSL. + +To enable/disable ADSL, the following can be written to the adsl_state file: + "start" + "stop + "restart" (stops, waits 1.5s, then starts) + "poll" (used to resume status polling if it was disabled due to failure) + +Changes in adsl/line state are reported via kernel log messages: + [4942145.150704] ATM dev 0: ADSL state: running + [4942243.663766] ATM dev 0: ADSL line: down + [4942249.665075] ATM dev 0: ADSL line: attempting to activate + [4942253.654954] ATM dev 0: ADSL line: training + [4942255.666387] ATM dev 0: ADSL line: channel analysis + [4942259.656262] ATM dev 0: ADSL line: exchange + [2635357.696901] ATM dev 0: ADSL line: up (8128 kb/s down | 832 kb/s up) diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index 30b7bfbc985a..8bcf7fe1dd80 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -476,8 +476,6 @@ static int cxacru_start_wait_urb(struct urb *urb, struct completion *done, add_timer(&timer); wait_for_completion(done); status = urb->status; - if (status == -ECONNRESET) - status = -ETIMEDOUT; del_timer_sync(&timer); if (actual_length) @@ -629,10 +627,22 @@ static int cxacru_card_status(struct cxacru_data *instance) 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, struct atm_dev *atm_dev) { 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; */ @@ -649,14 +659,18 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance, 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 */ mutex_lock(&instance->adsl_state_serialize); ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_START, NULL, 0, NULL, 0); - if (ret < 0) { + if (ret < 0) atm_err(usbatm_instance, "cxacru_atm_start: CHIP_ADSL_LINE_START returned %d\n", ret); - mutex_unlock(&instance->adsl_state_serialize); - return ret; - } /* Start status polling */ mutex_lock(&instance->poll_state_serialize); @@ -680,6 +694,11 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance, if (start_polling) cxacru_poll_status(&instance->poll_work.work); 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) @@ -1065,13 +1084,6 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance, 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_dev, usb_rcvintpipe(usb_dev, CXACRU_EP_CMD), instance->rcv_buf, PAGE_SIZE, @@ -1092,14 +1104,6 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance, 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: free_page((unsigned long) instance->snd_buf); free_page((unsigned long) instance->rcv_buf); @@ -1146,11 +1150,6 @@ static void cxacru_unbind(struct usbatm_data *usbatm_instance, free_page((unsigned long) instance->snd_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); usbatm_instance->driver_data = NULL; @@ -1231,6 +1230,7 @@ static struct usbatm_driver cxacru_driver = { .heavy_init = cxacru_heavy_init, .unbind = cxacru_unbind, .atm_start = cxacru_atm_start, + .atm_stop = cxacru_remove_device_files, .bulk_in = CXACRU_EP_DATA, .bulk_out = CXACRU_EP_DATA, .rx_padding = 3, diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index 7b1edfe46b28..6778f9af7943 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -347,10 +347,8 @@ static int handle_bidir (struct usblp *usblp) if (usblp->bidir && usblp->used && !usblp->sleeping) { usblp->readcount = 0; usblp->readurb->dev = usblp->dev; - if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0) { - usblp->used = 0; + if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0) return -EIO; - } } return 0; @@ -412,6 +410,7 @@ static int usblp_open(struct inode *inode, struct file *file) usblp->readurb->status = 0; if (handle_bidir(usblp) < 0) { + usblp->used = 0; file->private_data = NULL; retval = -EIO; } diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig index f493fb1eaa27..346fc030c929 100644 --- a/drivers/usb/core/Kconfig +++ b/drivers/usb/core/Kconfig @@ -40,21 +40,25 @@ config USB_DEVICEFS config USB_DEVICE_CLASS bool "USB device class-devices (DEPRECATED)" depends on USB - default n + default y ---help--- Userspace access to USB devices is granted by device-nodes exported directly from the usbdev in sysfs. Old versions of the driver core and udev needed additional class devices to export device nodes. These additional devices are difficult to handle in userspace, if - information about USB interfaces must be available. One device contains - the device node, the other device contains the interface data. Both - devices are at the same level in sysfs (siblings) and one can't access - the other. The device node created directly by the usbdev is the parent - device of the interface and therefore easily accessible from the interface - event. + information about USB interfaces must be available. One device + contains the device node, the other device contains the interface + data. Both devices are at the same level in sysfs (siblings) and one + can't access the other. The device node created directly by the + usb device is the parent device of the interface and therefore + easily accessible from the interface event. - This option provides backward compatibility if needed. + This option provides backward compatibility for libusb device + nodes (lsusb) when usbfs is not used, and the following udev rule + doesn't exist: + SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", \ + NAME="bus/usb/$env{BUSNUM}/$env{DEVNUM}", MODE="0644" config USB_DYNAMIC_MINORS bool "Dynamic USB minor allocation (EXPERIMENTAL)" diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index 2d4fd530e5e4..dd3482328ad2 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -49,7 +50,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, unsigned char *buffer0 = buffer; struct usb_endpoint_descriptor *d; struct usb_host_endpoint *endpoint; - int n, i; + int n, i, j; d = (struct usb_endpoint_descriptor *) buffer; buffer += d->bLength; @@ -84,6 +85,45 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, memcpy(&endpoint->desc, d, n); INIT_LIST_HEAD(&endpoint->urb_list); + /* If the bInterval value is outside the legal range, + * set it to a default value: 32 ms */ + i = 0; /* i = min, j = max, n = default */ + j = 255; + if (usb_endpoint_xfer_int(d)) { + i = 1; + switch (to_usb_device(ddev)->speed) { + case USB_SPEED_HIGH: + n = 9; /* 32 ms = 2^(9-1) uframes */ + j = 16; + break; + default: /* USB_SPEED_FULL or _LOW */ + /* For low-speed, 10 ms is the official minimum. + * But some "overclocked" devices might want faster + * polling so we'll allow it. */ + n = 32; + break; + } + } else if (usb_endpoint_xfer_isoc(d)) { + i = 1; + j = 16; + switch (to_usb_device(ddev)->speed) { + case USB_SPEED_HIGH: + n = 9; /* 32 ms = 2^(9-1) uframes */ + break; + default: /* USB_SPEED_FULL */ + n = 6; /* 32 ms = 2^(6-1) frames */ + break; + } + } + if (d->bInterval < i || d->bInterval > j) { + dev_warn(ddev, "config %d interface %d altsetting %d " + "endpoint 0x%X has an invalid bInterval %d, " + "changing to %d\n", + cfgno, inum, asnum, + d->bEndpointAddress, d->bInterval, n); + endpoint->desc.bInterval = n; + } + /* Skip over any Class Specific or Vendor Specific descriptors; * find the next endpoint or interface descriptor */ endpoint->extra = buffer; diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index f28af06905a5..6042364402b8 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c @@ -132,7 +132,7 @@ ep_matches ( * where it's an output parameter representing the full speed limit. * the usb spec fixes high speed bulk maxpacket at 512 bytes. */ - max = 0x7ff & le16_to_cpup (&desc->wMaxPacketSize); + max = 0x7ff & le16_to_cpu(desc->wMaxPacketSize); switch (type) { case USB_ENDPOINT_XFER_INT: /* INT: limit 64 bytes full speed, 1024 high speed */ diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index 188c74a95216..46d0e5252744 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -1369,12 +1369,12 @@ config_buf (struct dev_data *dev, u8 type, unsigned index) hs = !hs; if (hs) { dev->req->buf = dev->hs_config; - len = le16_to_cpup (&dev->hs_config->wTotalLength); + len = le16_to_cpu(dev->hs_config->wTotalLength); } else #endif { dev->req->buf = dev->config; - len = le16_to_cpup (&dev->config->wTotalLength); + len = le16_to_cpu(dev->config->wTotalLength); } ((u8 *)dev->req->buf) [1] = type; return len; @@ -1885,7 +1885,7 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) /* full or low speed config */ dev->config = (void *) kbuf; - total = le16_to_cpup (&dev->config->wTotalLength); + total = le16_to_cpu(dev->config->wTotalLength); if (!is_valid_config (dev->config) || total >= length) goto fail; kbuf += total; @@ -1894,7 +1894,7 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) /* optional high speed config */ if (kbuf [1] == USB_DT_CONFIG) { dev->hs_config = (void *) kbuf; - total = le16_to_cpup (&dev->hs_config->wTotalLength); + total = le16_to_cpu(dev->hs_config->wTotalLength); if (!is_valid_config (dev->hs_config) || total >= length) goto fail; kbuf += total; diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 52779c52b56d..d975ecf18e00 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -2440,9 +2440,9 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) tmp = 0; -#define w_value le16_to_cpup (&u.r.wValue) -#define w_index le16_to_cpup (&u.r.wIndex) -#define w_length le16_to_cpup (&u.r.wLength) +#define w_value le16_to_cpu(u.r.wValue) +#define w_index le16_to_cpu(u.r.wIndex) +#define w_length le16_to_cpu(u.r.wLength) /* ack the irq */ writel (1 << SETUP_PACKET_INTERRUPT, &dev->regs->irqstat0); diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index b394e63894d2..c4975a6cf777 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -1651,9 +1651,9 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) UDC_EP_NUM_REG = 0; } while (UDC_IRQ_SRC_REG & UDC_SETUP); -#define w_value le16_to_cpup (&u.r.wValue) -#define w_index le16_to_cpup (&u.r.wIndex) -#define w_length le16_to_cpup (&u.r.wLength) +#define w_value le16_to_cpu(u.r.wValue) +#define w_index le16_to_cpu(u.r.wIndex) +#define w_length le16_to_cpu(u.r.wLength) /* Delegate almost all control requests to the gadget driver, * except for a handful of ch9 status/feature requests that diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index 6ec8cf1a3ccb..708657c89132 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c @@ -186,10 +186,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, DEBUG("query OID %08x value, len %d:\n", OID, buf_len); for (i = 0; i < buf_len; i += 16) { DEBUG ("%03d: %08x %08x %08x %08x\n", i, - le32_to_cpup((__le32 *)&buf[i]), - le32_to_cpup((__le32 *)&buf[i + 4]), - le32_to_cpup((__le32 *)&buf[i + 8]), - le32_to_cpup((__le32 *)&buf[i + 12])); + le32_to_cpu(get_unaligned((__le32 *) + &buf[i])), + le32_to_cpu(get_unaligned((__le32 *) + &buf[i + 4])), + le32_to_cpu(get_unaligned((__le32 *) + &buf[i + 8])), + le32_to_cpu(get_unaligned((__le32 *) + &buf[i + 12]))); } } @@ -665,7 +669,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, break; case OID_PNP_QUERY_POWER: DEBUG("%s: OID_PNP_QUERY_POWER D%d\n", __FUNCTION__, - le32_to_cpup((__le32 *) buf) - 1); + le32_to_cpu(get_unaligned((__le32 *)buf)) - 1); /* only suspend is a real power state, and * it can't be entered by OID_PNP_SET_POWER... */ @@ -704,10 +708,14 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len, DEBUG("set OID %08x value, len %d:\n", OID, buf_len); for (i = 0; i < buf_len; i += 16) { DEBUG ("%03d: %08x %08x %08x %08x\n", i, - le32_to_cpup((__le32 *)&buf[i]), - le32_to_cpup((__le32 *)&buf[i + 4]), - le32_to_cpup((__le32 *)&buf[i + 8]), - le32_to_cpup((__le32 *)&buf[i + 12])); + le32_to_cpu(get_unaligned((__le32 *) + &buf[i])), + le32_to_cpu(get_unaligned((__le32 *) + &buf[i + 4])), + le32_to_cpu(get_unaligned((__le32 *) + &buf[i + 8])), + le32_to_cpu(get_unaligned((__le32 *) + &buf[i + 12]))); } } @@ -721,7 +729,8 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len, * PROMISCUOUS, DIRECTED, * MULTICAST, ALL_MULTICAST, BROADCAST */ - *params->filter = (u16) le32_to_cpup((__le32 *)buf); + *params->filter = (u16) le32_to_cpu(get_unaligned( + (__le32 *)buf)); DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n", __FUNCTION__, *params->filter); @@ -771,7 +780,7 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len, * resuming, Windows forces a reset, and then SET_POWER D0. * FIXME ... then things go batty; Windows wedges itself. */ - i = le32_to_cpup((__force __le32 *)buf); + i = le32_to_cpu(get_unaligned((__le32 *)buf)); DEBUG("%s: OID_PNP_SET_POWER D%d\n", __FUNCTION__, i - 1); switch (i) { case NdisDeviceStateD0: @@ -1058,8 +1067,8 @@ int rndis_msg_parser (u8 configNr, u8 *buf) return -ENOMEM; tmp = (__le32 *) buf; - MsgType = le32_to_cpup(tmp++); - MsgLength = le32_to_cpup(tmp++); + MsgType = le32_to_cpu(get_unaligned(tmp++)); + MsgLength = le32_to_cpu(get_unaligned(tmp++)); if (configNr >= RNDIS_MAX_CONFIGS) return -ENOTSUPP; diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 216c9c9d4d6d..bb9cc595219e 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -417,6 +417,8 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) unsigned long flags; spin_lock_irqsave (&ohci->lock, flags); + if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) + goto done; /* undocumented erratum seen on at least rev D */ if ((ohci->flags & OHCI_QUIRK_AMD756) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index d230ee72f9cd..54979c239c63 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1179,8 +1179,8 @@ UNUSUAL_DEV( 0x0a17, 0x006, 0x0000, 0xffff, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), -/* These are virtual windows driver CDs, which the zd1211rw driver automatically - * converts into a WLAN devices. */ +/* These are virtual windows driver CDs, which the zd1211rw driver + * automatically converts into WLAN devices. */ UNUSUAL_DEV( 0x0ace, 0x2011, 0x0101, 0x0101, "ZyXEL", "G-220F USB-WLAN Install", @@ -1193,6 +1193,14 @@ UNUSUAL_DEV( 0x0ace, 0x20ff, 0x0101, 0x0101, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_IGNORE_DEVICE ), +/* SanDisk that has a second LUN for a driver ISO, reported by + * Ben Collins */ +UNUSUAL_DEV( 0x0781, 0x5406, 0x0000, 0xffff, + "SanDisk", + "U3 Cruzer Micro driver ISO", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_SINGLE_LUN ), + #ifdef CONFIG_USB_STORAGE_ISD200 UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110, "ATI", @@ -1271,6 +1279,15 @@ UNUSUAL_DEV( 0x0dd8, 0x1060, 0x0000, 0xffff, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), +/* Reported by Edward Chapman (taken from linux-usb mailing list) + Netac OnlyDisk Mini U2CV2 512MB USB 2.0 Flash Drive */ +UNUSUAL_DEV( 0x0dd8, 0xd202, 0x0000, 0x9999, + "Netac", + "USB Flash Disk", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE ), + + /* Patch by Stephan Walter * I don't know why, but it works... */ UNUSUAL_DEV( 0x0dda, 0x0001, 0x0012, 0x0012,