···11#22-# USB ATM driver configuration22+# USB/ATM DSL configuration33#44-comment "USB ATM/DSL drivers"44+55+menu "USB DSL modem support"56 depends on USB6778config USB_ATM88- tristate "Generic USB ATM/DSL core I/O support"99+ tristate "USB DSL modem support"910 depends on USB && ATM1011 select CRC321112 default n1213 help1313- This provides a library which is used for packet I/O by USB DSL1414- modems, such as the SpeedTouch driver below. 1414+ Say Y here if you want to connect a USB Digital Subscriber Line (DSL)1515+ modem to your computer's USB port. You will then need to choose your1616+ modem from the list below.15171618 To compile this driver as a module, choose M here: the1717- module will be called usb_atm.1919+ module will be called usbatm.18201921config USB_SPEEDTOUCH2020- tristate "Alcatel Speedtouch USB support"2121- depends on USB && ATM2222- select USB_ATM2222+ tristate "Speedtouch USB support"2323+ depends on USB_ATM2424+ select FW_LOADER2325 help2424- Say Y here if you have an Alcatel SpeedTouch USB or SpeedTouch 3302626+ Say Y here if you have an SpeedTouch USB or SpeedTouch 3302527 modem. In order to use your modem you will need to install the 2628 two parts of the firmware, extracted by the user space tools; see2729 <http://www.linux-usb.org/SpeedTouch/> for details.28302931 To compile this driver as a module, choose M here: the3032 module will be called speedtch.3333+3434+config USB_CXACRU3535+ tristate "Conexant AccessRunner USB support"3636+ depends on USB_ATM3737+ select FW_LOADER3838+ help3939+ Say Y here if you have an ADSL USB modem based on the Conexant4040+ AccessRunner chipset. In order to use your modem you will need to4141+ install the firmware, extracted by the user space tools; see4242+ <http://accessrunner.sourceforge.net/> for details.4343+4444+ To compile this driver as a module, choose M here: the4545+ module will be called cxacru.4646+4747+config USB_XUSBATM4848+ tristate "Other USB DSL modem support"4949+ depends on USB_ATM5050+ help5151+ Say Y here if you have a DSL USB modem not explicitly supported by5252+ another USB DSL drivers. In order to use your modem you will need to5353+ pass the vendor ID, product ID, and endpoint numbers for transmission5454+ and reception as module parameters. You may need to initialize the5555+ the modem using a user space utility (a firmware loader for example).5656+5757+ To compile this driver as a module, choose M here: the5858+ module will be called xusbatm.5959+6060+endmenu
+4-3
drivers/usb/atm/Makefile
···11#22-# Makefile for the rest of the USB drivers33-# (the ones that don't fit into any other categories)22+# Makefile for USB ATM/xDSL drivers43#5466-obj-$(CONFIG_USB_ATM) += usb_atm.o55+obj-$(CONFIG_USB_CXACRU) += cxacru.o76obj-$(CONFIG_USB_SPEEDTOUCH) += speedtch.o77+obj-$(CONFIG_USB_ATM) += usbatm.o88+obj-$(CONFIG_USB_XUSBATM) += xusbatm.o
+878
drivers/usb/atm/cxacru.c
···11+/******************************************************************************22+ * cxacru.c - driver for USB ADSL modems based on33+ * Conexant AccessRunner chipset44+ *55+ * Copyright (C) 2004 David Woodhouse, Duncan Sands, Roman Kagan66+ * Copyright (C) 2005 Duncan Sands, Roman Kagan (rkagan % mail ! ru)77+ *88+ * This program is free software; you can redistribute it and/or modify it99+ * under the terms of the GNU General Public License as published by the Free1010+ * Software Foundation; either version 2 of the License, or (at your option)1111+ * any later version.1212+ *1313+ * This program is distributed in the hope that it will be useful, but WITHOUT1414+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or1515+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for1616+ * more details.1717+ *1818+ * You should have received a copy of the GNU General Public License along with1919+ * this program; if not, write to the Free Software Foundation, Inc., 592020+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.2121+ *2222+ ******************************************************************************/2323+2424+/*2525+ * Credit is due for Josep Comas, who created the original patch to speedtch.c2626+ * to support the different padding used by the AccessRunner (now generalized2727+ * into usbatm), and the userspace firmware loading utility.2828+ */2929+3030+#include <linux/module.h>3131+#include <linux/moduleparam.h>3232+#include <linux/kernel.h>3333+#include <linux/timer.h>3434+#include <linux/errno.h>3535+#include <linux/slab.h>3636+#include <linux/init.h>3737+#include <linux/device.h> /* FIXME: linux/firmware.h should include it itself */3838+#include <linux/firmware.h>3939+4040+#include "usbatm.h"4141+4242+#define DRIVER_AUTHOR "Roman Kagan, David Woodhouse, Duncan Sands"4343+#define DRIVER_VERSION "0.2"4444+#define DRIVER_DESC "Conexant AccessRunner ADSL USB modem driver"4545+4646+static const char cxacru_driver_name[] = "cxacru";4747+4848+#define CXACRU_EP_CMD 0x01 /* Bulk/interrupt in/out */4949+#define CXACRU_EP_DATA 0x02 /* Bulk in/out */5050+5151+#define CMD_PACKET_SIZE 64 /* Should be maxpacket(ep)? */5252+5353+/* Addresses */5454+#define PLLFCLK_ADDR 0x003500685555+#define PLLBCLK_ADDR 0x0035006c5656+#define SDRAMEN_ADDR 0x003500105757+#define FW_ADDR 0x008010005858+#define BR_ADDR 0x001806005959+#define SIG_ADDR 0x001805006060+#define BR_STACK_ADDR 0x00187f106161+6262+/* Values */6363+#define SDRAM_ENA 0x16464+6565+#define CMD_TIMEOUT 2000 /* msecs */6666+#define POLL_INTERVAL 5000 /* msecs */6767+6868+/* commands for interaction with the modem through the control channel before6969+ * firmware is loaded */7070+enum cxacru_fw_request {7171+ FW_CMD_ERR,7272+ FW_GET_VER,7373+ FW_READ_MEM,7474+ FW_WRITE_MEM,7575+ FW_RMW_MEM,7676+ FW_CHECKSUM_MEM,7777+ FW_GOTO_MEM,7878+};7979+8080+/* commands for interaction with the modem through the control channel once8181+ * firmware is loaded */8282+enum cxacru_cm_request {8383+ CM_REQUEST_UNDEFINED = 0x80,8484+ CM_REQUEST_TEST,8585+ CM_REQUEST_CHIP_GET_MAC_ADDRESS,8686+ CM_REQUEST_CHIP_GET_DP_VERSIONS,8787+ CM_REQUEST_CHIP_ADSL_LINE_START,8888+ CM_REQUEST_CHIP_ADSL_LINE_STOP,8989+ CM_REQUEST_CHIP_ADSL_LINE_GET_STATUS,9090+ CM_REQUEST_CHIP_ADSL_LINE_GET_SPEED,9191+ CM_REQUEST_CARD_INFO_GET,9292+ CM_REQUEST_CARD_DATA_GET,9393+ CM_REQUEST_CARD_DATA_SET,9494+ CM_REQUEST_COMMAND_HW_IO,9595+ CM_REQUEST_INTERFACE_HW_IO,9696+ CM_REQUEST_CARD_SERIAL_DATA_PATH_GET,9797+ CM_REQUEST_CARD_SERIAL_DATA_PATH_SET,9898+ CM_REQUEST_CARD_CONTROLLER_VERSION_GET,9999+ CM_REQUEST_CARD_GET_STATUS,100100+ CM_REQUEST_CARD_GET_MAC_ADDRESS,101101+ CM_REQUEST_CARD_GET_DATA_LINK_STATUS,102102+ CM_REQUEST_MAX,103103+};104104+105105+/* reply codes to the commands above */106106+enum cxacru_cm_status {107107+ CM_STATUS_UNDEFINED,108108+ CM_STATUS_SUCCESS,109109+ CM_STATUS_ERROR,110110+ CM_STATUS_UNSUPPORTED,111111+ CM_STATUS_UNIMPLEMENTED,112112+ CM_STATUS_PARAMETER_ERROR,113113+ CM_STATUS_DBG_LOOPBACK,114114+ CM_STATUS_MAX,115115+};116116+117117+/* indices into CARD_INFO_GET return array */118118+enum cxacru_info_idx {119119+ CXINF_DOWNSTREAM_RATE,120120+ CXINF_UPSTREAM_RATE,121121+ CXINF_LINK_STATUS,122122+ CXINF_LINE_STATUS,123123+ CXINF_MAC_ADDRESS_HIGH,124124+ CXINF_MAC_ADDRESS_LOW,125125+ CXINF_UPSTREAM_SNR_MARGIN,126126+ CXINF_DOWNSTREAM_SNR_MARGIN,127127+ CXINF_UPSTREAM_ATTENUATION,128128+ CXINF_DOWNSTREAM_ATTENUATION,129129+ CXINF_TRANSMITTER_POWER,130130+ CXINF_UPSTREAM_BITS_PER_FRAME,131131+ CXINF_DOWNSTREAM_BITS_PER_FRAME,132132+ CXINF_STARTUP_ATTEMPTS,133133+ CXINF_UPSTREAM_CRC_ERRORS,134134+ CXINF_DOWNSTREAM_CRC_ERRORS,135135+ CXINF_UPSTREAM_FEC_ERRORS,136136+ CXINF_DOWNSTREAM_FEC_ERRORS,137137+ CXINF_UPSTREAM_HEC_ERRORS,138138+ CXINF_DOWNSTREAM_HEC_ERRORS,139139+ CXINF_LINE_STARTABLE,140140+ CXINF_MODULATION,141141+ CXINF_ADSL_HEADEND,142142+ CXINF_ADSL_HEADEND_ENVIRONMENT,143143+ CXINF_CONTROLLER_VERSION,144144+ /* dunno what the missing two mean */145145+ CXINF_MAX = 0x1c,146146+};147147+148148+struct cxacru_modem_type {149149+ u32 pll_f_clk;150150+ u32 pll_b_clk;151151+ int boot_rom_patch;152152+};153153+154154+struct cxacru_data {155155+ struct usbatm_data *usbatm;156156+157157+ const struct cxacru_modem_type *modem_type;158158+159159+ int line_status;160160+ struct work_struct poll_work;161161+162162+ /* contol handles */163163+ struct semaphore cm_serialize;164164+ u8 *rcv_buf;165165+ u8 *snd_buf;166166+ struct urb *rcv_urb;167167+ struct urb *snd_urb;168168+ struct completion rcv_done;169169+ struct completion snd_done;170170+};171171+172172+/* the following three functions are stolen from drivers/usb/core/message.c */173173+static void cxacru_blocking_completion(struct urb *urb, struct pt_regs *regs)174174+{175175+ complete((struct completion *)urb->context);176176+}177177+178178+static void cxacru_timeout_kill(unsigned long data)179179+{180180+ usb_unlink_urb((struct urb *) data);181181+}182182+183183+static int cxacru_start_wait_urb(struct urb *urb, struct completion *done,184184+ int* actual_length)185185+{186186+ struct timer_list timer;187187+ int status;188188+189189+ init_timer(&timer);190190+ timer.expires = jiffies + msecs_to_jiffies(CMD_TIMEOUT);191191+ timer.data = (unsigned long) urb;192192+ timer.function = cxacru_timeout_kill;193193+ add_timer(&timer);194194+ wait_for_completion(done);195195+ status = urb->status;196196+ if (status == -ECONNRESET)197197+ status = -ETIMEDOUT;198198+ del_timer_sync(&timer);199199+200200+ if (actual_length)201201+ *actual_length = urb->actual_length;202202+ return status;203203+}204204+205205+static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm,206206+ u8 *wdata, int wsize, u8 *rdata, int rsize)207207+{208208+ int ret, actlen;209209+ int offb, offd;210210+ const int stride = CMD_PACKET_SIZE - 4;211211+ u8 *wbuf = instance->snd_buf;212212+ u8 *rbuf = instance->rcv_buf;213213+ int wbuflen = ((wsize - 1) / stride + 1) * CMD_PACKET_SIZE;214214+ int rbuflen = ((rsize - 1) / stride + 1) * CMD_PACKET_SIZE;215215+216216+ if (wbuflen > PAGE_SIZE || rbuflen > PAGE_SIZE) {217217+ dbg("too big transfer requested");218218+ ret = -ENOMEM;219219+ goto fail;220220+ }221221+222222+ down(&instance->cm_serialize);223223+224224+ /* submit reading urb before the writing one */225225+ init_completion(&instance->rcv_done);226226+ ret = usb_submit_urb(instance->rcv_urb, GFP_KERNEL);227227+ if (ret < 0) {228228+ dbg("submitting read urb for cm %#x failed", cm);229229+ ret = ret;230230+ goto fail;231231+ }232232+233233+ memset(wbuf, 0, wbuflen);234234+ /* handle wsize == 0 */235235+ wbuf[0] = cm;236236+ for (offb = offd = 0; offd < wsize; offd += stride, offb += CMD_PACKET_SIZE) {237237+ wbuf[offb] = cm;238238+ memcpy(wbuf + offb + 4, wdata + offd, min_t(int, stride, wsize - offd));239239+ }240240+241241+ instance->snd_urb->transfer_buffer_length = wbuflen;242242+ init_completion(&instance->snd_done);243243+ ret = usb_submit_urb(instance->snd_urb, GFP_KERNEL);244244+ if (ret < 0) {245245+ dbg("submitting write urb for cm %#x failed", cm);246246+ ret = ret;247247+ goto fail;248248+ }249249+250250+ ret = cxacru_start_wait_urb(instance->snd_urb, &instance->snd_done, NULL);251251+ if (ret < 0) {252252+ dbg("sending cm %#x failed", cm);253253+ ret = ret;254254+ goto fail;255255+ }256256+257257+ ret = cxacru_start_wait_urb(instance->rcv_urb, &instance->rcv_done, &actlen);258258+ if (ret < 0) {259259+ dbg("receiving cm %#x failed", cm);260260+ ret = ret;261261+ goto fail;262262+ }263263+ if (actlen % CMD_PACKET_SIZE || !actlen) {264264+ dbg("response is not a positive multiple of %d: %#x",265265+ CMD_PACKET_SIZE, actlen);266266+ ret = -EIO;267267+ goto fail;268268+ }269269+270270+ /* check the return status and copy the data to the output buffer, if needed */271271+ for (offb = offd = 0; offd < rsize && offb < actlen; offb += CMD_PACKET_SIZE) {272272+ if (rbuf[offb] != cm) {273273+ dbg("wrong cm %#x in response", rbuf[offb]);274274+ ret = -EIO;275275+ goto fail;276276+ }277277+ if (rbuf[offb + 1] != CM_STATUS_SUCCESS) {278278+ dbg("response failed: %#x", rbuf[offb + 1]);279279+ ret = -EIO;280280+ goto fail;281281+ }282282+ if (offd >= rsize)283283+ break;284284+ memcpy(rdata + offd, rbuf + offb + 4, min_t(int, stride, rsize - offd));285285+ offd += stride;286286+ }287287+288288+ ret = offd;289289+ dbg("cm %#x", cm);290290+fail:291291+ up(&instance->cm_serialize);292292+ return ret;293293+}294294+295295+static int cxacru_cm_get_array(struct cxacru_data *instance, enum cxacru_cm_request cm,296296+ u32 *data, int size)297297+{298298+ int ret, len;299299+ u32 *buf;300300+ int offb, offd;301301+ const int stride = CMD_PACKET_SIZE / (4 * 2) - 1;302302+ int buflen = ((size - 1) / stride + 1 + size * 2) * 4;303303+304304+ buf = kmalloc(buflen, GFP_KERNEL);305305+ if (!buf)306306+ return -ENOMEM;307307+308308+ ret = cxacru_cm(instance, cm, NULL, 0, (u8 *) buf, buflen);309309+ if (ret < 0)310310+ goto cleanup;311311+312312+ /* len > 0 && len % 4 == 0 guaranteed by cxacru_cm() */313313+ len = ret / 4;314314+ for (offb = 0; offb < len; ) {315315+ int l = le32_to_cpu(buf[offb++]);316316+ if (l > stride || l > (len - offb) / 2) {317317+ dbg("wrong data length %#x in response", l);318318+ ret = -EIO;319319+ goto cleanup;320320+ }321321+ while (l--) {322322+ offd = le32_to_cpu(buf[offb++]);323323+ if (offd >= size) {324324+ dbg("wrong index %#x in response", offd);325325+ ret = -EIO;326326+ goto cleanup;327327+ }328328+ data[offd] = le32_to_cpu(buf[offb++]);329329+ }330330+ }331331+332332+ ret = 0;333333+334334+cleanup:335335+ kfree(buf);336336+ return ret;337337+}338338+339339+static int cxacru_card_status(struct cxacru_data *instance)340340+{341341+ int ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_STATUS, NULL, 0, NULL, 0);342342+ if (ret < 0) { /* firmware not loaded */343343+ dbg("cxacru_adsl_start: CARD_GET_STATUS returned %d", ret);344344+ return ret;345345+ }346346+ return 0;347347+}348348+349349+static void cxacru_poll_status(struct cxacru_data *instance);350350+351351+static int cxacru_atm_start(struct usbatm_data *usbatm_instance,352352+ struct atm_dev *atm_dev)353353+{354354+ struct cxacru_data *instance = usbatm_instance->driver_data;355355+ struct device *dev = &usbatm_instance->usb_intf->dev;356356+ /*357357+ struct atm_dev *atm_dev = usbatm_instance->atm_dev;358358+ */359359+ int ret;360360+361361+ dbg("cxacru_atm_start");362362+363363+ /* Read MAC address */364364+ ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_MAC_ADDRESS, NULL, 0,365365+ atm_dev->esi, sizeof(atm_dev->esi));366366+ if (ret < 0) {367367+ dev_err(dev, "cxacru_atm_start: CARD_GET_MAC_ADDRESS returned %d\n", ret);368368+ return ret;369369+ }370370+371371+ /* start ADSL */372372+ ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_START, NULL, 0, NULL, 0);373373+ if (ret < 0) {374374+ dev_err(dev, "cxacru_atm_start: CHIP_ADSL_LINE_START returned %d\n", ret);375375+ return ret;376376+ }377377+378378+ /* Start status polling */379379+ cxacru_poll_status(instance);380380+ return 0;381381+}382382+383383+static void cxacru_poll_status(struct cxacru_data *instance)384384+{385385+ u32 buf[CXINF_MAX] = {};386386+ struct device *dev = &instance->usbatm->usb_intf->dev;387387+ struct atm_dev *atm_dev = instance->usbatm->atm_dev;388388+ int ret;389389+390390+ ret = cxacru_cm_get_array(instance, CM_REQUEST_CARD_INFO_GET, buf, CXINF_MAX);391391+ if (ret < 0) {392392+ dev_warn(dev, "poll status: error %d\n", ret);393393+ goto reschedule;394394+ }395395+396396+ if (instance->line_status == buf[CXINF_LINE_STATUS])397397+ goto reschedule;398398+399399+ instance->line_status = buf[CXINF_LINE_STATUS];400400+ switch (instance->line_status) {401401+ case 0:402402+ atm_dev->signal = ATM_PHY_SIG_LOST;403403+ dev_info(dev, "ADSL line: down\n");404404+ break;405405+406406+ case 1:407407+ atm_dev->signal = ATM_PHY_SIG_LOST;408408+ dev_info(dev, "ADSL line: attemtping to activate\n");409409+ break;410410+411411+ case 2:412412+ atm_dev->signal = ATM_PHY_SIG_LOST;413413+ dev_info(dev, "ADSL line: training\n");414414+ break;415415+416416+ case 3:417417+ atm_dev->signal = ATM_PHY_SIG_LOST;418418+ dev_info(dev, "ADSL line: channel analysis\n");419419+ break;420420+421421+ case 4:422422+ atm_dev->signal = ATM_PHY_SIG_LOST;423423+ dev_info(dev, "ADSL line: exchange\n");424424+ break;425425+426426+ case 5:427427+ atm_dev->link_rate = buf[CXINF_DOWNSTREAM_RATE] * 1000 / 424;428428+ atm_dev->signal = ATM_PHY_SIG_FOUND;429429+430430+ dev_info(dev, "ADSL line: up (%d Kib/s down | %d Kib/s up)\n",431431+ buf[CXINF_DOWNSTREAM_RATE], buf[CXINF_UPSTREAM_RATE]);432432+ break;433433+434434+ case 6:435435+ atm_dev->signal = ATM_PHY_SIG_LOST;436436+ dev_info(dev, "ADSL line: waiting\n");437437+ break;438438+439439+ case 7:440440+ atm_dev->signal = ATM_PHY_SIG_LOST;441441+ dev_info(dev, "ADSL line: initializing\n");442442+ break;443443+444444+ default:445445+ atm_dev->signal = ATM_PHY_SIG_UNKNOWN;446446+ dev_info(dev, "Unknown line state %02x\n", instance->line_status);447447+ break;448448+ }449449+reschedule:450450+ schedule_delayed_work(&instance->poll_work, msecs_to_jiffies(POLL_INTERVAL));451451+}452452+453453+static int cxacru_fw(struct usb_device *usb_dev, enum cxacru_fw_request fw,454454+ u8 code1, u8 code2, u32 addr, u8 *data, int size)455455+{456456+ int ret;457457+ u8 *buf;458458+ int offd, offb;459459+ const int stride = CMD_PACKET_SIZE - 8;460460+461461+ buf = (u8 *) __get_free_page(GFP_KERNEL);462462+ if (!buf)463463+ return -ENOMEM;464464+465465+ offb = offd = 0;466466+ do {467467+ int l = min_t(int, stride, size - offd);468468+ buf[offb++] = fw;469469+ buf[offb++] = l;470470+ buf[offb++] = code1;471471+ buf[offb++] = code2;472472+ *((u32 *) (buf + offb)) = cpu_to_le32(addr);473473+ offb += 4;474474+ addr += l;475475+ if(l)476476+ memcpy(buf + offb, data + offd, l);477477+ if (l < stride)478478+ memset(buf + offb + l, 0, stride - l);479479+ offb += stride;480480+ offd += stride;481481+ if ((offb >= PAGE_SIZE) || (offd >= size)) {482482+ ret = usb_bulk_msg(usb_dev, usb_sndbulkpipe(usb_dev, CXACRU_EP_CMD),483483+ buf, offb, NULL, CMD_TIMEOUT);484484+ if (ret < 0) {485485+ dbg("sending fw %#x failed", fw);486486+ goto cleanup;487487+ }488488+ offb = 0;489489+ }490490+ } while(offd < size);491491+ dbg("sent fw %#x", fw);492492+493493+ ret = 0;494494+495495+cleanup:496496+ free_page((unsigned long) buf);497497+ return ret;498498+}499499+500500+static void cxacru_upload_firmware(struct cxacru_data *instance,501501+ const struct firmware *fw,502502+ const struct firmware *bp,503503+ const struct firmware *cf)504504+{505505+ int ret;506506+ int off;507507+ struct usb_device *usb_dev = instance->usbatm->usb_dev;508508+ struct device *dev = &instance->usbatm->usb_intf->dev;509509+ u16 signature[] = { usb_dev->descriptor.idVendor, usb_dev->descriptor.idProduct };510510+ u32 val;511511+512512+ dbg("cxacru_upload_firmware");513513+514514+ /* FirmwarePllFClkValue */515515+ val = cpu_to_le32(instance->modem_type->pll_f_clk);516516+ ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLFCLK_ADDR, (u8 *) &val, 4);517517+ if (ret) {518518+ dev_err(dev, "FirmwarePllFClkValue failed: %d\n", ret);519519+ return;520520+ }521521+522522+ /* FirmwarePllBClkValue */523523+ val = cpu_to_le32(instance->modem_type->pll_b_clk);524524+ ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLBCLK_ADDR, (u8 *) &val, 4);525525+ if (ret) {526526+ dev_err(dev, "FirmwarePllBClkValue failed: %d\n", ret);527527+ return;528528+ }529529+530530+ /* Enable SDRAM */531531+ val = cpu_to_le32(SDRAM_ENA);532532+ ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SDRAMEN_ADDR, (u8 *) &val, 4);533533+ if (ret) {534534+ dev_err(dev, "Enable SDRAM failed: %d\n", ret);535535+ return;536536+ }537537+538538+ /* Firmware */539539+ ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, FW_ADDR, fw->data, fw->size);540540+ if (ret) {541541+ dev_err(dev, "Firmware upload failed: %d\n", ret);542542+ return;543543+ }544544+545545+ /* Boot ROM patch */546546+ if (instance->modem_type->boot_rom_patch) {547547+ ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_ADDR, bp->data, bp->size);548548+ if (ret) {549549+ dev_err(dev, "Boot ROM patching failed: %d\n", ret);550550+ return;551551+ }552552+ }553553+554554+ /* Signature */555555+ ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SIG_ADDR, (u8 *) signature, 4);556556+ if (ret) {557557+ dev_err(dev, "Signature storing failed: %d\n", ret);558558+ return;559559+ }560560+561561+ if (instance->modem_type->boot_rom_patch) {562562+ val = cpu_to_le32(BR_ADDR);563563+ ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_STACK_ADDR, (u8 *) &val, 4);564564+ }565565+ else {566566+ ret = cxacru_fw(usb_dev, FW_GOTO_MEM, 0x0, 0x0, FW_ADDR, NULL, 0);567567+ }568568+ if (ret) {569569+ dev_err(dev, "Passing control to firmware failed: %d\n", ret);570570+ return;571571+ }572572+573573+ /* Delay to allow firmware to start up. */574574+ msleep_interruptible(1000);575575+576576+ usb_clear_halt(usb_dev, usb_sndbulkpipe(usb_dev, CXACRU_EP_CMD));577577+ usb_clear_halt(usb_dev, usb_rcvbulkpipe(usb_dev, CXACRU_EP_CMD));578578+ usb_clear_halt(usb_dev, usb_sndbulkpipe(usb_dev, CXACRU_EP_DATA));579579+ usb_clear_halt(usb_dev, usb_rcvbulkpipe(usb_dev, CXACRU_EP_DATA));580580+581581+ ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_STATUS, NULL, 0, NULL, 0);582582+ if (ret < 0) {583583+ dev_err(dev, "modem failed to initialize: %d\n", ret);584584+ return;585585+ }586586+587587+ /* Load config data (le32), doing one packet at a time */588588+ if (cf)589589+ for (off = 0; off < cf->size / 4; ) {590590+ u32 buf[CMD_PACKET_SIZE / 4 - 1];591591+ int i, len = min_t(int, cf->size / 4 - off, CMD_PACKET_SIZE / 4 / 2 - 1);592592+ buf[0] = cpu_to_le32(len);593593+ for (i = 0; i < len; i++, off++) {594594+ buf[i * 2 + 1] = cpu_to_le32(off);595595+ memcpy(buf + i * 2 + 2, cf->data + off * 4, 4);596596+ }597597+ ret = cxacru_cm(instance, CM_REQUEST_CARD_DATA_SET,598598+ (u8 *) buf, len, NULL, 0);599599+ if (ret < 0) {600600+ dev_err(dev, "load config data failed: %d\n", ret);601601+ return;602602+ }603603+ }604604+605605+ msleep_interruptible(4000);606606+}607607+608608+static int cxacru_find_firmware(struct cxacru_data *instance,609609+ char* phase, const struct firmware **fw_p)610610+{611611+ struct device *dev = &instance->usbatm->usb_intf->dev;612612+ char buf[16];613613+614614+ sprintf(buf, "cxacru-%s.bin", phase);615615+ dbg("cxacru_find_firmware: looking for %s", buf);616616+617617+ if (request_firmware(fw_p, buf, dev)) {618618+ dev_dbg(dev, "no stage %s firmware found\n", phase);619619+ return -ENOENT;620620+ }621621+622622+ dev_info(dev, "found firmware %s\n", buf);623623+624624+ return 0;625625+}626626+627627+static int cxacru_heavy_init(struct usbatm_data *usbatm_instance,628628+ struct usb_interface *usb_intf)629629+{630630+ struct device *dev = &usbatm_instance->usb_intf->dev;631631+ const struct firmware *fw, *bp, *cf;632632+ struct cxacru_data *instance = usbatm_instance->driver_data;633633+634634+ int ret = cxacru_find_firmware(instance, "fw", &fw);635635+ if (ret) {636636+ dev_warn(dev, "firmware (cxacru-fw.bin) unavailable (hotplug misconfiguration?)\n");637637+ return ret;638638+ }639639+640640+ if (instance->modem_type->boot_rom_patch) {641641+ ret = cxacru_find_firmware(instance, "bp", &bp);642642+ if (ret) {643643+ dev_warn(dev, "boot ROM patch (cxacru-bp.bin) unavailable (hotplug misconfiguration?)\n");644644+ release_firmware(fw);645645+ return ret;646646+ }647647+ }648648+649649+ if (cxacru_find_firmware(instance, "cf", &cf)) /* optional */650650+ cf = NULL;651651+652652+ cxacru_upload_firmware(instance, fw, bp, cf);653653+654654+ if (cf)655655+ release_firmware(cf);656656+ if (instance->modem_type->boot_rom_patch)657657+ release_firmware(bp);658658+ release_firmware(fw);659659+660660+ ret = cxacru_card_status(instance);661661+ if (ret)662662+ dbg("modem initialisation failed");663663+ else664664+ dbg("done setting up the modem");665665+666666+ return ret;667667+}668668+669669+static int cxacru_bind(struct usbatm_data *usbatm_instance,670670+ struct usb_interface *intf, const struct usb_device_id *id,671671+ int *need_heavy_init)672672+{673673+ struct cxacru_data *instance;674674+ struct usb_device *usb_dev = interface_to_usbdev(intf);675675+ int ret;676676+677677+ /* instance init */678678+ instance = kmalloc(sizeof(*instance), GFP_KERNEL);679679+ if (!instance) {680680+ dbg("cxacru_bind: no memory for instance data");681681+ return -ENOMEM;682682+ }683683+684684+ memset(instance, 0, sizeof(*instance));685685+686686+ instance->usbatm = usbatm_instance;687687+ instance->modem_type = (struct cxacru_modem_type *) id->driver_info;688688+689689+ instance->rcv_buf = (u8 *) __get_free_page(GFP_KERNEL);690690+ if (!instance->rcv_buf) {691691+ dbg("cxacru_bind: no memory for rcv_buf");692692+ ret = -ENOMEM;693693+ goto fail;694694+ }695695+ instance->snd_buf = (u8 *) __get_free_page(GFP_KERNEL);696696+ if (!instance->snd_buf) {697697+ dbg("cxacru_bind: no memory for snd_buf");698698+ ret = -ENOMEM;699699+ goto fail;700700+ }701701+ instance->rcv_urb = usb_alloc_urb(0, GFP_KERNEL);702702+ if (!instance->rcv_urb) {703703+ dbg("cxacru_bind: no memory for rcv_urb");704704+ ret = -ENOMEM;705705+ goto fail;706706+ }707707+ instance->snd_urb = usb_alloc_urb(0, GFP_KERNEL);708708+ if (!instance->snd_urb) {709709+ dbg("cxacru_bind: no memory for snd_urb");710710+ ret = -ENOMEM;711711+ goto fail;712712+ }713713+714714+ usb_fill_int_urb(instance->rcv_urb,715715+ usb_dev, usb_rcvintpipe(usb_dev, CXACRU_EP_CMD),716716+ instance->rcv_buf, PAGE_SIZE,717717+ cxacru_blocking_completion, &instance->rcv_done, 1);718718+ instance->rcv_urb->transfer_flags |= URB_ASYNC_UNLINK;719719+720720+ usb_fill_int_urb(instance->snd_urb,721721+ usb_dev, usb_sndintpipe(usb_dev, CXACRU_EP_CMD),722722+ instance->snd_buf, PAGE_SIZE,723723+ cxacru_blocking_completion, &instance->snd_done, 4);724724+ instance->snd_urb->transfer_flags |= URB_ASYNC_UNLINK;725725+726726+ init_MUTEX(&instance->cm_serialize);727727+728728+ INIT_WORK(&instance->poll_work, (void *)cxacru_poll_status, instance);729729+730730+ usbatm_instance->driver_data = instance;731731+732732+ *need_heavy_init = cxacru_card_status(instance);733733+734734+ return 0;735735+736736+ fail:737737+ free_page((unsigned long) instance->snd_buf);738738+ free_page((unsigned long) instance->rcv_buf);739739+ usb_free_urb(instance->snd_urb);740740+ usb_free_urb(instance->rcv_urb);741741+ kfree(instance);742742+743743+ return ret;744744+}745745+746746+static void cxacru_unbind(struct usbatm_data *usbatm_instance,747747+ struct usb_interface *intf)748748+{749749+ struct cxacru_data *instance = usbatm_instance->driver_data;750750+751751+ dbg("cxacru_unbind entered");752752+753753+ if (!instance) {754754+ dbg("cxacru_unbind: NULL instance!");755755+ return;756756+ }757757+758758+ while (!cancel_delayed_work(&instance->poll_work))759759+ flush_scheduled_work();760760+761761+ usb_kill_urb(instance->snd_urb);762762+ usb_kill_urb(instance->rcv_urb);763763+ usb_free_urb(instance->snd_urb);764764+ usb_free_urb(instance->rcv_urb);765765+766766+ free_page((unsigned long) instance->snd_buf);767767+ free_page((unsigned long) instance->rcv_buf);768768+ kfree(instance);769769+770770+ usbatm_instance->driver_data = NULL;771771+}772772+773773+static const struct cxacru_modem_type cxacru_cafe = {774774+ .pll_f_clk = 0x02d874df,775775+ .pll_b_clk = 0x0196a51a,776776+ .boot_rom_patch = 1,777777+};778778+779779+static const struct cxacru_modem_type cxacru_cb00 = {780780+ .pll_f_clk = 0x5,781781+ .pll_b_clk = 0x3,782782+ .boot_rom_patch = 0,783783+};784784+785785+static const struct usb_device_id cxacru_usb_ids[] = {786786+ { /* V = Conexant P = ADSL modem (Euphrates project) */787787+ USB_DEVICE(0x0572, 0xcafe), .driver_info = (unsigned long) &cxacru_cafe788788+ },789789+ { /* V = Conexant P = ADSL modem (Hasbani project) */790790+ USB_DEVICE(0x0572, 0xcb00), .driver_info = (unsigned long) &cxacru_cb00791791+ },792792+ { /* V = Conexant P = ADSL modem */793793+ USB_DEVICE(0x0572, 0xcb01), .driver_info = (unsigned long) &cxacru_cb00794794+ },795795+ { /* V = Conexant P = ADSL modem */796796+ USB_DEVICE(0x0572, 0xcb06), .driver_info = (unsigned long) &cxacru_cb00797797+ },798798+ { /* V = Olitec P = ADSL modem version 2 */799799+ USB_DEVICE(0x08e3, 0x0100), .driver_info = (unsigned long) &cxacru_cafe800800+ },801801+ { /* V = Olitec P = ADSL modem version 3 */802802+ USB_DEVICE(0x08e3, 0x0102), .driver_info = (unsigned long) &cxacru_cb00803803+ },804804+ { /* V = Trust/Amigo Technology Co. P = AMX-CA86U */805805+ USB_DEVICE(0x0eb0, 0x3457), .driver_info = (unsigned long) &cxacru_cafe806806+ },807807+ { /* V = Zoom P = 5510 */808808+ USB_DEVICE(0x1803, 0x5510), .driver_info = (unsigned long) &cxacru_cb00809809+ },810810+ { /* V = Draytek P = Vigor 318 */811811+ USB_DEVICE(0x0675, 0x0200), .driver_info = (unsigned long) &cxacru_cb00812812+ },813813+ { /* V = Zyxel P = 630-C1 aka OMNI ADSL USB (Annex A) */814814+ USB_DEVICE(0x0586, 0x330a), .driver_info = (unsigned long) &cxacru_cb00815815+ },816816+ { /* V = Zyxel P = 630-C3 aka OMNI ADSL USB (Annex B) */817817+ USB_DEVICE(0x0586, 0x330b), .driver_info = (unsigned long) &cxacru_cb00818818+ },819819+ { /* V = Aethra P = Starmodem UM1020 */820820+ USB_DEVICE(0x0659, 0x0020), .driver_info = (unsigned long) &cxacru_cb00821821+ },822822+ { /* V = Aztech Systems P = ? AKA Pirelli AUA-010 */823823+ USB_DEVICE(0x0509, 0x0812), .driver_info = (unsigned long) &cxacru_cb00824824+ },825825+ { /* V = Netopia P = Cayman 3341(Annex A)/3351(Annex B) */826826+ USB_DEVICE(0x100d, 0xcb01), .driver_info = (unsigned long) &cxacru_cb00827827+ },828828+ { /* V = Netopia P = Cayman 3342(Annex A)/3352(Annex B) */829829+ USB_DEVICE(0x100d, 0x3342), .driver_info = (unsigned long) &cxacru_cb00830830+ },831831+ {}832832+};833833+834834+MODULE_DEVICE_TABLE(usb, cxacru_usb_ids);835835+836836+static struct usbatm_driver cxacru_driver = {837837+ .owner = THIS_MODULE,838838+ .driver_name = cxacru_driver_name,839839+ .bind = cxacru_bind,840840+ .heavy_init = cxacru_heavy_init,841841+ .unbind = cxacru_unbind,842842+ .atm_start = cxacru_atm_start,843843+ .in = CXACRU_EP_DATA,844844+ .out = CXACRU_EP_DATA,845845+ .rx_padding = 3,846846+ .tx_padding = 11,847847+};848848+849849+static int cxacru_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)850850+{851851+ return usbatm_usb_probe(intf, id, &cxacru_driver);852852+}853853+854854+static struct usb_driver cxacru_usb_driver = {855855+ .owner = THIS_MODULE,856856+ .name = cxacru_driver_name,857857+ .probe = cxacru_usb_probe,858858+ .disconnect = usbatm_usb_disconnect,859859+ .id_table = cxacru_usb_ids860860+};861861+862862+static int __init cxacru_init(void)863863+{864864+ return usb_register(&cxacru_usb_driver);865865+}866866+867867+static void __exit cxacru_cleanup(void)868868+{869869+ usb_deregister(&cxacru_usb_driver);870870+}871871+872872+module_init(cxacru_init);873873+module_exit(cxacru_cleanup);874874+875875+MODULE_AUTHOR(DRIVER_AUTHOR);876876+MODULE_DESCRIPTION(DRIVER_DESC);877877+MODULE_LICENSE("GPL");878878+MODULE_VERSION(DRIVER_VERSION);
+549-570
drivers/usb/atm/speedtch.c
···55 * Copyright (C) 2003, Duncan Sands66 * Copyright (C) 2004, David Woodhouse77 *88+ * Based on "modem_run.c", copyright (C) 2001, Benoit Papillault99+ *810 * This program is free software; you can redistribute it and/or modify it911 * under the terms of the GNU General Public License as published by the Free1012 * Software Foundation; either version 2 of the License, or (at your option)···2321 *2422 ******************************************************************************/25232424+#include <asm/page.h>2525+#include <linux/device.h>2626+#include <linux/errno.h>2727+#include <linux/firmware.h>2828+#include <linux/gfp.h>2929+#include <linux/init.h>3030+#include <linux/kernel.h>2631#include <linux/module.h>2732#include <linux/moduleparam.h>2828-#include <linux/gfp.h>2929-#include <linux/kernel.h>3030-#include <linux/sched.h>3131-#include <linux/timer.h>3232-#include <linux/errno.h>3333-#include <linux/proc_fs.h>3433#include <linux/slab.h>3535-#include <linux/wait.h>3636-#include <linux/list.h>3737-#include <asm/processor.h>3838-#include <asm/uaccess.h>3939-#include <linux/smp_lock.h>4040-#include <linux/interrupt.h>4141-#include <linux/atm.h>4242-#include <linux/atmdev.h>4343-#include <linux/crc32.h>4444-#include <linux/init.h>4545-#include <linux/firmware.h>3434+#include <linux/stat.h>3535+#include <linux/timer.h>3636+#include <linux/workqueue.h>46374747-#include "usb_atm.h"4848-4949-#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)5050-# define USE_FW_LOADER5151-#endif3838+#include "usbatm.h"52395340#define DRIVER_AUTHOR "Johan Verrept, Duncan Sands <duncan.sands@free.fr>"5454-#define DRIVER_VERSION "1.8"4141+#define DRIVER_VERSION "1.9"5542#define DRIVER_DESC "Alcatel SpeedTouch USB driver version " DRIVER_VERSION56435744static const char speedtch_driver_name[] = "speedtch";58455959-#define SPEEDTOUCH_VENDORID 0x06b96060-#define SPEEDTOUCH_PRODUCTID 0x40614646+#define CTRL_TIMEOUT 2000 /* milliseconds */4747+#define DATA_TIMEOUT 2000 /* milliseconds */61486262-/* Timeout in jiffies */6363-#define CTRL_TIMEOUT 20006464-#define DATA_TIMEOUT 20004949+#define OFFSET_7 0 /* size 1 */5050+#define OFFSET_b 1 /* size 8 */5151+#define OFFSET_d 9 /* size 4 */5252+#define OFFSET_e 13 /* size 1 */5353+#define OFFSET_f 14 /* size 1 */5454+#define TOTAL 1565556666-#define OFFSET_7 0 /* size 1 */6767-#define OFFSET_b 1 /* size 8 */6868-#define OFFSET_d 9 /* size 4 */6969-#define OFFSET_e 13 /* size 1 */7070-#define OFFSET_f 14 /* size 1 */7171-#define TOTAL 155656+#define SIZE_7 15757+#define SIZE_b 85858+#define SIZE_d 45959+#define SIZE_e 16060+#define SIZE_f 172617373-#define SIZE_7 17474-#define SIZE_b 87575-#define SIZE_d 47676-#define SIZE_e 17777-#define SIZE_f 16262+#define MIN_POLL_DELAY 5000 /* milliseconds */6363+#define MAX_POLL_DELAY 60000 /* milliseconds */78647979-static int dl_512_first = 0;8080-static int sw_buffering = 0;6565+#define RESUBMIT_DELAY 1000 /* milliseconds */81668282-module_param(dl_512_first, bool, 0444);8383-MODULE_PARM_DESC(dl_512_first, "Read 512 bytes before sending firmware");6767+#define DEFAULT_ALTSETTING 16868+#define DEFAULT_DL_512_FIRST 06969+#define DEFAULT_SW_BUFFERING 084708585-module_param(sw_buffering, uint, 0444);8686-MODULE_PARM_DESC(sw_buffering, "Enable software buffering");7171+static int altsetting = DEFAULT_ALTSETTING;7272+static int dl_512_first = DEFAULT_DL_512_FIRST;7373+static int sw_buffering = DEFAULT_SW_BUFFERING;87748888-#define UDSL_IOCTL_LINE_UP 18989-#define UDSL_IOCTL_LINE_DOWN 27575+module_param(altsetting, int, S_IRUGO | S_IWUSR);7676+MODULE_PARM_DESC(altsetting,7777+ "Alternative setting for data interface (default: "7878+ __MODULE_STRING(DEFAULT_ALTSETTING) ")");90799191-#define SPEEDTCH_ENDPOINT_INT 0x819292-#define SPEEDTCH_ENDPOINT_DATA 0x079393-#define SPEEDTCH_ENDPOINT_FIRMWARE 0x058080+module_param(dl_512_first, bool, S_IRUGO | S_IWUSR);8181+MODULE_PARM_DESC(dl_512_first,8282+ "Read 512 bytes before sending firmware (default: "8383+ __MODULE_STRING(DEFAULT_DL_512_FIRST) ")");8484+8585+module_param(sw_buffering, bool, S_IRUGO | S_IWUSR);8686+MODULE_PARM_DESC(sw_buffering,8787+ "Enable software buffering (default: "8888+ __MODULE_STRING(DEFAULT_SW_BUFFERING) ")");8989+9090+#define ENDPOINT_INT 0x819191+#define ENDPOINT_DATA 0x079292+#define ENDPOINT_FIRMWARE 0x0594939594#define hex2int(c) ( (c >= '0') && (c <= '9') ? (c - '0') : ((c & 0xf) + 9) )96959797-static struct usb_device_id speedtch_usb_ids[] = {9898- {USB_DEVICE(SPEEDTOUCH_VENDORID, SPEEDTOUCH_PRODUCTID)},9999- {}100100-};101101-102102-MODULE_DEVICE_TABLE(usb, speedtch_usb_ids);103103-10496struct speedtch_instance_data {105105- struct udsl_instance_data u;9797+ struct usbatm_data *usbatm;10698107107- /* Status */9999+ struct work_struct status_checker;100100+101101+ int poll_delay; /* milliseconds */102102+103103+ struct timer_list resubmit_timer;108104 struct urb *int_urb;109105 unsigned char int_data[16];110110- struct work_struct poll_work;111111- struct timer_list poll_timer;112112-};113113-/* USB */114106115115-static int speedtch_usb_probe(struct usb_interface *intf,116116- const struct usb_device_id *id);117117-static void speedtch_usb_disconnect(struct usb_interface *intf);118118-static int speedtch_usb_ioctl(struct usb_interface *intf, unsigned int code,119119- void *user_data);120120-static void speedtch_handle_int(struct urb *urb, struct pt_regs *regs);121121-static void speedtch_poll_status(struct speedtch_instance_data *instance);122122-123123-static struct usb_driver speedtch_usb_driver = {124124- .owner = THIS_MODULE,125125- .name = speedtch_driver_name,126126- .probe = speedtch_usb_probe,127127- .disconnect = speedtch_usb_disconnect,128128- .ioctl = speedtch_usb_ioctl,129129- .id_table = speedtch_usb_ids,107107+ unsigned char scratch_buffer[TOTAL];130108};131109132110/***************133111** firmware **134112***************/135113136136-static void speedtch_got_firmware(struct speedtch_instance_data *instance,137137- int got_it)114114+static void speedtch_set_swbuff(struct speedtch_instance_data *instance, int state)138115{139139- int err;140140- struct usb_interface *intf;141141-142142- down(&instance->u.serialize); /* vs self, speedtch_firmware_start */143143- if (instance->u.status == UDSL_LOADED_FIRMWARE)144144- goto out;145145- if (!got_it) {146146- instance->u.status = UDSL_NO_FIRMWARE;147147- goto out;148148- }149149- if ((err = usb_set_interface(instance->u.usb_dev, 1, 1)) < 0) {150150- dbg("speedtch_got_firmware: usb_set_interface returned %d!", err);151151- instance->u.status = UDSL_NO_FIRMWARE;152152- goto out;153153- }154154-155155- /* Set up interrupt endpoint */156156- intf = usb_ifnum_to_if(instance->u.usb_dev, 0);157157- if (intf && !usb_driver_claim_interface(&speedtch_usb_driver, intf, NULL)) {158158-159159- instance->int_urb = usb_alloc_urb(0, GFP_KERNEL);160160- if (instance->int_urb) {161161-162162- usb_fill_int_urb(instance->int_urb, instance->u.usb_dev,163163- usb_rcvintpipe(instance->u.usb_dev, SPEEDTCH_ENDPOINT_INT),164164- instance->int_data,165165- sizeof(instance->int_data),166166- speedtch_handle_int, instance, 50);167167- err = usb_submit_urb(instance->int_urb, GFP_KERNEL);168168- if (err) {169169- /* Doesn't matter; we'll poll anyway */170170- dbg("speedtch_got_firmware: Submission of interrupt URB failed %d", err);171171- usb_free_urb(instance->int_urb);172172- instance->int_urb = NULL;173173- usb_driver_release_interface(&speedtch_usb_driver, intf);174174- }175175- }176176- }177177- /* Start status polling */178178- mod_timer(&instance->poll_timer, jiffies + (1 * HZ));179179-180180- instance->u.status = UDSL_LOADED_FIRMWARE;181181- tasklet_schedule(&instance->u.receive_tasklet);182182- out:183183- up(&instance->u.serialize);184184- wake_up_interruptible(&instance->u.firmware_waiters);185185-}186186-187187-static int speedtch_set_swbuff(struct speedtch_instance_data *instance,188188- int state)189189-{190190- struct usb_device *dev = instance->u.usb_dev;116116+ struct usbatm_data *usbatm = instance->usbatm;117117+ struct usb_device *usb_dev = usbatm->usb_dev;191118 int ret;192119193193- ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),194194- 0x32, 0x40, state ? 0x01 : 0x00,195195- 0x00, NULL, 0, 100);196196- if (ret < 0) {197197- printk("Warning: %sabling SW buffering: usb_control_msg returned %d\n",198198- state ? "En" : "Dis", ret);199199- return ret;200200- }201201-202202- dbg("speedtch_set_swbuff: %sbled SW buffering", state ? "En" : "Dis");203203- return 0;120120+ ret = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),121121+ 0x32, 0x40, state ? 0x01 : 0x00, 0x00, NULL, 0, CTRL_TIMEOUT);122122+ if (ret < 0)123123+ usb_warn(usbatm,124124+ "%sabling SW buffering: usb_control_msg returned %d\n",125125+ state ? "En" : "Dis", ret);126126+ else127127+ dbg("speedtch_set_swbuff: %sbled SW buffering", state ? "En" : "Dis");204128}205129206130static void speedtch_test_sequence(struct speedtch_instance_data *instance)207131{208208- struct usb_device *dev = instance->u.usb_dev;209209- unsigned char buf[10];132132+ struct usbatm_data *usbatm = instance->usbatm;133133+ struct usb_device *usb_dev = usbatm->usb_dev;134134+ unsigned char *buf = instance->scratch_buffer;210135 int ret;211136212137 /* URB 147 */213138 buf[0] = 0x1c;214139 buf[1] = 0x50;215215- ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),216216- 0x01, 0x40, 0x0b, 0x00, buf, 2, 100);140140+ ret = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),141141+ 0x01, 0x40, 0x0b, 0x00, buf, 2, CTRL_TIMEOUT);217142 if (ret < 0)218218- printk(KERN_WARNING "%s failed on URB147: %d\n", __func__, ret);143143+ usb_warn(usbatm, "%s failed on URB147: %d\n", __func__, ret);219144220145 /* URB 148 */221146 buf[0] = 0x32;222147 buf[1] = 0x00;223223- ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),224224- 0x01, 0x40, 0x02, 0x00, buf, 2, 100);148148+ ret = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),149149+ 0x01, 0x40, 0x02, 0x00, buf, 2, CTRL_TIMEOUT);225150 if (ret < 0)226226- printk(KERN_WARNING "%s failed on URB148: %d\n", __func__, ret);151151+ usb_warn(usbatm, "%s failed on URB148: %d\n", __func__, ret);227152228153 /* URB 149 */229154 buf[0] = 0x01;230155 buf[1] = 0x00;231156 buf[2] = 0x01;232232- ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),233233- 0x01, 0x40, 0x03, 0x00, buf, 3, 100);157157+ ret = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),158158+ 0x01, 0x40, 0x03, 0x00, buf, 3, CTRL_TIMEOUT);234159 if (ret < 0)235235- printk(KERN_WARNING "%s failed on URB149: %d\n", __func__, ret);160160+ usb_warn(usbatm, "%s failed on URB149: %d\n", __func__, ret);236161237162 /* URB 150 */238163 buf[0] = 0x01;239164 buf[1] = 0x00;240165 buf[2] = 0x01;241241- ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),242242- 0x01, 0x40, 0x04, 0x00, buf, 3, 100);166166+ ret = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),167167+ 0x01, 0x40, 0x04, 0x00, buf, 3, CTRL_TIMEOUT);243168 if (ret < 0)244244- printk(KERN_WARNING "%s failed on URB150: %d\n", __func__, ret);169169+ usb_warn(usbatm, "%s failed on URB150: %d\n", __func__, ret);245170}246171247247-static int speedtch_start_synchro(struct speedtch_instance_data *instance)248248-{249249- struct usb_device *dev = instance->u.usb_dev;250250- unsigned char buf[2];251251- int ret;252252-253253- ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),254254- 0x12, 0xc0, 0x04, 0x00,255255- buf, sizeof(buf), CTRL_TIMEOUT);256256- if (ret < 0) {257257- printk(KERN_WARNING "SpeedTouch: Failed to start ADSL synchronisation: %d\n", ret);258258- return ret;259259- }260260-261261- dbg("speedtch_start_synchro: modem prodded. %d Bytes returned: %02x %02x", ret, buf[0], buf[1]);262262- return 0;263263-}264264-265265-static void speedtch_handle_int(struct urb *urb, struct pt_regs *regs)266266-{267267- struct speedtch_instance_data *instance = urb->context;268268- unsigned int count = urb->actual_length;269269- int ret;270270-271271- /* The magic interrupt for "up state" */272272- const static unsigned char up_int[6] = { 0xa1, 0x00, 0x01, 0x00, 0x00, 0x00 };273273- /* The magic interrupt for "down state" */274274- const static unsigned char down_int[6] = { 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00 };275275-276276- switch (urb->status) {277277- case 0:278278- /* success */279279- break;280280- case -ECONNRESET:281281- case -ENOENT:282282- case -ESHUTDOWN:283283- /* this urb is terminated; clean up */284284- dbg("%s - urb shutting down with status: %d", __func__, urb->status);285285- return;286286- default:287287- dbg("%s - nonzero urb status received: %d", __func__, urb->status);288288- goto exit;289289- }290290-291291- if (count < 6) {292292- dbg("%s - int packet too short", __func__);293293- goto exit;294294- }295295-296296- if (!memcmp(up_int, instance->int_data, 6)) {297297- del_timer(&instance->poll_timer);298298- printk(KERN_NOTICE "DSL line goes up\n");299299- } else if (!memcmp(down_int, instance->int_data, 6)) {300300- printk(KERN_NOTICE "DSL line goes down\n");301301- } else {302302- int i;303303-304304- printk(KERN_DEBUG "Unknown interrupt packet of %d bytes:", count);305305- for (i = 0; i < count; i++)306306- printk(" %02x", instance->int_data[i]);307307- printk("\n");308308- }309309- schedule_work(&instance->poll_work);310310-311311- exit:312312- rmb();313313- if (!instance->int_urb)314314- return;315315-316316- ret = usb_submit_urb(urb, GFP_ATOMIC);317317- if (ret)318318- err("%s - usb_submit_urb failed with result %d", __func__, ret);319319-}320320-321321-static int speedtch_get_status(struct speedtch_instance_data *instance,322322- unsigned char *buf)323323-{324324- struct usb_device *dev = instance->u.usb_dev;325325- int ret;326326-327327- memset(buf, 0, TOTAL);328328-329329- ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),330330- 0x12, 0xc0, 0x07, 0x00, buf + OFFSET_7, SIZE_7,331331- CTRL_TIMEOUT);332332- if (ret < 0) {333333- dbg("MSG 7 failed");334334- return ret;335335- }336336-337337- ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),338338- 0x12, 0xc0, 0x0b, 0x00, buf + OFFSET_b, SIZE_b,339339- CTRL_TIMEOUT);340340- if (ret < 0) {341341- dbg("MSG B failed");342342- return ret;343343- }344344-345345- ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),346346- 0x12, 0xc0, 0x0d, 0x00, buf + OFFSET_d, SIZE_d,347347- CTRL_TIMEOUT);348348- if (ret < 0) {349349- dbg("MSG D failed");350350- return ret;351351- }352352-353353- ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),354354- 0x01, 0xc0, 0x0e, 0x00, buf + OFFSET_e, SIZE_e,355355- CTRL_TIMEOUT);356356- if (ret < 0) {357357- dbg("MSG E failed");358358- return ret;359359- }360360-361361- ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),362362- 0x01, 0xc0, 0x0f, 0x00, buf + OFFSET_f, SIZE_f,363363- CTRL_TIMEOUT);364364- if (ret < 0) {365365- dbg("MSG F failed");366366- return ret;367367- }368368-369369- return 0;370370-}371371-372372-static void speedtch_poll_status(struct speedtch_instance_data *instance)373373-{374374- unsigned char buf[TOTAL];375375- int ret;376376-377377- ret = speedtch_get_status(instance, buf);378378- if (ret) {379379- printk(KERN_WARNING380380- "SpeedTouch: Error %d fetching device status\n", ret);381381- return;382382- }383383-384384- dbg("Line state %02x", buf[OFFSET_7]);385385-386386- switch (buf[OFFSET_7]) {387387- case 0:388388- if (instance->u.atm_dev->signal != ATM_PHY_SIG_LOST) {389389- instance->u.atm_dev->signal = ATM_PHY_SIG_LOST;390390- printk(KERN_NOTICE "ADSL line is down\n");391391- /* It'll never resync again unless we ask it to... */392392- speedtch_start_synchro(instance);393393- }394394- break;395395-396396- case 0x08:397397- if (instance->u.atm_dev->signal != ATM_PHY_SIG_UNKNOWN) {398398- instance->u.atm_dev->signal = ATM_PHY_SIG_UNKNOWN;399399- printk(KERN_NOTICE "ADSL line is blocked?\n");400400- }401401- break;402402-403403- case 0x10:404404- if (instance->u.atm_dev->signal != ATM_PHY_SIG_LOST) {405405- instance->u.atm_dev->signal = ATM_PHY_SIG_LOST;406406- printk(KERN_NOTICE "ADSL line is synchronising\n");407407- }408408- break;409409-410410- case 0x20:411411- if (instance->u.atm_dev->signal != ATM_PHY_SIG_FOUND) {412412- int down_speed = buf[OFFSET_b] | (buf[OFFSET_b + 1] << 8)413413- | (buf[OFFSET_b + 2] << 16) | (buf[OFFSET_b + 3] << 24);414414- int up_speed = buf[OFFSET_b + 4] | (buf[OFFSET_b + 5] << 8)415415- | (buf[OFFSET_b + 6] << 16) | (buf[OFFSET_b + 7] << 24);416416-417417- if (!(down_speed & 0x0000ffff) &&418418- !(up_speed & 0x0000ffff)) {419419- down_speed >>= 16;420420- up_speed >>= 16;421421- }422422- instance->u.atm_dev->link_rate = down_speed * 1000 / 424;423423- instance->u.atm_dev->signal = ATM_PHY_SIG_FOUND;424424-425425- printk(KERN_NOTICE426426- "ADSL line is up (%d Kib/s down | %d Kib/s up)\n",427427- down_speed, up_speed);428428- }429429- break;430430-431431- default:432432- if (instance->u.atm_dev->signal != ATM_PHY_SIG_UNKNOWN) {433433- instance->u.atm_dev->signal = ATM_PHY_SIG_UNKNOWN;434434- printk(KERN_NOTICE "Unknown line state %02x\n", buf[OFFSET_7]);435435- }436436- break;437437- }438438-}439439-440440-static void speedtch_timer_poll(unsigned long data)441441-{442442- struct speedtch_instance_data *instance = (void *)data;443443-444444- schedule_work(&instance->poll_work);445445- mod_timer(&instance->poll_timer, jiffies + (5 * HZ));446446-}447447-448448-#ifdef USE_FW_LOADER449449-static void speedtch_upload_firmware(struct speedtch_instance_data *instance,172172+static int speedtch_upload_firmware(struct speedtch_instance_data *instance,450173 const struct firmware *fw1,451174 const struct firmware *fw2)452175{453176 unsigned char *buffer;454454- struct usb_device *usb_dev = instance->u.usb_dev;177177+ struct usbatm_data *usbatm = instance->usbatm;455178 struct usb_interface *intf;456456- int actual_length, ret;179179+ struct usb_device *usb_dev = usbatm->usb_dev;180180+ int actual_length;181181+ int ret = 0;457182 int offset;458183459459- dbg("speedtch_upload_firmware");460460-461461- if (!(intf = usb_ifnum_to_if(usb_dev, 2))) {462462- dbg("speedtch_upload_firmware: interface not found!");463463- goto fail;464464- }184184+ usb_dbg(usbatm, "%s entered\n", __func__);465185466186 if (!(buffer = (unsigned char *)__get_free_page(GFP_KERNEL))) {467467- dbg("speedtch_upload_firmware: no memory for buffer!");468468- goto fail;187187+ ret = -ENOMEM;188188+ usb_dbg(usbatm, "%s: no memory for buffer!\n", __func__);189189+ goto out;469190 }470191471471- /* A user-space firmware loader may already have claimed interface #2 */472472- if ((ret =473473- usb_driver_claim_interface(&speedtch_usb_driver, intf, NULL)) < 0) {474474- dbg("speedtch_upload_firmware: interface in use (%d)!", ret);475475- goto fail_free;192192+ if (!(intf = usb_ifnum_to_if(usb_dev, 2))) {193193+ ret = -ENODEV;194194+ usb_dbg(usbatm, "%s: interface not found!\n", __func__);195195+ goto out_free;476196 }477197478198 /* URB 7 */479199 if (dl_512_first) { /* some modems need a read before writing the firmware */480480- ret = usb_bulk_msg(usb_dev, usb_rcvbulkpipe(usb_dev, SPEEDTCH_ENDPOINT_FIRMWARE),200200+ ret = usb_bulk_msg(usb_dev, usb_rcvbulkpipe(usb_dev, ENDPOINT_FIRMWARE),481201 buffer, 0x200, &actual_length, 2000);482202483203 if (ret < 0 && ret != -ETIMEDOUT)484484- dbg("speedtch_upload_firmware: read BLOCK0 from modem failed (%d)!", ret);204204+ usb_dbg(usbatm, "%s: read BLOCK0 from modem failed (%d)!\n", __func__, ret);485205 else486486- dbg("speedtch_upload_firmware: BLOCK0 downloaded (%d bytes)", ret);206206+ usb_dbg(usbatm, "%s: BLOCK0 downloaded (%d bytes)\n", __func__, ret);487207 }488208489209 /* URB 8 : both leds are static green */···213489 int thislen = min_t(int, PAGE_SIZE, fw1->size - offset);214490 memcpy(buffer, fw1->data + offset, thislen);215491216216- ret = usb_bulk_msg(usb_dev, usb_sndbulkpipe(usb_dev, SPEEDTCH_ENDPOINT_FIRMWARE),492492+ ret = usb_bulk_msg(usb_dev, usb_sndbulkpipe(usb_dev, ENDPOINT_FIRMWARE),217493 buffer, thislen, &actual_length, DATA_TIMEOUT);218494219495 if (ret < 0) {220220- dbg("speedtch_upload_firmware: write BLOCK1 to modem failed (%d)!", ret);221221- goto fail_release;496496+ usb_dbg(usbatm, "%s: write BLOCK1 to modem failed (%d)!\n", __func__, ret);497497+ goto out_free;222498 }223223- dbg("speedtch_upload_firmware: BLOCK1 uploaded (%zu bytes)", fw1->size);499499+ usb_dbg(usbatm, "%s: BLOCK1 uploaded (%zu bytes)\n", __func__, fw1->size);224500 }225501226502 /* USB led blinking green, ADSL led off */227503228504 /* URB 11 */229229- ret = usb_bulk_msg(usb_dev, usb_rcvbulkpipe(usb_dev, SPEEDTCH_ENDPOINT_FIRMWARE),505505+ ret = usb_bulk_msg(usb_dev, usb_rcvbulkpipe(usb_dev, ENDPOINT_FIRMWARE),230506 buffer, 0x200, &actual_length, DATA_TIMEOUT);231507232508 if (ret < 0) {233233- dbg("speedtch_upload_firmware: read BLOCK2 from modem failed (%d)!", ret);234234- goto fail_release;509509+ usb_dbg(usbatm, "%s: read BLOCK2 from modem failed (%d)!\n", __func__, ret);510510+ goto out_free;235511 }236236- dbg("speedtch_upload_firmware: BLOCK2 downloaded (%d bytes)", actual_length);512512+ usb_dbg(usbatm, "%s: BLOCK2 downloaded (%d bytes)\n", __func__, actual_length);237513238514 /* URBs 12 to 139 - USB led blinking green, ADSL led off */239515 for (offset = 0; offset < fw2->size; offset += PAGE_SIZE) {240516 int thislen = min_t(int, PAGE_SIZE, fw2->size - offset);241517 memcpy(buffer, fw2->data + offset, thislen);242518243243- ret = usb_bulk_msg(usb_dev, usb_sndbulkpipe(usb_dev, SPEEDTCH_ENDPOINT_FIRMWARE),519519+ ret = usb_bulk_msg(usb_dev, usb_sndbulkpipe(usb_dev, ENDPOINT_FIRMWARE),244520 buffer, thislen, &actual_length, DATA_TIMEOUT);245521246522 if (ret < 0) {247247- dbg("speedtch_upload_firmware: write BLOCK3 to modem failed (%d)!", ret);248248- goto fail_release;523523+ usb_dbg(usbatm, "%s: write BLOCK3 to modem failed (%d)!\n", __func__, ret);524524+ goto out_free;249525 }250526 }251251- dbg("speedtch_upload_firmware: BLOCK3 uploaded (%zu bytes)", fw2->size);527527+ usb_dbg(usbatm, "%s: BLOCK3 uploaded (%zu bytes)\n", __func__, fw2->size);252528253529 /* USB led static green, ADSL led static red */254530255531 /* URB 142 */256256- ret = usb_bulk_msg(usb_dev, usb_rcvbulkpipe(usb_dev, SPEEDTCH_ENDPOINT_FIRMWARE),532532+ ret = usb_bulk_msg(usb_dev, usb_rcvbulkpipe(usb_dev, ENDPOINT_FIRMWARE),257533 buffer, 0x200, &actual_length, DATA_TIMEOUT);258534259535 if (ret < 0) {260260- dbg("speedtch_upload_firmware: read BLOCK4 from modem failed (%d)!", ret);261261- goto fail_release;536536+ usb_dbg(usbatm, "%s: read BLOCK4 from modem failed (%d)!\n", __func__, ret);537537+ goto out_free;262538 }263539264540 /* success */265265- dbg("speedtch_upload_firmware: BLOCK4 downloaded (%d bytes)", actual_length);541541+ usb_dbg(usbatm, "%s: BLOCK4 downloaded (%d bytes)\n", __func__, actual_length);266542267543 /* Delay to allow firmware to start up. We can do this here268544 because we're in our own kernel thread anyway. */269269- msleep(1000);545545+ msleep_interruptible(1000);270546271547 /* Enable software buffering, if requested */272548 if (sw_buffering)···275551 /* Magic spell; don't ask us what this does */276552 speedtch_test_sequence(instance);277553278278- /* Start modem synchronisation */279279- if (speedtch_start_synchro(instance))280280- dbg("speedtch_start_synchro: failed");554554+ ret = 0;281555282282- speedtch_got_firmware(instance, 1);283283-556556+out_free:284557 free_page((unsigned long)buffer);285285- return;286286-287287- fail_release:288288- /* Only release interface #2 if uploading failed; we don't release it289289- we succeeded. This prevents the userspace tools from trying to load290290- the firmware themselves */291291- usb_driver_release_interface(&speedtch_usb_driver, intf);292292- fail_free:293293- free_page((unsigned long)buffer);294294- fail:295295- speedtch_got_firmware(instance, 0);558558+out:559559+ return ret;296560}297561298298-static int speedtch_find_firmware(struct speedtch_instance_data299299- *instance, int phase,562562+static int speedtch_find_firmware(struct usb_interface *intf, int phase,300563 const struct firmware **fw_p)301564{302302- char buf[24];303303- const u16 bcdDevice = le16_to_cpu(instance->u.usb_dev->descriptor.bcdDevice);565565+ struct device *dev = &intf->dev;566566+ const u16 bcdDevice = le16_to_cpu(interface_to_usbdev(intf)->descriptor.bcdDevice);304567 const u8 major_revision = bcdDevice >> 8;305568 const u8 minor_revision = bcdDevice & 0xff;569569+ char buf[24];306570307571 sprintf(buf, "speedtch-%d.bin.%x.%02x", phase, major_revision, minor_revision);308308- dbg("speedtch_find_firmware: looking for %s", buf);572572+ dev_dbg(dev, "%s: looking for %s\n", __func__, buf);309573310310- if (request_firmware(fw_p, buf, &instance->u.usb_dev->dev)) {574574+ if (request_firmware(fw_p, buf, dev)) {311575 sprintf(buf, "speedtch-%d.bin.%x", phase, major_revision);312312- dbg("speedtch_find_firmware: looking for %s", buf);576576+ dev_dbg(dev, "%s: looking for %s\n", __func__, buf);313577314314- if (request_firmware(fw_p, buf, &instance->u.usb_dev->dev)) {578578+ if (request_firmware(fw_p, buf, dev)) {315579 sprintf(buf, "speedtch-%d.bin", phase);316316- dbg("speedtch_find_firmware: looking for %s", buf);580580+ dev_dbg(dev, "%s: looking for %s\n", __func__, buf);317581318318- if (request_firmware(fw_p, buf, &instance->u.usb_dev->dev)) {319319- dev_warn(&instance->u.usb_dev->dev, "no stage %d firmware found!", phase);582582+ if (request_firmware(fw_p, buf, dev)) {583583+ dev_warn(dev, "no stage %d firmware found!\n", phase);320584 return -ENOENT;321585 }322586 }323587 }324588325325- dev_info(&instance->u.usb_dev->dev, "found stage %d firmware %s\n", phase, buf);589589+ dev_info(dev, "found stage %d firmware %s\n", phase, buf);326590327591 return 0;328592}329593330330-static int speedtch_load_firmware(void *arg)594594+static int speedtch_heavy_init(struct usbatm_data *usbatm, struct usb_interface *intf)331595{332596 const struct firmware *fw1, *fw2;333333- struct speedtch_instance_data *instance = arg;597597+ struct speedtch_instance_data *instance = usbatm->driver_data;598598+ int ret;334599335335- BUG_ON(!instance);600600+ if ((ret = speedtch_find_firmware(intf, 1, &fw1)) < 0)601601+ return ret;336602337337- daemonize("firmware/speedtch");338338-339339- if (!speedtch_find_firmware(instance, 1, &fw1)) {340340- if (!speedtch_find_firmware(instance, 2, &fw2)) {341341- speedtch_upload_firmware(instance, fw1, fw2);342342- release_firmware(fw2);343343- }603603+ if ((ret = speedtch_find_firmware(intf, 2, &fw2)) < 0) {344604 release_firmware(fw1);605605+ return ret;345606 }346607347347- /* In case we failed, set state back to NO_FIRMWARE so that348348- another later attempt may work. Otherwise, we never actually349349- manage to recover if, for example, the firmware is on /usr and350350- we look for it too early. */351351- speedtch_got_firmware(instance, 0);608608+ ret = speedtch_upload_firmware(instance, fw1, fw2);352609353353- module_put(THIS_MODULE);354354- udsl_put_instance(&instance->u);610610+ release_firmware(fw2);611611+ release_firmware(fw1);612612+613613+ return ret;614614+}615615+616616+617617+/**********618618+** ATM **619619+**********/620620+621621+static int speedtch_read_status(struct speedtch_instance_data *instance)622622+{623623+ struct usbatm_data *usbatm = instance->usbatm;624624+ struct usb_device *usb_dev = usbatm->usb_dev;625625+ unsigned char *buf = instance->scratch_buffer;626626+ int ret;627627+628628+ memset(buf, 0, TOTAL);629629+630630+ ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),631631+ 0x12, 0xc0, 0x07, 0x00, buf + OFFSET_7, SIZE_7,632632+ CTRL_TIMEOUT);633633+ if (ret < 0) {634634+ atm_dbg(usbatm, "%s: MSG 7 failed\n", __func__);635635+ return ret;636636+ }637637+638638+ ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),639639+ 0x12, 0xc0, 0x0b, 0x00, buf + OFFSET_b, SIZE_b,640640+ CTRL_TIMEOUT);641641+ if (ret < 0) {642642+ atm_dbg(usbatm, "%s: MSG B failed\n", __func__);643643+ return ret;644644+ }645645+646646+ ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),647647+ 0x12, 0xc0, 0x0d, 0x00, buf + OFFSET_d, SIZE_d,648648+ CTRL_TIMEOUT);649649+ if (ret < 0) {650650+ atm_dbg(usbatm, "%s: MSG D failed\n", __func__);651651+ return ret;652652+ }653653+654654+ ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),655655+ 0x01, 0xc0, 0x0e, 0x00, buf + OFFSET_e, SIZE_e,656656+ CTRL_TIMEOUT);657657+ if (ret < 0) {658658+ atm_dbg(usbatm, "%s: MSG E failed\n", __func__);659659+ return ret;660660+ }661661+662662+ ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),663663+ 0x01, 0xc0, 0x0f, 0x00, buf + OFFSET_f, SIZE_f,664664+ CTRL_TIMEOUT);665665+ if (ret < 0) {666666+ atm_dbg(usbatm, "%s: MSG F failed\n", __func__);667667+ return ret;668668+ }669669+355670 return 0;356671}357357-#endif /* USE_FW_LOADER */358672359359-static void speedtch_firmware_start(struct speedtch_instance_data *instance)673673+static int speedtch_start_synchro(struct speedtch_instance_data *instance)360674{361361-#ifdef USE_FW_LOADER675675+ struct usbatm_data *usbatm = instance->usbatm;676676+ struct usb_device *usb_dev = usbatm->usb_dev;677677+ unsigned char *buf = instance->scratch_buffer;362678 int ret;363363-#endif364679365365- dbg("speedtch_firmware_start");680680+ atm_dbg(usbatm, "%s entered\n", __func__);366681367367- down(&instance->u.serialize); /* vs self, speedtch_got_firmware */682682+ memset(buf, 0, 2);368683369369- if (instance->u.status >= UDSL_LOADING_FIRMWARE) {370370- up(&instance->u.serialize);684684+ ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),685685+ 0x12, 0xc0, 0x04, 0x00,686686+ buf, 2, CTRL_TIMEOUT);687687+688688+ if (ret < 0)689689+ atm_warn(usbatm, "failed to start ADSL synchronisation: %d\n", ret);690690+ else691691+ atm_dbg(usbatm, "%s: modem prodded. %d bytes returned: %02x %02x\n",692692+ __func__, ret, buf[0], buf[1]);693693+694694+ return ret;695695+}696696+697697+static void speedtch_check_status(struct speedtch_instance_data *instance)698698+{699699+ struct usbatm_data *usbatm = instance->usbatm;700700+ struct atm_dev *atm_dev = usbatm->atm_dev;701701+ unsigned char *buf = instance->scratch_buffer;702702+ int ret;703703+704704+ atm_dbg(usbatm, "%s entered\n", __func__);705705+706706+ ret = speedtch_read_status(instance);707707+ if (ret < 0) {708708+ atm_warn(usbatm, "error %d fetching device status\n", ret);709709+ if (instance->poll_delay < MAX_POLL_DELAY)710710+ instance->poll_delay *= 2;371711 return;372712 }373713374374- instance->u.status = UDSL_LOADING_FIRMWARE;375375- up(&instance->u.serialize);714714+ if (instance->poll_delay > MIN_POLL_DELAY)715715+ instance->poll_delay /= 2;376716377377-#ifdef USE_FW_LOADER378378- udsl_get_instance(&instance->u);379379- try_module_get(THIS_MODULE);717717+ atm_dbg(usbatm, "%s: line state %02x\n", __func__, buf[OFFSET_7]);380718381381- ret = kernel_thread(speedtch_load_firmware, instance,382382- CLONE_FS | CLONE_FILES);719719+ switch (buf[OFFSET_7]) {720720+ case 0:721721+ if (atm_dev->signal != ATM_PHY_SIG_LOST) {722722+ atm_dev->signal = ATM_PHY_SIG_LOST;723723+ atm_info(usbatm, "ADSL line is down\n");724724+ /* It'll never resync again unless we ask it to... */725725+ ret = speedtch_start_synchro(instance);726726+ }727727+ break;383728384384- if (ret >= 0)385385- return; /* OK */729729+ case 0x08:730730+ if (atm_dev->signal != ATM_PHY_SIG_UNKNOWN) {731731+ atm_dev->signal = ATM_PHY_SIG_UNKNOWN;732732+ atm_info(usbatm, "ADSL line is blocked?\n");733733+ }734734+ break;386735387387- dbg("speedtch_firmware_start: kernel_thread failed (%d)!", ret);736736+ case 0x10:737737+ if (atm_dev->signal != ATM_PHY_SIG_LOST) {738738+ atm_dev->signal = ATM_PHY_SIG_LOST;739739+ atm_info(usbatm, "ADSL line is synchronising\n");740740+ }741741+ break;388742389389- module_put(THIS_MODULE);390390- udsl_put_instance(&instance->u);391391- /* Just pretend it never happened... hope modem_run happens */392392-#endif /* USE_FW_LOADER */743743+ case 0x20:744744+ if (atm_dev->signal != ATM_PHY_SIG_FOUND) {745745+ int down_speed = buf[OFFSET_b] | (buf[OFFSET_b + 1] << 8)746746+ | (buf[OFFSET_b + 2] << 16) | (buf[OFFSET_b + 3] << 24);747747+ int up_speed = buf[OFFSET_b + 4] | (buf[OFFSET_b + 5] << 8)748748+ | (buf[OFFSET_b + 6] << 16) | (buf[OFFSET_b + 7] << 24);393749394394- speedtch_got_firmware(instance, 0);750750+ if (!(down_speed & 0x0000ffff) && !(up_speed & 0x0000ffff)) {751751+ down_speed >>= 16;752752+ up_speed >>= 16;753753+ }754754+755755+ atm_dev->link_rate = down_speed * 1000 / 424;756756+ atm_dev->signal = ATM_PHY_SIG_FOUND;757757+758758+ atm_info(usbatm,759759+ "ADSL line is up (%d Kib/s down | %d Kib/s up)\n",760760+ down_speed, up_speed);761761+ }762762+ break;763763+764764+ default:765765+ if (atm_dev->signal != ATM_PHY_SIG_UNKNOWN) {766766+ atm_dev->signal = ATM_PHY_SIG_UNKNOWN;767767+ atm_info(usbatm, "Unknown line state %02x\n", buf[OFFSET_7]);768768+ }769769+ break;770770+ }395771}396772397397-static int speedtch_firmware_wait(struct udsl_instance_data *instance)773773+static void speedtch_status_poll(unsigned long data)398774{399399- speedtch_firmware_start((void *)instance);775775+ struct speedtch_instance_data *instance = (void *)data;400776401401- if (wait_event_interruptible(instance->firmware_waiters, instance->status != UDSL_LOADING_FIRMWARE) < 0)402402- return -ERESTARTSYS;777777+ schedule_work(&instance->status_checker);403778404404- return (instance->status == UDSL_LOADED_FIRMWARE) ? 0 : -EAGAIN;779779+ /* The following check is racy, but the race is harmless */780780+ if (instance->poll_delay < MAX_POLL_DELAY)781781+ mod_timer(&instance->status_checker.timer, jiffies + msecs_to_jiffies(instance->poll_delay));782782+ else783783+ atm_warn(instance->usbatm, "Too many failures - disabling line status polling\n");405784}785785+786786+static void speedtch_resubmit_int(unsigned long data)787787+{788788+ struct speedtch_instance_data *instance = (void *)data;789789+ struct urb *int_urb = instance->int_urb;790790+ int ret;791791+792792+ atm_dbg(instance->usbatm, "%s entered\n", __func__);793793+794794+ if (int_urb) {795795+ ret = usb_submit_urb(int_urb, GFP_ATOMIC);796796+ if (!ret)797797+ schedule_work(&instance->status_checker);798798+ else {799799+ atm_dbg(instance->usbatm, "%s: usb_submit_urb failed with result %d\n", __func__, ret);800800+ mod_timer(&instance->resubmit_timer, jiffies + msecs_to_jiffies(RESUBMIT_DELAY));801801+ }802802+ }803803+}804804+805805+static void speedtch_handle_int(struct urb *int_urb, struct pt_regs *regs)806806+{807807+ struct speedtch_instance_data *instance = int_urb->context;808808+ struct usbatm_data *usbatm = instance->usbatm;809809+ unsigned int count = int_urb->actual_length;810810+ int ret = int_urb->status;811811+812812+ /* The magic interrupt for "up state" */813813+ const static unsigned char up_int[6] = { 0xa1, 0x00, 0x01, 0x00, 0x00, 0x00 };814814+ /* The magic interrupt for "down state" */815815+ const static unsigned char down_int[6] = { 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00 };816816+817817+ atm_dbg(usbatm, "%s entered\n", __func__);818818+819819+ if (ret < 0) {820820+ atm_dbg(usbatm, "%s: nonzero urb status %d!\n", __func__, ret);821821+ goto fail;822822+ }823823+824824+ if ((count == 6) && !memcmp(up_int, instance->int_data, 6)) {825825+ del_timer(&instance->status_checker.timer);826826+ atm_info(usbatm, "DSL line goes up\n");827827+ } else if ((count == 6) && !memcmp(down_int, instance->int_data, 6)) {828828+ atm_info(usbatm, "DSL line goes down\n");829829+ } else {830830+ int i;831831+832832+ atm_dbg(usbatm, "%s: unknown interrupt packet of length %d:", __func__, count);833833+ for (i = 0; i < count; i++)834834+ printk(" %02x", instance->int_data[i]);835835+ printk("\n");836836+ goto fail;837837+ }838838+839839+ if ((int_urb = instance->int_urb)) {840840+ ret = usb_submit_urb(int_urb, GFP_ATOMIC);841841+ schedule_work(&instance->status_checker);842842+ if (ret < 0) {843843+ atm_dbg(usbatm, "%s: usb_submit_urb failed with result %d\n", __func__, ret);844844+ goto fail;845845+ }846846+ }847847+848848+ return;849849+850850+fail:851851+ if ((int_urb = instance->int_urb))852852+ mod_timer(&instance->resubmit_timer, jiffies + msecs_to_jiffies(RESUBMIT_DELAY));853853+}854854+855855+static int speedtch_atm_start(struct usbatm_data *usbatm, struct atm_dev *atm_dev)856856+{857857+ struct usb_device *usb_dev = usbatm->usb_dev;858858+ struct speedtch_instance_data *instance = usbatm->driver_data;859859+ int i, ret;860860+ unsigned char mac_str[13];861861+862862+ atm_dbg(usbatm, "%s entered\n", __func__);863863+864864+ if ((ret = usb_set_interface(usb_dev, 1, altsetting)) < 0) {865865+ atm_dbg(usbatm, "%s: usb_set_interface returned %d!\n", __func__, ret);866866+ return ret;867867+ }868868+869869+ /* Set MAC address, it is stored in the serial number */870870+ memset(atm_dev->esi, 0, sizeof(atm_dev->esi));871871+ if (usb_string(usb_dev, usb_dev->descriptor.iSerialNumber, mac_str, sizeof(mac_str)) == 12) {872872+ for (i = 0; i < 6; i++)873873+ atm_dev->esi[i] = (hex2int(mac_str[i * 2]) * 16) + (hex2int(mac_str[i * 2 + 1]));874874+ }875875+876876+ /* Start modem synchronisation */877877+ ret = speedtch_start_synchro(instance);878878+879879+ /* Set up interrupt endpoint */880880+ if (instance->int_urb) {881881+ ret = usb_submit_urb(instance->int_urb, GFP_KERNEL);882882+ if (ret < 0) {883883+ /* Doesn't matter; we'll poll anyway */884884+ atm_dbg(usbatm, "%s: submission of interrupt URB failed (%d)!\n", __func__, ret);885885+ usb_free_urb(instance->int_urb);886886+ instance->int_urb = NULL;887887+ }888888+ }889889+890890+ /* Start status polling */891891+ mod_timer(&instance->status_checker.timer, jiffies + msecs_to_jiffies(1000));892892+893893+ return 0;894894+}895895+896896+static void speedtch_atm_stop(struct usbatm_data *usbatm, struct atm_dev *atm_dev)897897+{898898+ struct speedtch_instance_data *instance = usbatm->driver_data;899899+ struct urb *int_urb = instance->int_urb;900900+901901+ atm_dbg(usbatm, "%s entered\n", __func__);902902+903903+ del_timer_sync(&instance->status_checker.timer);904904+905905+ /*906906+ * Since resubmit_timer and int_urb can schedule themselves and907907+ * each other, shutting them down correctly takes some care908908+ */909909+ instance->int_urb = NULL; /* signal shutdown */910910+ mb();911911+ usb_kill_urb(int_urb);912912+ del_timer_sync(&instance->resubmit_timer);913913+ /*914914+ * At this point, speedtch_handle_int and speedtch_resubmit_int915915+ * can run or be running, but instance->int_urb == NULL means that916916+ * they will not reschedule917917+ */918918+ usb_kill_urb(int_urb);919919+ del_timer_sync(&instance->resubmit_timer);920920+ usb_free_urb(int_urb);921921+922922+ flush_scheduled_work();923923+}924924+406925407926/**********408927** USB **409928**********/410929411411-static int speedtch_usb_ioctl(struct usb_interface *intf, unsigned int code,412412- void *user_data)413413-{414414- struct speedtch_instance_data *instance = usb_get_intfdata(intf);930930+static struct usb_device_id speedtch_usb_ids[] = {931931+ {USB_DEVICE(0x06b9, 0x4061)},932932+ {}933933+};415934416416- dbg("speedtch_usb_ioctl entered");935935+MODULE_DEVICE_TABLE(usb, speedtch_usb_ids);417936418418- if (!instance) {419419- dbg("speedtch_usb_ioctl: NULL instance!");420420- return -ENODEV;421421- }937937+static int speedtch_usb_probe(struct usb_interface *, const struct usb_device_id *);422938423423- switch (code) {424424- case UDSL_IOCTL_LINE_UP:425425- instance->u.atm_dev->signal = ATM_PHY_SIG_FOUND;426426- speedtch_got_firmware(instance, 1);427427- return (instance->u.status == UDSL_LOADED_FIRMWARE) ? 0 : -EIO;428428- case UDSL_IOCTL_LINE_DOWN:429429- instance->u.atm_dev->signal = ATM_PHY_SIG_LOST;430430- return 0;431431- default:432432- return -ENOTTY;433433- }939939+static struct usb_driver speedtch_usb_driver = {940940+ .owner = THIS_MODULE,941941+ .name = speedtch_driver_name,942942+ .probe = speedtch_usb_probe,943943+ .disconnect = usbatm_usb_disconnect,944944+ .id_table = speedtch_usb_ids945945+};946946+947947+static void speedtch_release_interfaces(struct usb_device *usb_dev, int num_interfaces) {948948+ struct usb_interface *cur_intf;949949+ int i;950950+951951+ for(i = 0; i < num_interfaces; i++)952952+ if ((cur_intf = usb_ifnum_to_if(usb_dev, i))) {953953+ usb_set_intfdata(cur_intf, NULL);954954+ usb_driver_release_interface(&speedtch_usb_driver, cur_intf);955955+ }434956}435957436436-static int speedtch_usb_probe(struct usb_interface *intf,437437- const struct usb_device_id *id)958958+static int speedtch_bind(struct usbatm_data *usbatm,959959+ struct usb_interface *intf,960960+ const struct usb_device_id *id,961961+ int *need_heavy_init)438962{439439- struct usb_device *dev = interface_to_usbdev(intf);440440- int ifnum = intf->altsetting->desc.bInterfaceNumber;963963+ struct usb_device *usb_dev = interface_to_usbdev(intf);964964+ struct usb_interface *cur_intf;441965 struct speedtch_instance_data *instance;442442- unsigned char mac_str[13];443443- int ret, i;444444- char buf7[SIZE_7];966966+ int ifnum = intf->altsetting->desc.bInterfaceNumber;967967+ int num_interfaces = usb_dev->actconfig->desc.bNumInterfaces;968968+ int i, ret;445969446446- dbg("speedtch_usb_probe: trying device with vendor=0x%x, product=0x%x, ifnum %d",447447- le16_to_cpu(dev->descriptor.idVendor),448448- le16_to_cpu(dev->descriptor.idProduct), ifnum);970970+ usb_dbg(usbatm, "%s entered\n", __func__);449971450450- if ((dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) || 451451- (ifnum != 1))972972+ if (usb_dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) {973973+ usb_dbg(usbatm, "%s: wrong device class %d\n", __func__, usb_dev->descriptor.bDeviceClass);452974 return -ENODEV;975975+ }453976454454- dbg("speedtch_usb_probe: device accepted");977977+ /* claim all interfaces */455978456456- /* instance init */979979+ for (i=0; i < num_interfaces; i++) {980980+ cur_intf = usb_ifnum_to_if(usb_dev, i);981981+982982+ if ((i != ifnum) && cur_intf) {983983+ ret = usb_driver_claim_interface(&speedtch_usb_driver, cur_intf, usbatm);984984+985985+ if (ret < 0) {986986+ usb_dbg(usbatm, "%s: failed to claim interface %d (%d)\n", __func__, i, ret);987987+ speedtch_release_interfaces(usb_dev, i);988988+ return ret;989989+ }990990+ }991991+ }992992+457993 instance = kmalloc(sizeof(*instance), GFP_KERNEL);994994+458995 if (!instance) {459459- dbg("speedtch_usb_probe: no memory for instance data!");460460- return -ENOMEM;996996+ usb_dbg(usbatm, "%s: no memory for instance data!\n", __func__);997997+ ret = -ENOMEM;998998+ goto fail_release;461999 }46210004631001 memset(instance, 0, sizeof(struct speedtch_instance_data));4641002465465- if ((ret = usb_set_interface(dev, 0, 0)) < 0)466466- goto fail;10031003+ instance->usbatm = usbatm;4671004468468- if ((ret = usb_set_interface(dev, 2, 0)) < 0)469469- goto fail;10051005+ INIT_WORK(&instance->status_checker, (void *)speedtch_check_status, instance);4701006471471- instance->u.data_endpoint = SPEEDTCH_ENDPOINT_DATA;472472- instance->u.firmware_wait = speedtch_firmware_wait;473473- instance->u.driver_name = speedtch_driver_name;10071007+ instance->status_checker.timer.function = speedtch_status_poll;10081008+ instance->status_checker.timer.data = (unsigned long)instance;10091009+ instance->poll_delay = MIN_POLL_DELAY;4741010475475- ret = udsl_instance_setup(dev, &instance->u);476476- if (ret)477477- goto fail;10111011+ init_timer(&instance->resubmit_timer);10121012+ instance->resubmit_timer.function = speedtch_resubmit_int;10131013+ instance->resubmit_timer.data = (unsigned long)instance;4781014479479- init_timer(&instance->poll_timer);480480- instance->poll_timer.function = speedtch_timer_poll;481481- instance->poll_timer.data = (unsigned long)instance;10151015+ instance->int_urb = usb_alloc_urb(0, GFP_KERNEL);4821016483483- INIT_WORK(&instance->poll_work, (void *)speedtch_poll_status, instance);10171017+ if (instance->int_urb)10181018+ usb_fill_int_urb(instance->int_urb, usb_dev,10191019+ usb_rcvintpipe(usb_dev, ENDPOINT_INT),10201020+ instance->int_data, sizeof(instance->int_data),10211021+ speedtch_handle_int, instance, 50);10221022+ else10231023+ usb_dbg(usbatm, "%s: no memory for interrupt urb!\n", __func__);4841024485485- /* set MAC address, it is stored in the serial number */486486- memset(instance->u.atm_dev->esi, 0, sizeof(instance->u.atm_dev->esi));487487- if (usb_string(dev, dev->descriptor.iSerialNumber, mac_str, sizeof(mac_str)) == 12) {488488- for (i = 0; i < 6; i++)489489- instance->u.atm_dev->esi[i] =490490- (hex2int(mac_str[i * 2]) * 16) + (hex2int(mac_str[i * 2 + 1]));491491- }10251025+ /* check whether the modem already seems to be alive */10261026+ ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),10271027+ 0x12, 0xc0, 0x07, 0x00,10281028+ instance->scratch_buffer + OFFSET_7, SIZE_7, 500);4921029493493- /* First check whether the modem already seems to be alive */494494- ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),495495- 0x12, 0xc0, 0x07, 0x00, buf7, SIZE_7, 500);10301030+ *need_heavy_init = (ret != SIZE_7);4961031497497- if (ret == SIZE_7) {498498- dbg("firmware appears to be already loaded");499499- speedtch_got_firmware(instance, 1);500500- speedtch_poll_status(instance);501501- } else {502502- speedtch_firmware_start(instance);503503- }10321032+ usb_dbg(usbatm, "%s: firmware %s loaded\n", __func__, need_heavy_init ? "not" : "already");5041033505505- usb_set_intfdata(intf, instance);10341034+ if (*need_heavy_init)10351035+ if ((ret = usb_reset_device(usb_dev)) < 0)10361036+ goto fail_free;10371037+10381038+ usbatm->driver_data = instance;50610395071040 return 0;5081041509509- fail:10421042+fail_free:10431043+ usb_free_urb(instance->int_urb);5101044 kfree(instance);511511-512512- return -ENOMEM;10451045+fail_release:10461046+ speedtch_release_interfaces(usb_dev, num_interfaces);10471047+ return ret;5131048}5141049515515-static void speedtch_usb_disconnect(struct usb_interface *intf)10501050+static void speedtch_unbind(struct usbatm_data *usbatm, struct usb_interface *intf)5161051{517517- struct speedtch_instance_data *instance = usb_get_intfdata(intf);10521052+ struct usb_device *usb_dev = interface_to_usbdev(intf);10531053+ struct speedtch_instance_data *instance = usbatm->driver_data;5181054519519- dbg("speedtch_usb_disconnect entered");10551055+ usb_dbg(usbatm, "%s entered\n", __func__);5201056521521- if (!instance) {522522- dbg("speedtch_usb_disconnect: NULL instance!");523523- return;524524- }525525-526526-/*QQ need to handle disconnects on interface #2 while uploading firmware */527527-/*QQ and what about interface #1? */528528-529529- if (instance->int_urb) {530530- struct urb *int_urb = instance->int_urb;531531- instance->int_urb = NULL;532532- wmb();533533- usb_unlink_urb(int_urb);534534- usb_free_urb(int_urb);535535- }536536-537537- instance->int_data[0] = 1;538538- del_timer_sync(&instance->poll_timer);539539- wmb();540540- flush_scheduled_work();541541-542542- udsl_instance_disconnect(&instance->u);543543-544544- /* clean up */545545- usb_set_intfdata(intf, NULL);546546- udsl_put_instance(&instance->u);10571057+ speedtch_release_interfaces(usb_dev, usb_dev->actconfig->desc.bNumInterfaces);10581058+ usb_free_urb(instance->int_urb);10591059+ kfree(instance);5471060}10611061+54810625491063/***********5501064** init **5511065***********/552106610671067+static struct usbatm_driver speedtch_usbatm_driver = {10681068+ .owner = THIS_MODULE,10691069+ .driver_name = speedtch_driver_name,10701070+ .bind = speedtch_bind,10711071+ .heavy_init = speedtch_heavy_init,10721072+ .unbind = speedtch_unbind,10731073+ .atm_start = speedtch_atm_start,10741074+ .atm_stop = speedtch_atm_stop,10751075+ .in = ENDPOINT_DATA,10761076+ .out = ENDPOINT_DATA10771077+};10781078+10791079+static int speedtch_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)10801080+{10811081+ return usbatm_usb_probe(intf, id, &speedtch_usbatm_driver);10821082+}10831083+5531084static int __init speedtch_usb_init(void)5541085{555555- dbg("speedtch_usb_init: driver version " DRIVER_VERSION);10861086+ dbg("%s: driver version %s", __func__, DRIVER_VERSION);55610875571088 return usb_register(&speedtch_usb_driver);5581089}55910905601091static void __exit speedtch_usb_cleanup(void)5611092{562562- dbg("speedtch_usb_cleanup entered");10931093+ dbg("%s", __func__);56310945641095 usb_deregister(&speedtch_usb_driver);5651096}
-1188
drivers/usb/atm/usb_atm.c
···11-/******************************************************************************22- * usb_atm.c - Generic USB xDSL driver core33- *44- * Copyright (C) 2001, Alcatel55- * Copyright (C) 2003, Duncan Sands, SolNegro, Josep Comas66- * Copyright (C) 2004, David Woodhouse77- *88- * This program is free software; you can redistribute it and/or modify it99- * under the terms of the GNU General Public License as published by the Free1010- * Software Foundation; either version 2 of the License, or (at your option)1111- * any later version.1212- *1313- * This program is distributed in the hope that it will be useful, but WITHOUT1414- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or1515- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for1616- * more details.1717- *1818- * You should have received a copy of the GNU General Public License along with1919- * this program; if not, write to the Free Software Foundation, Inc., 592020- * Temple Place - Suite 330, Boston, MA 02111-1307, USA.2121- *2222- ******************************************************************************/2323-2424-/*2525- * Written by Johan Verrept, maintained by Duncan Sands (duncan.sands@free.fr)2626- *2727- * 1.7+: - See the check-in logs2828- *2929- * 1.6: - No longer opens a connection if the firmware is not loaded3030- * - Added support for the speedtouch 3303131- * - Removed the limit on the number of devices3232- * - Module now autoloads on device plugin3333- * - Merged relevant parts of sarlib3434- * - Replaced the kernel thread with a tasklet3535- * - New packet transmission code3636- * - Changed proc file contents3737- * - Fixed all known SMP races3838- * - Many fixes and cleanups3939- * - Various fixes by Oliver Neukum (oliver@neukum.name)4040- *4141- * 1.5A: - Version for inclusion in 2.5 series kernel4242- * - Modifications by Richard Purdie (rpurdie@rpsys.net)4343- * - made compatible with kernel 2.5.6 onwards by changing4444- * udsl_usb_send_data_context->urb to a pointer and adding code4545- * to alloc and free it4646- * - remove_wait_queue() added to udsl_atm_processqueue_thread()4747- *4848- * 1.5: - fixed memory leak when atmsar_decode_aal5 returned NULL.4949- * (reported by stephen.robinson@zen.co.uk)5050- *5151- * 1.4: - changed the spin_lock() under interrupt to spin_lock_irqsave()5252- * - unlink all active send urbs of a vcc that is being closed.5353- *5454- * 1.3.1: - added the version number5555- *5656- * 1.3: - Added multiple send urb support5757- * - fixed memory leak and vcc->tx_inuse starvation bug5858- * when not enough memory left in vcc.5959- *6060- * 1.2: - Fixed race condition in udsl_usb_send_data()6161- * 1.1: - Turned off packet debugging6262- *6363- */6464-6565-#include <linux/module.h>6666-#include <linux/moduleparam.h>6767-#include <linux/kernel.h>6868-#include <linux/sched.h>6969-#include <linux/timer.h>7070-#include <linux/errno.h>7171-#include <linux/proc_fs.h>7272-#include <linux/slab.h>7373-#include <linux/wait.h>7474-#include <linux/list.h>7575-#include <asm/uaccess.h>7676-#include <linux/smp_lock.h>7777-#include <linux/interrupt.h>7878-#include <linux/atm.h>7979-#include <linux/atmdev.h>8080-#include <linux/crc32.h>8181-#include <linux/init.h>8282-#include <linux/firmware.h>8383-8484-#include "usb_atm.h"8585-8686-#ifdef VERBOSE_DEBUG8787-static int udsl_print_packet(const unsigned char *data, int len);8888-#define PACKETDEBUG(arg...) udsl_print_packet (arg)8989-#define vdbg(arg...) dbg (arg)9090-#else9191-#define PACKETDEBUG(arg...)9292-#define vdbg(arg...)9393-#endif9494-9595-#define DRIVER_AUTHOR "Johan Verrept, Duncan Sands <duncan.sands@free.fr>"9696-#define DRIVER_VERSION "1.8"9797-#define DRIVER_DESC "Generic USB ATM/DSL I/O, version " DRIVER_VERSION9898-9999-static unsigned int num_rcv_urbs = UDSL_DEFAULT_RCV_URBS;100100-static unsigned int num_snd_urbs = UDSL_DEFAULT_SND_URBS;101101-static unsigned int num_rcv_bufs = UDSL_DEFAULT_RCV_BUFS;102102-static unsigned int num_snd_bufs = UDSL_DEFAULT_SND_BUFS;103103-static unsigned int rcv_buf_size = UDSL_DEFAULT_RCV_BUF_SIZE;104104-static unsigned int snd_buf_size = UDSL_DEFAULT_SND_BUF_SIZE;105105-106106-module_param(num_rcv_urbs, uint, 0444);107107-MODULE_PARM_DESC(num_rcv_urbs,108108- "Number of urbs used for reception (range: 0-"109109- __MODULE_STRING(UDSL_MAX_RCV_URBS) ", default: "110110- __MODULE_STRING(UDSL_DEFAULT_RCV_URBS) ")");111111-112112-module_param(num_snd_urbs, uint, 0444);113113-MODULE_PARM_DESC(num_snd_urbs,114114- "Number of urbs used for transmission (range: 0-"115115- __MODULE_STRING(UDSL_MAX_SND_URBS) ", default: "116116- __MODULE_STRING(UDSL_DEFAULT_SND_URBS) ")");117117-118118-module_param(num_rcv_bufs, uint, 0444);119119-MODULE_PARM_DESC(num_rcv_bufs,120120- "Number of buffers used for reception (range: 0-"121121- __MODULE_STRING(UDSL_MAX_RCV_BUFS) ", default: "122122- __MODULE_STRING(UDSL_DEFAULT_RCV_BUFS) ")");123123-124124-module_param(num_snd_bufs, uint, 0444);125125-MODULE_PARM_DESC(num_snd_bufs,126126- "Number of buffers used for transmission (range: 0-"127127- __MODULE_STRING(UDSL_MAX_SND_BUFS) ", default: "128128- __MODULE_STRING(UDSL_DEFAULT_SND_BUFS) ")");129129-130130-module_param(rcv_buf_size, uint, 0444);131131-MODULE_PARM_DESC(rcv_buf_size,132132- "Size of the buffers used for reception (range: 0-"133133- __MODULE_STRING(UDSL_MAX_RCV_BUF_SIZE) ", default: "134134- __MODULE_STRING(UDSL_DEFAULT_RCV_BUF_SIZE) ")");135135-136136-module_param(snd_buf_size, uint, 0444);137137-MODULE_PARM_DESC(snd_buf_size,138138- "Size of the buffers used for transmission (range: 0-"139139- __MODULE_STRING(UDSL_MAX_SND_BUF_SIZE) ", default: "140140- __MODULE_STRING(UDSL_DEFAULT_SND_BUF_SIZE) ")");141141-142142-/* ATM */143143-144144-static void udsl_atm_dev_close(struct atm_dev *dev);145145-static int udsl_atm_open(struct atm_vcc *vcc);146146-static void udsl_atm_close(struct atm_vcc *vcc);147147-static int udsl_atm_ioctl(struct atm_dev *dev, unsigned int cmd, void __user * arg);148148-static int udsl_atm_send(struct atm_vcc *vcc, struct sk_buff *skb);149149-static int udsl_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *page);150150-151151-static struct atmdev_ops udsl_atm_devops = {152152- .dev_close = udsl_atm_dev_close,153153- .open = udsl_atm_open,154154- .close = udsl_atm_close,155155- .ioctl = udsl_atm_ioctl,156156- .send = udsl_atm_send,157157- .proc_read = udsl_atm_proc_read,158158- .owner = THIS_MODULE,159159-};160160-161161-/***********162162-** misc **163163-***********/164164-165165-static inline void udsl_pop(struct atm_vcc *vcc, struct sk_buff *skb)166166-{167167- if (vcc->pop)168168- vcc->pop(vcc, skb);169169- else170170- dev_kfree_skb(skb);171171-}172172-173173-/*************174174-** decode **175175-*************/176176-177177-static inline struct udsl_vcc_data *udsl_find_vcc(struct udsl_instance_data *instance,178178- short vpi, int vci)179179-{180180- struct udsl_vcc_data *vcc;181181-182182- list_for_each_entry(vcc, &instance->vcc_list, list)183183- if ((vcc->vci == vci) && (vcc->vpi == vpi))184184- return vcc;185185- return NULL;186186-}187187-188188-static void udsl_extract_cells(struct udsl_instance_data *instance,189189- unsigned char *source, unsigned int howmany)190190-{191191- struct udsl_vcc_data *cached_vcc = NULL;192192- struct atm_vcc *vcc;193193- struct sk_buff *sarb;194194- struct udsl_vcc_data *vcc_data;195195- int cached_vci = 0;196196- unsigned int i;197197- int pti;198198- int vci;199199- short cached_vpi = 0;200200- short vpi;201201-202202- for (i = 0; i < howmany;203203- i++, source += ATM_CELL_SIZE + instance->rcv_padding) {204204- vpi = ((source[0] & 0x0f) << 4) | (source[1] >> 4);205205- vci = ((source[1] & 0x0f) << 12) | (source[2] << 4) | (source[3] >> 4);206206- pti = (source[3] & 0x2) != 0;207207-208208- vdbg("udsl_extract_cells: vpi %hd, vci %d, pti %d", vpi, vci, pti);209209-210210- if (cached_vcc && (vci == cached_vci) && (vpi == cached_vpi))211211- vcc_data = cached_vcc;212212- else if ((vcc_data = udsl_find_vcc(instance, vpi, vci))) {213213- cached_vcc = vcc_data;214214- cached_vpi = vpi;215215- cached_vci = vci;216216- } else {217217- dbg("udsl_extract_cells: unknown vpi/vci (%hd/%d)!", vpi, vci);218218- continue;219219- }220220-221221- vcc = vcc_data->vcc;222222- sarb = vcc_data->sarb;223223-224224- if (sarb->tail + ATM_CELL_PAYLOAD > sarb->end) {225225- dbg("udsl_extract_cells: buffer overrun (sarb->len %u, vcc: 0x%p)!", sarb->len, vcc);226226- /* discard cells already received */227227- skb_trim(sarb, 0);228228- }229229-230230- memcpy(sarb->tail, source + ATM_CELL_HEADER, ATM_CELL_PAYLOAD);231231- __skb_put(sarb, ATM_CELL_PAYLOAD);232232-233233- if (pti) {234234- struct sk_buff *skb;235235- unsigned int length;236236- unsigned int pdu_length;237237-238238- length = (source[ATM_CELL_SIZE - 6] << 8) + source[ATM_CELL_SIZE - 5];239239-240240- /* guard against overflow */241241- if (length > ATM_MAX_AAL5_PDU) {242242- dbg("udsl_extract_cells: bogus length %u (vcc: 0x%p)!", length, vcc);243243- atomic_inc(&vcc->stats->rx_err);244244- goto out;245245- }246246-247247- pdu_length = UDSL_NUM_CELLS(length) * ATM_CELL_PAYLOAD;248248-249249- if (sarb->len < pdu_length) {250250- dbg("udsl_extract_cells: bogus pdu_length %u (sarb->len: %u, vcc: 0x%p)!", pdu_length, sarb->len, vcc);251251- atomic_inc(&vcc->stats->rx_err);252252- goto out;253253- }254254-255255- if (crc32_be(~0, sarb->tail - pdu_length, pdu_length) != 0xc704dd7b) {256256- dbg("udsl_extract_cells: packet failed crc check (vcc: 0x%p)!", vcc);257257- atomic_inc(&vcc->stats->rx_err);258258- goto out;259259- }260260-261261- vdbg("udsl_extract_cells: got packet (length: %u, pdu_length: %u, vcc: 0x%p)", length, pdu_length, vcc);262262-263263- if (!(skb = dev_alloc_skb(length))) {264264- dbg("udsl_extract_cells: no memory for skb (length: %u)!", length);265265- atomic_inc(&vcc->stats->rx_drop);266266- goto out;267267- }268268-269269- vdbg("udsl_extract_cells: allocated new sk_buff (skb: 0x%p, skb->truesize: %u)", skb, skb->truesize);270270-271271- if (!atm_charge(vcc, skb->truesize)) {272272- dbg("udsl_extract_cells: failed atm_charge (skb->truesize: %u)!", skb->truesize);273273- dev_kfree_skb(skb);274274- goto out; /* atm_charge increments rx_drop */275275- }276276-277277- memcpy(skb->data, sarb->tail - pdu_length, length);278278- __skb_put(skb, length);279279-280280- vdbg("udsl_extract_cells: sending skb 0x%p, skb->len %u, skb->truesize %u", skb, skb->len, skb->truesize);281281-282282- PACKETDEBUG(skb->data, skb->len);283283-284284- vcc->push(vcc, skb);285285-286286- atomic_inc(&vcc->stats->rx);287287- out:288288- skb_trim(sarb, 0);289289- }290290- }291291-}292292-293293-/*************294294-** encode **295295-*************/296296-297297-static inline void udsl_fill_cell_header(unsigned char *target, struct atm_vcc *vcc)298298-{299299- target[0] = vcc->vpi >> 4;300300- target[1] = (vcc->vpi << 4) | (vcc->vci >> 12);301301- target[2] = vcc->vci >> 4;302302- target[3] = vcc->vci << 4;303303- target[4] = 0xec;304304-}305305-306306-static const unsigned char zeros[ATM_CELL_PAYLOAD];307307-308308-static void udsl_groom_skb(struct atm_vcc *vcc, struct sk_buff *skb)309309-{310310- struct udsl_control *ctrl = UDSL_SKB(skb);311311- unsigned int zero_padding;312312- u32 crc;313313-314314- ctrl->atm_data.vcc = vcc;315315-316316- ctrl->num_cells = UDSL_NUM_CELLS(skb->len);317317- ctrl->num_entire = skb->len / ATM_CELL_PAYLOAD;318318-319319- zero_padding = ctrl->num_cells * ATM_CELL_PAYLOAD - skb->len - ATM_AAL5_TRAILER;320320-321321- if (ctrl->num_entire + 1 < ctrl->num_cells)322322- ctrl->pdu_padding = zero_padding - (ATM_CELL_PAYLOAD - ATM_AAL5_TRAILER);323323- else324324- ctrl->pdu_padding = zero_padding;325325-326326- ctrl->aal5_trailer[0] = 0; /* UU = 0 */327327- ctrl->aal5_trailer[1] = 0; /* CPI = 0 */328328- ctrl->aal5_trailer[2] = skb->len >> 8;329329- ctrl->aal5_trailer[3] = skb->len;330330-331331- crc = crc32_be(~0, skb->data, skb->len);332332- crc = crc32_be(crc, zeros, zero_padding);333333- crc = crc32_be(crc, ctrl->aal5_trailer, 4);334334- crc = ~crc;335335-336336- ctrl->aal5_trailer[4] = crc >> 24;337337- ctrl->aal5_trailer[5] = crc >> 16;338338- ctrl->aal5_trailer[6] = crc >> 8;339339- ctrl->aal5_trailer[7] = crc;340340-}341341-342342-static unsigned int udsl_write_cells(struct udsl_instance_data *instance,343343- unsigned int howmany, struct sk_buff *skb,344344- unsigned char **target_p)345345-{346346- struct udsl_control *ctrl = UDSL_SKB(skb);347347- unsigned char *target = *target_p;348348- unsigned int nc, ne, i;349349-350350- vdbg("udsl_write_cells: howmany=%u, skb->len=%d, num_cells=%u, num_entire=%u, pdu_padding=%u", howmany, skb->len, ctrl->num_cells, ctrl->num_entire, ctrl->pdu_padding);351351-352352- nc = ctrl->num_cells;353353- ne = min(howmany, ctrl->num_entire);354354-355355- for (i = 0; i < ne; i++) {356356- udsl_fill_cell_header(target, ctrl->atm_data.vcc);357357- target += ATM_CELL_HEADER;358358- memcpy(target, skb->data, ATM_CELL_PAYLOAD);359359- target += ATM_CELL_PAYLOAD;360360- if (instance->snd_padding) {361361- memset(target, 0, instance->snd_padding);362362- target += instance->snd_padding;363363- }364364- __skb_pull(skb, ATM_CELL_PAYLOAD);365365- }366366-367367- ctrl->num_entire -= ne;368368-369369- if (!(ctrl->num_cells -= ne) || !(howmany -= ne))370370- goto out;371371-372372- udsl_fill_cell_header(target, ctrl->atm_data.vcc);373373- target += ATM_CELL_HEADER;374374- memcpy(target, skb->data, skb->len);375375- target += skb->len;376376- __skb_pull(skb, skb->len);377377- memset(target, 0, ctrl->pdu_padding);378378- target += ctrl->pdu_padding;379379-380380- if (--ctrl->num_cells) {381381- if (!--howmany) {382382- ctrl->pdu_padding = ATM_CELL_PAYLOAD - ATM_AAL5_TRAILER;383383- goto out;384384- }385385-386386- if (instance->snd_padding) {387387- memset(target, 0, instance->snd_padding);388388- target += instance->snd_padding;389389- }390390- udsl_fill_cell_header(target, ctrl->atm_data.vcc);391391- target += ATM_CELL_HEADER;392392- memset(target, 0, ATM_CELL_PAYLOAD - ATM_AAL5_TRAILER);393393- target += ATM_CELL_PAYLOAD - ATM_AAL5_TRAILER;394394-395395- --ctrl->num_cells;396396- UDSL_ASSERT(!ctrl->num_cells);397397- }398398-399399- memcpy(target, ctrl->aal5_trailer, ATM_AAL5_TRAILER);400400- target += ATM_AAL5_TRAILER;401401- /* set pti bit in last cell */402402- *(target + 3 - ATM_CELL_SIZE) |= 0x2;403403- if (instance->snd_padding) {404404- memset(target, 0, instance->snd_padding);405405- target += instance->snd_padding;406406- }407407- out:408408- *target_p = target;409409- return nc - ctrl->num_cells;410410-}411411-412412-/**************413413-** receive **414414-**************/415415-416416-static void udsl_complete_receive(struct urb *urb, struct pt_regs *regs)417417-{418418- struct udsl_receive_buffer *buf;419419- struct udsl_instance_data *instance;420420- struct udsl_receiver *rcv;421421- unsigned long flags;422422-423423- if (!urb || !(rcv = urb->context)) {424424- dbg("udsl_complete_receive: bad urb!");425425- return;426426- }427427-428428- instance = rcv->instance;429429- buf = rcv->buffer;430430-431431- buf->filled_cells = urb->actual_length / (ATM_CELL_SIZE + instance->rcv_padding);432432-433433- vdbg("udsl_complete_receive: urb 0x%p, status %d, actual_length %d, filled_cells %u, rcv 0x%p, buf 0x%p", urb, urb->status, urb->actual_length, buf->filled_cells, rcv, buf);434434-435435- UDSL_ASSERT(buf->filled_cells <= rcv_buf_size);436436-437437- /* may not be in_interrupt() */438438- spin_lock_irqsave(&instance->receive_lock, flags);439439- list_add(&rcv->list, &instance->spare_receivers);440440- list_add_tail(&buf->list, &instance->filled_receive_buffers);441441- if (likely(!urb->status))442442- tasklet_schedule(&instance->receive_tasklet);443443- spin_unlock_irqrestore(&instance->receive_lock, flags);444444-}445445-446446-static void udsl_process_receive(unsigned long data)447447-{448448- struct udsl_receive_buffer *buf;449449- struct udsl_instance_data *instance = (struct udsl_instance_data *)data;450450- struct udsl_receiver *rcv;451451- int err;452452-453453- made_progress:454454- while (!list_empty(&instance->spare_receive_buffers)) {455455- spin_lock_irq(&instance->receive_lock);456456- if (list_empty(&instance->spare_receivers)) {457457- spin_unlock_irq(&instance->receive_lock);458458- break;459459- }460460- rcv = list_entry(instance->spare_receivers.next,461461- struct udsl_receiver, list);462462- list_del(&rcv->list);463463- spin_unlock_irq(&instance->receive_lock);464464-465465- buf = list_entry(instance->spare_receive_buffers.next,466466- struct udsl_receive_buffer, list);467467- list_del(&buf->list);468468-469469- rcv->buffer = buf;470470-471471- usb_fill_bulk_urb(rcv->urb, instance->usb_dev,472472- usb_rcvbulkpipe(instance->usb_dev, instance->data_endpoint),473473- buf->base,474474- rcv_buf_size * (ATM_CELL_SIZE + instance->rcv_padding),475475- udsl_complete_receive, rcv);476476-477477- vdbg("udsl_process_receive: sending urb 0x%p, rcv 0x%p, buf 0x%p",478478- rcv->urb, rcv, buf);479479-480480- if ((err = usb_submit_urb(rcv->urb, GFP_ATOMIC)) < 0) {481481- dbg("udsl_process_receive: urb submission failed (%d)!", err);482482- list_add(&buf->list, &instance->spare_receive_buffers);483483- spin_lock_irq(&instance->receive_lock);484484- list_add(&rcv->list, &instance->spare_receivers);485485- spin_unlock_irq(&instance->receive_lock);486486- break;487487- }488488- }489489-490490- spin_lock_irq(&instance->receive_lock);491491- if (list_empty(&instance->filled_receive_buffers)) {492492- spin_unlock_irq(&instance->receive_lock);493493- return; /* done - no more buffers */494494- }495495- buf = list_entry(instance->filled_receive_buffers.next,496496- struct udsl_receive_buffer, list);497497- list_del(&buf->list);498498- spin_unlock_irq(&instance->receive_lock);499499-500500- vdbg("udsl_process_receive: processing buf 0x%p", buf);501501- udsl_extract_cells(instance, buf->base, buf->filled_cells);502502- list_add(&buf->list, &instance->spare_receive_buffers);503503- goto made_progress;504504-}505505-506506-/***********507507-** send **508508-***********/509509-510510-static void udsl_complete_send(struct urb *urb, struct pt_regs *regs)511511-{512512- struct udsl_instance_data *instance;513513- struct udsl_sender *snd;514514- unsigned long flags;515515-516516- if (!urb || !(snd = urb->context) || !(instance = snd->instance)) {517517- dbg("udsl_complete_send: bad urb!");518518- return;519519- }520520-521521- vdbg("udsl_complete_send: urb 0x%p, status %d, snd 0x%p, buf 0x%p", urb,522522- urb->status, snd, snd->buffer);523523-524524- /* may not be in_interrupt() */525525- spin_lock_irqsave(&instance->send_lock, flags);526526- list_add(&snd->list, &instance->spare_senders);527527- list_add(&snd->buffer->list, &instance->spare_send_buffers);528528- tasklet_schedule(&instance->send_tasklet);529529- spin_unlock_irqrestore(&instance->send_lock, flags);530530-}531531-532532-static void udsl_process_send(unsigned long data)533533-{534534- struct udsl_send_buffer *buf;535535- struct udsl_instance_data *instance = (struct udsl_instance_data *)data;536536- struct sk_buff *skb;537537- struct udsl_sender *snd;538538- int err;539539- unsigned int num_written;540540-541541- made_progress:542542- spin_lock_irq(&instance->send_lock);543543- while (!list_empty(&instance->spare_senders)) {544544- if (!list_empty(&instance->filled_send_buffers)) {545545- buf = list_entry(instance->filled_send_buffers.next,546546- struct udsl_send_buffer, list);547547- list_del(&buf->list);548548- } else if ((buf = instance->current_buffer)) {549549- instance->current_buffer = NULL;550550- } else /* all buffers empty */551551- break;552552-553553- snd = list_entry(instance->spare_senders.next,554554- struct udsl_sender, list);555555- list_del(&snd->list);556556- spin_unlock_irq(&instance->send_lock);557557-558558- snd->buffer = buf;559559- usb_fill_bulk_urb(snd->urb, instance->usb_dev,560560- usb_sndbulkpipe(instance->usb_dev, instance->data_endpoint),561561- buf->base,562562- (snd_buf_size - buf->free_cells) * (ATM_CELL_SIZE + instance->snd_padding),563563- udsl_complete_send, snd);564564-565565- vdbg("udsl_process_send: submitting urb 0x%p (%d cells), snd 0x%p, buf 0x%p",566566- snd->urb, snd_buf_size - buf->free_cells, snd, buf);567567-568568- if ((err = usb_submit_urb(snd->urb, GFP_ATOMIC)) < 0) {569569- dbg("udsl_process_send: urb submission failed (%d)!", err);570570- spin_lock_irq(&instance->send_lock);571571- list_add(&snd->list, &instance->spare_senders);572572- spin_unlock_irq(&instance->send_lock);573573- list_add(&buf->list, &instance->filled_send_buffers);574574- return; /* bail out */575575- }576576-577577- spin_lock_irq(&instance->send_lock);578578- } /* while */579579- spin_unlock_irq(&instance->send_lock);580580-581581- if (!instance->current_skb)582582- instance->current_skb = skb_dequeue(&instance->sndqueue);583583- if (!instance->current_skb)584584- return; /* done - no more skbs */585585-586586- skb = instance->current_skb;587587-588588- if (!(buf = instance->current_buffer)) {589589- spin_lock_irq(&instance->send_lock);590590- if (list_empty(&instance->spare_send_buffers)) {591591- instance->current_buffer = NULL;592592- spin_unlock_irq(&instance->send_lock);593593- return; /* done - no more buffers */594594- }595595- buf = list_entry(instance->spare_send_buffers.next,596596- struct udsl_send_buffer, list);597597- list_del(&buf->list);598598- spin_unlock_irq(&instance->send_lock);599599-600600- buf->free_start = buf->base;601601- buf->free_cells = snd_buf_size;602602-603603- instance->current_buffer = buf;604604- }605605-606606- num_written = udsl_write_cells(instance, buf->free_cells, skb, &buf->free_start);607607-608608- vdbg("udsl_process_send: wrote %u cells from skb 0x%p to buffer 0x%p",609609- num_written, skb, buf);610610-611611- if (!(buf->free_cells -= num_written)) {612612- list_add_tail(&buf->list, &instance->filled_send_buffers);613613- instance->current_buffer = NULL;614614- }615615-616616- vdbg("udsl_process_send: buffer contains %d cells, %d left",617617- snd_buf_size - buf->free_cells, buf->free_cells);618618-619619- if (!UDSL_SKB(skb)->num_cells) {620620- struct atm_vcc *vcc = UDSL_SKB(skb)->atm_data.vcc;621621-622622- udsl_pop(vcc, skb);623623- instance->current_skb = NULL;624624-625625- atomic_inc(&vcc->stats->tx);626626- }627627-628628- goto made_progress;629629-}630630-631631-static void udsl_cancel_send(struct udsl_instance_data *instance,632632- struct atm_vcc *vcc)633633-{634634- struct sk_buff *skb, *n;635635-636636- dbg("udsl_cancel_send entered");637637- spin_lock_irq(&instance->sndqueue.lock);638638- for (skb = instance->sndqueue.next, n = skb->next;639639- skb != (struct sk_buff *)&instance->sndqueue;640640- skb = n, n = skb->next)641641- if (UDSL_SKB(skb)->atm_data.vcc == vcc) {642642- dbg("udsl_cancel_send: popping skb 0x%p", skb);643643- __skb_unlink(skb, &instance->sndqueue);644644- udsl_pop(vcc, skb);645645- }646646- spin_unlock_irq(&instance->sndqueue.lock);647647-648648- tasklet_disable(&instance->send_tasklet);649649- if ((skb = instance->current_skb) && (UDSL_SKB(skb)->atm_data.vcc == vcc)) {650650- dbg("udsl_cancel_send: popping current skb (0x%p)", skb);651651- instance->current_skb = NULL;652652- udsl_pop(vcc, skb);653653- }654654- tasklet_enable(&instance->send_tasklet);655655- dbg("udsl_cancel_send done");656656-}657657-658658-static int udsl_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)659659-{660660- struct udsl_instance_data *instance = vcc->dev->dev_data;661661- int err;662662-663663- vdbg("udsl_atm_send called (skb 0x%p, len %u)", skb, skb->len);664664-665665- if (!instance) {666666- dbg("udsl_atm_send: NULL data!");667667- err = -ENODEV;668668- goto fail;669669- }670670-671671- if (vcc->qos.aal != ATM_AAL5) {672672- dbg("udsl_atm_send: unsupported ATM type %d!", vcc->qos.aal);673673- err = -EINVAL;674674- goto fail;675675- }676676-677677- if (skb->len > ATM_MAX_AAL5_PDU) {678678- dbg("udsl_atm_send: packet too long (%d vs %d)!", skb->len,679679- ATM_MAX_AAL5_PDU);680680- err = -EINVAL;681681- goto fail;682682- }683683-684684- PACKETDEBUG(skb->data, skb->len);685685-686686- udsl_groom_skb(vcc, skb);687687- skb_queue_tail(&instance->sndqueue, skb);688688- tasklet_schedule(&instance->send_tasklet);689689-690690- return 0;691691-692692- fail:693693- udsl_pop(vcc, skb);694694- return err;695695-}696696-697697-/********************698698-** bean counting **699699-********************/700700-701701-static void udsl_destroy_instance(struct kref *kref)702702-{703703- struct udsl_instance_data *instance =704704- container_of(kref, struct udsl_instance_data, refcount);705705-706706- tasklet_kill(&instance->receive_tasklet);707707- tasklet_kill(&instance->send_tasklet);708708- usb_put_dev(instance->usb_dev);709709- kfree(instance);710710-}711711-712712-void udsl_get_instance(struct udsl_instance_data *instance)713713-{714714- kref_get(&instance->refcount);715715-}716716-717717-void udsl_put_instance(struct udsl_instance_data *instance)718718-{719719- kref_put(&instance->refcount, udsl_destroy_instance);720720-}721721-722722-/**********723723-** ATM **724724-**********/725725-726726-static void udsl_atm_dev_close(struct atm_dev *dev)727727-{728728- struct udsl_instance_data *instance = dev->dev_data;729729-730730- dev->dev_data = NULL;731731- udsl_put_instance(instance);732732-}733733-734734-static int udsl_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *page)735735-{736736- struct udsl_instance_data *instance = atm_dev->dev_data;737737- int left = *pos;738738-739739- if (!instance) {740740- dbg("udsl_atm_proc_read: NULL instance!");741741- return -ENODEV;742742- }743743-744744- if (!left--)745745- return sprintf(page, "%s\n", instance->description);746746-747747- if (!left--)748748- return sprintf(page, "MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",749749- atm_dev->esi[0], atm_dev->esi[1],750750- atm_dev->esi[2], atm_dev->esi[3],751751- atm_dev->esi[4], atm_dev->esi[5]);752752-753753- if (!left--)754754- return sprintf(page,755755- "AAL5: tx %d ( %d err ), rx %d ( %d err, %d drop )\n",756756- atomic_read(&atm_dev->stats.aal5.tx),757757- atomic_read(&atm_dev->stats.aal5.tx_err),758758- atomic_read(&atm_dev->stats.aal5.rx),759759- atomic_read(&atm_dev->stats.aal5.rx_err),760760- atomic_read(&atm_dev->stats.aal5.rx_drop));761761-762762- if (!left--) {763763- switch (atm_dev->signal) {764764- case ATM_PHY_SIG_FOUND:765765- sprintf(page, "Line up");766766- break;767767- case ATM_PHY_SIG_LOST:768768- sprintf(page, "Line down");769769- break;770770- default:771771- sprintf(page, "Line state unknown");772772- break;773773- }774774-775775- if (instance->usb_dev->state == USB_STATE_NOTATTACHED)776776- strcat(page, ", disconnected\n");777777- else {778778- if (instance->status == UDSL_LOADED_FIRMWARE)779779- strcat(page, ", firmware loaded\n");780780- else if (instance->status == UDSL_LOADING_FIRMWARE)781781- strcat(page, ", firmware loading\n");782782- else783783- strcat(page, ", no firmware\n");784784- }785785-786786- return strlen(page);787787- }788788-789789- return 0;790790-}791791-792792-static int udsl_atm_open(struct atm_vcc *vcc)793793-{794794- struct udsl_instance_data *instance = vcc->dev->dev_data;795795- struct udsl_vcc_data *new;796796- unsigned int max_pdu;797797- int vci = vcc->vci;798798- short vpi = vcc->vpi;799799- int err;800800-801801- dbg("udsl_atm_open: vpi %hd, vci %d", vpi, vci);802802-803803- if (!instance) {804804- dbg("udsl_atm_open: NULL data!");805805- return -ENODEV;806806- }807807-808808- /* only support AAL5 */809809- if ((vcc->qos.aal != ATM_AAL5) || (vcc->qos.rxtp.max_sdu < 0)810810- || (vcc->qos.rxtp.max_sdu > ATM_MAX_AAL5_PDU)) {811811- dbg("udsl_atm_open: unsupported ATM type %d!", vcc->qos.aal);812812- return -EINVAL;813813- }814814-815815- if (instance->firmware_wait &&816816- (err = instance->firmware_wait(instance)) < 0) {817817- dbg("udsl_atm_open: firmware not loaded (%d)!", err);818818- return err;819819- }820820-821821- down(&instance->serialize); /* vs self, udsl_atm_close */822822-823823- if (udsl_find_vcc(instance, vpi, vci)) {824824- dbg("udsl_atm_open: %hd/%d already in use!", vpi, vci);825825- up(&instance->serialize);826826- return -EADDRINUSE;827827- }828828-829829- if (!(new = kmalloc(sizeof(struct udsl_vcc_data), GFP_KERNEL))) {830830- dbg("udsl_atm_open: no memory for vcc_data!");831831- up(&instance->serialize);832832- return -ENOMEM;833833- }834834-835835- memset(new, 0, sizeof(struct udsl_vcc_data));836836- new->vcc = vcc;837837- new->vpi = vpi;838838- new->vci = vci;839839-840840- /* udsl_extract_cells requires at least one cell */841841- max_pdu = max(1, UDSL_NUM_CELLS(vcc->qos.rxtp.max_sdu)) * ATM_CELL_PAYLOAD;842842- if (!(new->sarb = alloc_skb(max_pdu, GFP_KERNEL))) {843843- dbg("udsl_atm_open: no memory for SAR buffer!");844844- kfree(new);845845- up(&instance->serialize);846846- return -ENOMEM;847847- }848848-849849- vcc->dev_data = new;850850-851851- tasklet_disable(&instance->receive_tasklet);852852- list_add(&new->list, &instance->vcc_list);853853- tasklet_enable(&instance->receive_tasklet);854854-855855- set_bit(ATM_VF_ADDR, &vcc->flags);856856- set_bit(ATM_VF_PARTIAL, &vcc->flags);857857- set_bit(ATM_VF_READY, &vcc->flags);858858-859859- up(&instance->serialize);860860-861861- tasklet_schedule(&instance->receive_tasklet);862862-863863- dbg("udsl_atm_open: allocated vcc data 0x%p (max_pdu: %u)", new, max_pdu);864864-865865- return 0;866866-}867867-868868-static void udsl_atm_close(struct atm_vcc *vcc)869869-{870870- struct udsl_instance_data *instance = vcc->dev->dev_data;871871- struct udsl_vcc_data *vcc_data = vcc->dev_data;872872-873873- dbg("udsl_atm_close called");874874-875875- if (!instance || !vcc_data) {876876- dbg("udsl_atm_close: NULL data!");877877- return;878878- }879879-880880- dbg("udsl_atm_close: deallocating vcc 0x%p with vpi %d vci %d",881881- vcc_data, vcc_data->vpi, vcc_data->vci);882882-883883- udsl_cancel_send(instance, vcc);884884-885885- down(&instance->serialize); /* vs self, udsl_atm_open */886886-887887- tasklet_disable(&instance->receive_tasklet);888888- list_del(&vcc_data->list);889889- tasklet_enable(&instance->receive_tasklet);890890-891891- kfree_skb(vcc_data->sarb);892892- vcc_data->sarb = NULL;893893-894894- kfree(vcc_data);895895- vcc->dev_data = NULL;896896-897897- vcc->vpi = ATM_VPI_UNSPEC;898898- vcc->vci = ATM_VCI_UNSPEC;899899- clear_bit(ATM_VF_READY, &vcc->flags);900900- clear_bit(ATM_VF_PARTIAL, &vcc->flags);901901- clear_bit(ATM_VF_ADDR, &vcc->flags);902902-903903- up(&instance->serialize);904904-905905- dbg("udsl_atm_close successful");906906-}907907-908908-static int udsl_atm_ioctl(struct atm_dev *dev, unsigned int cmd,909909- void __user * arg)910910-{911911- switch (cmd) {912912- case ATM_QUERYLOOP:913913- return put_user(ATM_LM_NONE, (int __user *)arg) ? -EFAULT : 0;914914- default:915915- return -ENOIOCTLCMD;916916- }917917-}918918-919919-/**********920920-** USB **921921-**********/922922-923923-int udsl_instance_setup(struct usb_device *dev,924924- struct udsl_instance_data *instance)925925-{926926- char *buf;927927- int i, length;928928-929929- kref_init(&instance->refcount); /* one for USB */930930- udsl_get_instance(instance); /* one for ATM */931931-932932- init_MUTEX(&instance->serialize);933933-934934- instance->usb_dev = dev;935935-936936- INIT_LIST_HEAD(&instance->vcc_list);937937-938938- instance->status = UDSL_NO_FIRMWARE;939939- init_waitqueue_head(&instance->firmware_waiters);940940-941941- spin_lock_init(&instance->receive_lock);942942- INIT_LIST_HEAD(&instance->spare_receivers);943943- INIT_LIST_HEAD(&instance->filled_receive_buffers);944944-945945- tasklet_init(&instance->receive_tasklet, udsl_process_receive, (unsigned long)instance);946946- INIT_LIST_HEAD(&instance->spare_receive_buffers);947947-948948- skb_queue_head_init(&instance->sndqueue);949949-950950- spin_lock_init(&instance->send_lock);951951- INIT_LIST_HEAD(&instance->spare_senders);952952- INIT_LIST_HEAD(&instance->spare_send_buffers);953953-954954- tasklet_init(&instance->send_tasklet, udsl_process_send,955955- (unsigned long)instance);956956- INIT_LIST_HEAD(&instance->filled_send_buffers);957957-958958- /* receive init */959959- for (i = 0; i < num_rcv_urbs; i++) {960960- struct udsl_receiver *rcv = &(instance->receivers[i]);961961-962962- if (!(rcv->urb = usb_alloc_urb(0, GFP_KERNEL))) {963963- dbg("udsl_usb_probe: no memory for receive urb %d!", i);964964- goto fail;965965- }966966-967967- rcv->instance = instance;968968-969969- list_add(&rcv->list, &instance->spare_receivers);970970- }971971-972972- for (i = 0; i < num_rcv_bufs; i++) {973973- struct udsl_receive_buffer *buf =974974- &(instance->receive_buffers[i]);975975-976976- buf->base = kmalloc(rcv_buf_size * (ATM_CELL_SIZE + instance->rcv_padding),977977- GFP_KERNEL);978978- if (!buf->base) {979979- dbg("udsl_usb_probe: no memory for receive buffer %d!", i);980980- goto fail;981981- }982982-983983- list_add(&buf->list, &instance->spare_receive_buffers);984984- }985985-986986- /* send init */987987- for (i = 0; i < num_snd_urbs; i++) {988988- struct udsl_sender *snd = &(instance->senders[i]);989989-990990- if (!(snd->urb = usb_alloc_urb(0, GFP_KERNEL))) {991991- dbg("udsl_usb_probe: no memory for send urb %d!", i);992992- goto fail;993993- }994994-995995- snd->instance = instance;996996-997997- list_add(&snd->list, &instance->spare_senders);998998- }999999-10001000- for (i = 0; i < num_snd_bufs; i++) {10011001- struct udsl_send_buffer *buf = &(instance->send_buffers[i]);10021002-10031003- buf->base = kmalloc(snd_buf_size * (ATM_CELL_SIZE + instance->snd_padding),10041004- GFP_KERNEL);10051005- if (!buf->base) {10061006- dbg("udsl_usb_probe: no memory for send buffer %d!", i);10071007- goto fail;10081008- }10091009-10101010- list_add(&buf->list, &instance->spare_send_buffers);10111011- }10121012-10131013- /* ATM init */10141014- instance->atm_dev = atm_dev_register(instance->driver_name,10151015- &udsl_atm_devops, -1, NULL);10161016- if (!instance->atm_dev) {10171017- dbg("udsl_usb_probe: failed to register ATM device!");10181018- goto fail;10191019- }10201020-10211021- instance->atm_dev->ci_range.vpi_bits = ATM_CI_MAX;10221022- instance->atm_dev->ci_range.vci_bits = ATM_CI_MAX;10231023- instance->atm_dev->signal = ATM_PHY_SIG_UNKNOWN;10241024-10251025- /* temp init ATM device, set to 128kbit */10261026- instance->atm_dev->link_rate = 128 * 1000 / 424;10271027-10281028- /* device description */10291029- buf = instance->description;10301030- length = sizeof(instance->description);10311031-10321032- if ((i = usb_string(dev, dev->descriptor.iProduct, buf, length)) < 0)10331033- goto finish;10341034-10351035- buf += i;10361036- length -= i;10371037-10381038- i = scnprintf(buf, length, " (");10391039- buf += i;10401040- length -= i;10411041-10421042- if (length <= 0 || (i = usb_make_path(dev, buf, length)) < 0)10431043- goto finish;10441044-10451045- buf += i;10461046- length -= i;10471047-10481048- snprintf(buf, length, ")");10491049-10501050- finish:10511051- /* ready for ATM callbacks */10521052- wmb();10531053- instance->atm_dev->dev_data = instance;10541054-10551055- usb_get_dev(dev);10561056-10571057- return 0;10581058-10591059- fail:10601060- for (i = 0; i < num_snd_bufs; i++)10611061- kfree(instance->send_buffers[i].base);10621062-10631063- for (i = 0; i < num_snd_urbs; i++)10641064- usb_free_urb(instance->senders[i].urb);10651065-10661066- for (i = 0; i < num_rcv_bufs; i++)10671067- kfree(instance->receive_buffers[i].base);10681068-10691069- for (i = 0; i < num_rcv_urbs; i++)10701070- usb_free_urb(instance->receivers[i].urb);10711071-10721072- return -ENOMEM;10731073-}10741074-10751075-void udsl_instance_disconnect(struct udsl_instance_data *instance)10761076-{10771077- int i;10781078-10791079- dbg("udsl_instance_disconnect entered");10801080-10811081- if (!instance) {10821082- dbg("udsl_instance_disconnect: NULL instance!");10831083- return;10841084- }10851085-10861086- /* receive finalize */10871087- tasklet_disable(&instance->receive_tasklet);10881088-10891089- for (i = 0; i < num_rcv_urbs; i++)10901090- usb_kill_urb(instance->receivers[i].urb);10911091-10921092- /* no need to take the spinlock */10931093- INIT_LIST_HEAD(&instance->filled_receive_buffers);10941094- INIT_LIST_HEAD(&instance->spare_receive_buffers);10951095-10961096- tasklet_enable(&instance->receive_tasklet);10971097-10981098- for (i = 0; i < num_rcv_urbs; i++)10991099- usb_free_urb(instance->receivers[i].urb);11001100-11011101- for (i = 0; i < num_rcv_bufs; i++)11021102- kfree(instance->receive_buffers[i].base);11031103-11041104- /* send finalize */11051105- tasklet_disable(&instance->send_tasklet);11061106-11071107- for (i = 0; i < num_snd_urbs; i++)11081108- usb_kill_urb(instance->senders[i].urb);11091109-11101110- /* no need to take the spinlock */11111111- INIT_LIST_HEAD(&instance->spare_senders);11121112- INIT_LIST_HEAD(&instance->spare_send_buffers);11131113- instance->current_buffer = NULL;11141114-11151115- tasklet_enable(&instance->send_tasklet);11161116-11171117- for (i = 0; i < num_snd_urbs; i++)11181118- usb_free_urb(instance->senders[i].urb);11191119-11201120- for (i = 0; i < num_snd_bufs; i++)11211121- kfree(instance->send_buffers[i].base);11221122-11231123- /* ATM finalize */11241124- shutdown_atm_dev(instance->atm_dev);11251125-}11261126-11271127-EXPORT_SYMBOL_GPL(udsl_get_instance);11281128-EXPORT_SYMBOL_GPL(udsl_put_instance);11291129-EXPORT_SYMBOL_GPL(udsl_instance_setup);11301130-EXPORT_SYMBOL_GPL(udsl_instance_disconnect);11311131-11321132-/***********11331133-** init **11341134-***********/11351135-11361136-static int __init udsl_usb_init(void)11371137-{11381138- dbg("udsl_usb_init: driver version " DRIVER_VERSION);11391139-11401140- if (sizeof(struct udsl_control) > sizeof(((struct sk_buff *) 0)->cb)) {11411141- printk(KERN_ERR __FILE__ ": unusable with this kernel!\n");11421142- return -EIO;11431143- }11441144-11451145- if ((num_rcv_urbs > UDSL_MAX_RCV_URBS)11461146- || (num_snd_urbs > UDSL_MAX_SND_URBS)11471147- || (num_rcv_bufs > UDSL_MAX_RCV_BUFS)11481148- || (num_snd_bufs > UDSL_MAX_SND_BUFS)11491149- || (rcv_buf_size > UDSL_MAX_RCV_BUF_SIZE)11501150- || (snd_buf_size > UDSL_MAX_SND_BUF_SIZE))11511151- return -EINVAL;11521152-11531153- return 0;11541154-}11551155-11561156-static void __exit udsl_usb_exit(void)11571157-{11581158-}11591159-11601160-module_init(udsl_usb_init);11611161-module_exit(udsl_usb_exit);11621162-11631163-MODULE_AUTHOR(DRIVER_AUTHOR);11641164-MODULE_DESCRIPTION(DRIVER_DESC);11651165-MODULE_LICENSE("GPL");11661166-MODULE_VERSION(DRIVER_VERSION);11671167-11681168-/************11691169-** debug **11701170-************/11711171-11721172-#ifdef VERBOSE_DEBUG11731173-static int udsl_print_packet(const unsigned char *data, int len)11741174-{11751175- unsigned char buffer[256];11761176- int i = 0, j = 0;11771177-11781178- for (i = 0; i < len;) {11791179- buffer[0] = '\0';11801180- sprintf(buffer, "%.3d :", i);11811181- for (j = 0; (j < 16) && (i < len); j++, i++) {11821182- sprintf(buffer, "%s %2.2x", buffer, data[i]);11831183- }11841184- dbg("%s", buffer);11851185- }11861186- return i;11871187-}11881188-#endif
-176
drivers/usb/atm/usb_atm.h
···11-/******************************************************************************22- * usb_atm.h - Generic USB xDSL driver core33- *44- * Copyright (C) 2001, Alcatel55- * Copyright (C) 2003, Duncan Sands, SolNegro, Josep Comas66- * Copyright (C) 2004, David Woodhouse77- *88- * This program is free software; you can redistribute it and/or modify it99- * under the terms of the GNU General Public License as published by the Free1010- * Software Foundation; either version 2 of the License, or (at your option)1111- * any later version.1212- *1313- * This program is distributed in the hope that it will be useful, but WITHOUT1414- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or1515- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for1616- * more details.1717- *1818- * You should have received a copy of the GNU General Public License along with1919- * this program; if not, write to the Free Software Foundation, Inc., 592020- * Temple Place - Suite 330, Boston, MA 02111-1307, USA.2121- *2222- ******************************************************************************/2323-2424-#include <linux/config.h>2525-#include <linux/list.h>2626-#include <linux/kref.h>2727-#include <linux/atm.h>2828-#include <linux/atmdev.h>2929-#include <asm/semaphore.h>3030-3131-/*3232-#define DEBUG3333-#define VERBOSE_DEBUG3434-*/3535-3636-#if !defined (DEBUG) && defined (CONFIG_USB_DEBUG)3737-# define DEBUG3838-#endif3939-4040-#include <linux/usb.h>4141-4242-#ifdef DEBUG4343-#define UDSL_ASSERT(x) BUG_ON(!(x))4444-#else4545-#define UDSL_ASSERT(x) do { if (!(x)) warn("failed assertion '" #x "' at line %d", __LINE__); } while(0)4646-#endif4747-4848-#define UDSL_MAX_RCV_URBS 44949-#define UDSL_MAX_SND_URBS 45050-#define UDSL_MAX_RCV_BUFS 85151-#define UDSL_MAX_SND_BUFS 85252-#define UDSL_MAX_RCV_BUF_SIZE 1024 /* ATM cells */5353-#define UDSL_MAX_SND_BUF_SIZE 1024 /* ATM cells */5454-#define UDSL_DEFAULT_RCV_URBS 25555-#define UDSL_DEFAULT_SND_URBS 25656-#define UDSL_DEFAULT_RCV_BUFS 45757-#define UDSL_DEFAULT_SND_BUFS 45858-#define UDSL_DEFAULT_RCV_BUF_SIZE 64 /* ATM cells */5959-#define UDSL_DEFAULT_SND_BUF_SIZE 64 /* ATM cells */6060-6161-#define ATM_CELL_HEADER (ATM_CELL_SIZE - ATM_CELL_PAYLOAD)6262-#define UDSL_NUM_CELLS(x) (((x) + ATM_AAL5_TRAILER + ATM_CELL_PAYLOAD - 1) / ATM_CELL_PAYLOAD)6363-6464-/* receive */6565-6666-struct udsl_receive_buffer {6767- struct list_head list;6868- unsigned char *base;6969- unsigned int filled_cells;7070-};7171-7272-struct udsl_receiver {7373- struct list_head list;7474- struct udsl_receive_buffer *buffer;7575- struct urb *urb;7676- struct udsl_instance_data *instance;7777-};7878-7979-struct udsl_vcc_data {8080- /* vpi/vci lookup */8181- struct list_head list;8282- short vpi;8383- int vci;8484- struct atm_vcc *vcc;8585-8686- /* raw cell reassembly */8787- struct sk_buff *sarb;8888-};8989-9090-/* send */9191-9292-struct udsl_send_buffer {9393- struct list_head list;9494- unsigned char *base;9595- unsigned char *free_start;9696- unsigned int free_cells;9797-};9898-9999-struct udsl_sender {100100- struct list_head list;101101- struct udsl_send_buffer *buffer;102102- struct urb *urb;103103- struct udsl_instance_data *instance;104104-};105105-106106-struct udsl_control {107107- struct atm_skb_data atm_data;108108- unsigned int num_cells;109109- unsigned int num_entire;110110- unsigned int pdu_padding;111111- unsigned char aal5_trailer[ATM_AAL5_TRAILER];112112-};113113-114114-#define UDSL_SKB(x) ((struct udsl_control *)(x)->cb)115115-116116-/* main driver data */117117-118118-enum udsl_status {119119- UDSL_NO_FIRMWARE,120120- UDSL_LOADING_FIRMWARE,121121- UDSL_LOADED_FIRMWARE122122-};123123-124124-struct udsl_instance_data {125125- struct kref refcount;126126- struct semaphore serialize;127127-128128- /* USB device part */129129- struct usb_device *usb_dev;130130- char description[64];131131- int data_endpoint;132132- int snd_padding;133133- int rcv_padding;134134- const char *driver_name;135135-136136- /* ATM device part */137137- struct atm_dev *atm_dev;138138- struct list_head vcc_list;139139-140140- /* firmware */141141- int (*firmware_wait) (struct udsl_instance_data *);142142- enum udsl_status status;143143- wait_queue_head_t firmware_waiters;144144-145145- /* receive */146146- struct udsl_receiver receivers[UDSL_MAX_RCV_URBS];147147- struct udsl_receive_buffer receive_buffers[UDSL_MAX_RCV_BUFS];148148-149149- spinlock_t receive_lock;150150- struct list_head spare_receivers;151151- struct list_head filled_receive_buffers;152152-153153- struct tasklet_struct receive_tasklet;154154- struct list_head spare_receive_buffers;155155-156156- /* send */157157- struct udsl_sender senders[UDSL_MAX_SND_URBS];158158- struct udsl_send_buffer send_buffers[UDSL_MAX_SND_BUFS];159159-160160- struct sk_buff_head sndqueue;161161-162162- spinlock_t send_lock;163163- struct list_head spare_senders;164164- struct list_head spare_send_buffers;165165-166166- struct tasklet_struct send_tasklet;167167- struct sk_buff *current_skb; /* being emptied */168168- struct udsl_send_buffer *current_buffer; /* being filled */169169- struct list_head filled_send_buffers;170170-};171171-172172-extern int udsl_instance_setup(struct usb_device *dev,173173- struct udsl_instance_data *instance);174174-extern void udsl_instance_disconnect(struct udsl_instance_data *instance);175175-extern void udsl_get_instance(struct udsl_instance_data *instance);176176-extern void udsl_put_instance(struct udsl_instance_data *instance);
+1230
drivers/usb/atm/usbatm.c
···11+/******************************************************************************22+ * usbatm.c - Generic USB xDSL driver core33+ *44+ * Copyright (C) 2001, Alcatel55+ * Copyright (C) 2003, Duncan Sands, SolNegro, Josep Comas66+ * Copyright (C) 2004, David Woodhouse, Roman Kagan77+ *88+ * This program is free software; you can redistribute it and/or modify it99+ * under the terms of the GNU General Public License as published by the Free1010+ * Software Foundation; either version 2 of the License, or (at your option)1111+ * any later version.1212+ *1313+ * This program is distributed in the hope that it will be useful, but WITHOUT1414+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or1515+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for1616+ * more details.1717+ *1818+ * You should have received a copy of the GNU General Public License along with1919+ * this program; if not, write to the Free Software Foundation, Inc., 592020+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.2121+ *2222+ ******************************************************************************/2323+2424+/*2525+ * Written by Johan Verrept, Duncan Sands (duncan.sands@free.fr) and David Woodhouse2626+ *2727+ * 1.7+: - See the check-in logs2828+ *2929+ * 1.6: - No longer opens a connection if the firmware is not loaded3030+ * - Added support for the speedtouch 3303131+ * - Removed the limit on the number of devices3232+ * - Module now autoloads on device plugin3333+ * - Merged relevant parts of sarlib3434+ * - Replaced the kernel thread with a tasklet3535+ * - New packet transmission code3636+ * - Changed proc file contents3737+ * - Fixed all known SMP races3838+ * - Many fixes and cleanups3939+ * - Various fixes by Oliver Neukum (oliver@neukum.name)4040+ *4141+ * 1.5A: - Version for inclusion in 2.5 series kernel4242+ * - Modifications by Richard Purdie (rpurdie@rpsys.net)4343+ * - made compatible with kernel 2.5.6 onwards by changing4444+ * usbatm_usb_send_data_context->urb to a pointer and adding code4545+ * to alloc and free it4646+ * - remove_wait_queue() added to usbatm_atm_processqueue_thread()4747+ *4848+ * 1.5: - fixed memory leak when atmsar_decode_aal5 returned NULL.4949+ * (reported by stephen.robinson@zen.co.uk)5050+ *5151+ * 1.4: - changed the spin_lock() under interrupt to spin_lock_irqsave()5252+ * - unlink all active send urbs of a vcc that is being closed.5353+ *5454+ * 1.3.1: - added the version number5555+ *5656+ * 1.3: - Added multiple send urb support5757+ * - fixed memory leak and vcc->tx_inuse starvation bug5858+ * when not enough memory left in vcc.5959+ *6060+ * 1.2: - Fixed race condition in usbatm_usb_send_data()6161+ * 1.1: - Turned off packet debugging6262+ *6363+ */6464+6565+#include "usbatm.h"6666+6767+#include <asm/uaccess.h>6868+#include <linux/crc32.h>6969+#include <linux/errno.h>7070+#include <linux/init.h>7171+#include <linux/interrupt.h>7272+#include <linux/kernel.h>7373+#include <linux/module.h>7474+#include <linux/moduleparam.h>7575+#include <linux/proc_fs.h>7676+#include <linux/sched.h>7777+#include <linux/signal.h>7878+#include <linux/slab.h>7979+#include <linux/smp_lock.h>8080+#include <linux/stat.h>8181+#include <linux/timer.h>8282+#include <linux/wait.h>8383+8484+#ifdef VERBOSE_DEBUG8585+static int usbatm_print_packet(const unsigned char *data, int len);8686+#define PACKETDEBUG(arg...) usbatm_print_packet (arg)8787+#define vdbg(arg...) dbg (arg)8888+#else8989+#define PACKETDEBUG(arg...)9090+#define vdbg(arg...)9191+#endif9292+9393+#define DRIVER_AUTHOR "Johan Verrept, Duncan Sands <duncan.sands@free.fr>"9494+#define DRIVER_VERSION "1.9"9595+#define DRIVER_DESC "Generic USB ATM/DSL I/O, version " DRIVER_VERSION9696+9797+static const char usbatm_driver_name[] = "usbatm";9898+9999+#define UDSL_MAX_RCV_URBS 16100100+#define UDSL_MAX_SND_URBS 16101101+#define UDSL_MAX_RCV_BUF_SIZE 1024 /* ATM cells */102102+#define UDSL_MAX_SND_BUF_SIZE 1024 /* ATM cells */103103+#define UDSL_DEFAULT_RCV_URBS 4104104+#define UDSL_DEFAULT_SND_URBS 4105105+#define UDSL_DEFAULT_RCV_BUF_SIZE 64 /* ATM cells */106106+#define UDSL_DEFAULT_SND_BUF_SIZE 64 /* ATM cells */107107+108108+#define ATM_CELL_HEADER (ATM_CELL_SIZE - ATM_CELL_PAYLOAD)109109+110110+#define THROTTLE_MSECS 100 /* delay to recover processing after urb submission fails */111111+112112+static unsigned int num_rcv_urbs = UDSL_DEFAULT_RCV_URBS;113113+static unsigned int num_snd_urbs = UDSL_DEFAULT_SND_URBS;114114+static unsigned int rcv_buf_size = UDSL_DEFAULT_RCV_BUF_SIZE;115115+static unsigned int snd_buf_size = UDSL_DEFAULT_SND_BUF_SIZE;116116+117117+module_param(num_rcv_urbs, uint, S_IRUGO);118118+MODULE_PARM_DESC(num_rcv_urbs,119119+ "Number of urbs used for reception (range: 0-"120120+ __MODULE_STRING(UDSL_MAX_RCV_URBS) ", default: "121121+ __MODULE_STRING(UDSL_DEFAULT_RCV_URBS) ")");122122+123123+module_param(num_snd_urbs, uint, S_IRUGO);124124+MODULE_PARM_DESC(num_snd_urbs,125125+ "Number of urbs used for transmission (range: 0-"126126+ __MODULE_STRING(UDSL_MAX_SND_URBS) ", default: "127127+ __MODULE_STRING(UDSL_DEFAULT_SND_URBS) ")");128128+129129+module_param(rcv_buf_size, uint, S_IRUGO);130130+MODULE_PARM_DESC(rcv_buf_size,131131+ "Size of the buffers used for reception in ATM cells (range: 1-"132132+ __MODULE_STRING(UDSL_MAX_RCV_BUF_SIZE) ", default: "133133+ __MODULE_STRING(UDSL_DEFAULT_RCV_BUF_SIZE) ")");134134+135135+module_param(snd_buf_size, uint, S_IRUGO);136136+MODULE_PARM_DESC(snd_buf_size,137137+ "Size of the buffers used for transmission in ATM cells (range: 1-"138138+ __MODULE_STRING(UDSL_MAX_SND_BUF_SIZE) ", default: "139139+ __MODULE_STRING(UDSL_DEFAULT_SND_BUF_SIZE) ")");140140+141141+142142+/* receive */143143+144144+struct usbatm_vcc_data {145145+ /* vpi/vci lookup */146146+ struct list_head list;147147+ short vpi;148148+ int vci;149149+ struct atm_vcc *vcc;150150+151151+ /* raw cell reassembly */152152+ struct sk_buff *sarb;153153+};154154+155155+156156+/* send */157157+158158+struct usbatm_control {159159+ struct atm_skb_data atm;160160+ u32 len;161161+ u32 crc;162162+};163163+164164+#define UDSL_SKB(x) ((struct usbatm_control *)(x)->cb)165165+166166+167167+/* ATM */168168+169169+static void usbatm_atm_dev_close(struct atm_dev *dev);170170+static int usbatm_atm_open(struct atm_vcc *vcc);171171+static void usbatm_atm_close(struct atm_vcc *vcc);172172+static int usbatm_atm_ioctl(struct atm_dev *dev, unsigned int cmd, void __user * arg);173173+static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb);174174+static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *page);175175+176176+static struct atmdev_ops usbatm_atm_devops = {177177+ .dev_close = usbatm_atm_dev_close,178178+ .open = usbatm_atm_open,179179+ .close = usbatm_atm_close,180180+ .ioctl = usbatm_atm_ioctl,181181+ .send = usbatm_atm_send,182182+ .proc_read = usbatm_atm_proc_read,183183+ .owner = THIS_MODULE,184184+};185185+186186+187187+/***********188188+** misc **189189+***********/190190+191191+static inline unsigned int usbatm_pdu_length(unsigned int length)192192+{193193+ length += ATM_CELL_PAYLOAD - 1 + ATM_AAL5_TRAILER;194194+ return length - length % ATM_CELL_PAYLOAD;195195+}196196+197197+static inline void usbatm_pop(struct atm_vcc *vcc, struct sk_buff *skb)198198+{199199+ if (vcc->pop)200200+ vcc->pop(vcc, skb);201201+ else202202+ dev_kfree_skb(skb);203203+}204204+205205+206206+/***********207207+** urbs **208208+************/209209+210210+static inline struct urb *usbatm_pop_urb(struct usbatm_channel *channel)211211+{212212+ struct urb *urb;213213+214214+ spin_lock_irq(&channel->lock);215215+ if (list_empty(&channel->list)) {216216+ spin_unlock_irq(&channel->lock);217217+ return NULL;218218+ }219219+220220+ urb = list_entry(channel->list.next, struct urb, urb_list);221221+ list_del(&urb->urb_list);222222+ spin_unlock_irq(&channel->lock);223223+224224+ return urb;225225+}226226+227227+static inline int usbatm_submit_urb(struct urb *urb)228228+{229229+ struct usbatm_channel *channel = urb->context;230230+ int ret;231231+232232+ vdbg("%s: submitting urb 0x%p, size %u",233233+ __func__, urb, urb->transfer_buffer_length);234234+235235+ ret = usb_submit_urb(urb, GFP_ATOMIC);236236+ if (ret) {237237+ atm_dbg(channel->usbatm, "%s: urb 0x%p submission failed (%d)!\n",238238+ __func__, urb, ret);239239+240240+ /* consider all errors transient and return the buffer back to the queue */241241+ urb->status = -EAGAIN;242242+ spin_lock_irq(&channel->lock);243243+244244+ /* must add to the front when sending; doesn't matter when receiving */245245+ list_add(&urb->urb_list, &channel->list);246246+247247+ spin_unlock_irq(&channel->lock);248248+249249+ /* make sure the channel doesn't stall */250250+ mod_timer(&channel->delay, jiffies + msecs_to_jiffies(THROTTLE_MSECS));251251+ }252252+253253+ return ret;254254+}255255+256256+static void usbatm_complete(struct urb *urb, struct pt_regs *regs)257257+{258258+ struct usbatm_channel *channel = urb->context;259259+ unsigned long flags;260260+261261+ vdbg("%s: urb 0x%p, status %d, actual_length %d",262262+ __func__, urb, urb->status, urb->actual_length);263263+264264+ /* usually in_interrupt(), but not always */265265+ spin_lock_irqsave(&channel->lock, flags);266266+267267+ /* must add to the back when receiving; doesn't matter when sending */268268+ list_add_tail(&urb->urb_list, &channel->list);269269+270270+ spin_unlock_irqrestore(&channel->lock, flags);271271+272272+ if (unlikely(urb->status))273273+ /* throttle processing in case of an error */274274+ mod_timer(&channel->delay, jiffies + msecs_to_jiffies(THROTTLE_MSECS));275275+ else276276+ tasklet_schedule(&channel->tasklet);277277+}278278+279279+280280+/*************281281+** decode **282282+*************/283283+284284+static inline struct usbatm_vcc_data *usbatm_find_vcc(struct usbatm_data *instance,285285+ short vpi, int vci)286286+{287287+ struct usbatm_vcc_data *vcc;288288+289289+ list_for_each_entry(vcc, &instance->vcc_list, list)290290+ if ((vcc->vci == vci) && (vcc->vpi == vpi))291291+ return vcc;292292+ return NULL;293293+}294294+295295+static void usbatm_extract_cells(struct usbatm_data *instance,296296+ unsigned char *source, unsigned int avail_data)297297+{298298+ struct usbatm_vcc_data *cached_vcc = NULL;299299+ struct atm_vcc *vcc;300300+ struct sk_buff *sarb;301301+ unsigned int stride = instance->rx_channel.stride;302302+ int vci, cached_vci = 0;303303+ short vpi, cached_vpi = 0;304304+ u8 pti;305305+306306+ for (; avail_data >= stride; avail_data -= stride, source += stride) {307307+ vpi = ((source[0] & 0x0f) << 4) | (source[1] >> 4);308308+ vci = ((source[1] & 0x0f) << 12) | (source[2] << 4) | (source[3] >> 4);309309+ pti = ((source[3] & 0xe) >> 1);310310+311311+ vdbg("%s: vpi %hd, vci %d, pti %d", __func__, vpi, vci, pti);312312+313313+ if ((vci != cached_vci) || (vpi != cached_vpi)) {314314+ cached_vpi = vpi;315315+ cached_vci = vci;316316+317317+ cached_vcc = usbatm_find_vcc(instance, vpi, vci);318318+319319+ if (!cached_vcc)320320+ atm_dbg(instance, "%s: unknown vpi/vci (%hd/%d)!\n", __func__, vpi, vci);321321+ }322322+323323+ if (!cached_vcc)324324+ continue;325325+326326+ vcc = cached_vcc->vcc;327327+328328+ /* OAM F5 end-to-end */329329+ if (pti == ATM_PTI_E2EF5) {330330+ atm_warn(instance, "%s: OAM not supported (vpi %d, vci %d)!\n", __func__, vpi, vci);331331+ atomic_inc(&vcc->stats->rx_err);332332+ continue;333333+ }334334+335335+ sarb = cached_vcc->sarb;336336+337337+ if (sarb->tail + ATM_CELL_PAYLOAD > sarb->end) {338338+ atm_dbg(instance, "%s: buffer overrun (sarb->len %u, vcc: 0x%p)!\n",339339+ __func__, sarb->len, vcc);340340+ /* discard cells already received */341341+ skb_trim(sarb, 0);342342+ UDSL_ASSERT(sarb->tail + ATM_CELL_PAYLOAD <= sarb->end);343343+ }344344+345345+ memcpy(sarb->tail, source + ATM_CELL_HEADER, ATM_CELL_PAYLOAD);346346+ __skb_put(sarb, ATM_CELL_PAYLOAD);347347+348348+ if (pti & 1) {349349+ struct sk_buff *skb;350350+ unsigned int length;351351+ unsigned int pdu_length;352352+353353+ length = (source[ATM_CELL_SIZE - 6] << 8) + source[ATM_CELL_SIZE - 5];354354+355355+ /* guard against overflow */356356+ if (length > ATM_MAX_AAL5_PDU) {357357+ atm_dbg(instance, "%s: bogus length %u (vcc: 0x%p)!\n",358358+ __func__, length, vcc);359359+ atomic_inc(&vcc->stats->rx_err);360360+ goto out;361361+ }362362+363363+ pdu_length = usbatm_pdu_length(length);364364+365365+ if (sarb->len < pdu_length) {366366+ atm_dbg(instance, "%s: bogus pdu_length %u (sarb->len: %u, vcc: 0x%p)!\n",367367+ __func__, pdu_length, sarb->len, vcc);368368+ atomic_inc(&vcc->stats->rx_err);369369+ goto out;370370+ }371371+372372+ if (crc32_be(~0, sarb->tail - pdu_length, pdu_length) != 0xc704dd7b) {373373+ atm_dbg(instance, "%s: packet failed crc check (vcc: 0x%p)!\n",374374+ __func__, vcc);375375+ atomic_inc(&vcc->stats->rx_err);376376+ goto out;377377+ }378378+379379+ vdbg("%s: got packet (length: %u, pdu_length: %u, vcc: 0x%p)", __func__, length, pdu_length, vcc);380380+381381+ if (!(skb = dev_alloc_skb(length))) {382382+ atm_dbg(instance, "%s: no memory for skb (length: %u)!\n", __func__, length);383383+ atomic_inc(&vcc->stats->rx_drop);384384+ goto out;385385+ }386386+387387+ vdbg("%s: allocated new sk_buff (skb: 0x%p, skb->truesize: %u)", __func__, skb, skb->truesize);388388+389389+ if (!atm_charge(vcc, skb->truesize)) {390390+ atm_dbg(instance, "%s: failed atm_charge (skb->truesize: %u)!\n", __func__, skb->truesize);391391+ dev_kfree_skb(skb);392392+ goto out; /* atm_charge increments rx_drop */393393+ }394394+395395+ memcpy(skb->data, sarb->tail - pdu_length, length);396396+ __skb_put(skb, length);397397+398398+ vdbg("%s: sending skb 0x%p, skb->len %u, skb->truesize %u",399399+ __func__, skb, skb->len, skb->truesize);400400+401401+ PACKETDEBUG(skb->data, skb->len);402402+403403+ vcc->push(vcc, skb);404404+405405+ atomic_inc(&vcc->stats->rx);406406+ out:407407+ skb_trim(sarb, 0);408408+ }409409+ }410410+}411411+412412+413413+/*************414414+** encode **415415+*************/416416+417417+static unsigned int usbatm_write_cells(struct usbatm_data *instance,418418+ struct sk_buff *skb,419419+ u8 *target, unsigned int avail_space)420420+{421421+ struct usbatm_control *ctrl = UDSL_SKB(skb);422422+ struct atm_vcc *vcc = ctrl->atm.vcc;423423+ unsigned int num_written;424424+ unsigned int stride = instance->tx_channel.stride;425425+426426+ vdbg("%s: skb->len=%d, avail_space=%u", __func__, skb->len, avail_space);427427+ UDSL_ASSERT(!(avail_space % stride));428428+429429+ for (num_written = 0; num_written < avail_space && ctrl->len;430430+ num_written += stride, target += stride) {431431+ unsigned int data_len = min_t(unsigned int, skb->len, ATM_CELL_PAYLOAD);432432+ unsigned int left = ATM_CELL_PAYLOAD - data_len;433433+ u8 *ptr = target;434434+435435+ ptr[0] = vcc->vpi >> 4;436436+ ptr[1] = (vcc->vpi << 4) | (vcc->vci >> 12);437437+ ptr[2] = vcc->vci >> 4;438438+ ptr[3] = vcc->vci << 4;439439+ ptr[4] = 0xec;440440+ ptr += ATM_CELL_HEADER;441441+442442+ memcpy(ptr, skb->data, data_len);443443+ ptr += data_len;444444+ __skb_pull(skb, data_len);445445+446446+ if(!left)447447+ continue;448448+449449+ memset(ptr, 0, left);450450+451451+ if (left >= ATM_AAL5_TRAILER) { /* trailer will go in this cell */452452+ u8 *trailer = target + ATM_CELL_SIZE - ATM_AAL5_TRAILER;453453+ /* trailer[0] = 0; UU = 0 */454454+ /* trailer[1] = 0; CPI = 0 */455455+ trailer[2] = ctrl->len >> 8;456456+ trailer[3] = ctrl->len;457457+458458+ ctrl->crc = ~ crc32_be(ctrl->crc, ptr, left - 4);459459+460460+ trailer[4] = ctrl->crc >> 24;461461+ trailer[5] = ctrl->crc >> 16;462462+ trailer[6] = ctrl->crc >> 8;463463+ trailer[7] = ctrl->crc;464464+465465+ target[3] |= 0x2; /* adjust PTI */466466+467467+ ctrl->len = 0; /* tag this skb finished */468468+ }469469+ else470470+ ctrl->crc = crc32_be(ctrl->crc, ptr, left);471471+ }472472+473473+ return num_written;474474+}475475+476476+477477+/**************478478+** receive **479479+**************/480480+481481+static void usbatm_rx_process(unsigned long data)482482+{483483+ struct usbatm_data *instance = (struct usbatm_data *)data;484484+ struct urb *urb;485485+486486+ while ((urb = usbatm_pop_urb(&instance->rx_channel))) {487487+ vdbg("%s: processing urb 0x%p", __func__, urb);488488+489489+ if (usb_pipeisoc(urb->pipe)) {490490+ int i;491491+ for (i = 0; i < urb->number_of_packets; i++)492492+ if (!urb->iso_frame_desc[i].status)493493+ usbatm_extract_cells(instance,494494+ (u8 *)urb->transfer_buffer + urb->iso_frame_desc[i].offset,495495+ urb->iso_frame_desc[i].actual_length);496496+ }497497+ else498498+ if (!urb->status)499499+ usbatm_extract_cells(instance, urb->transfer_buffer, urb->actual_length);500500+501501+ if (usbatm_submit_urb(urb))502502+ return;503503+ }504504+}505505+506506+507507+/***********508508+** send **509509+***********/510510+511511+static void usbatm_tx_process(unsigned long data)512512+{513513+ struct usbatm_data *instance = (struct usbatm_data *)data;514514+ struct sk_buff *skb = instance->current_skb;515515+ struct urb *urb = NULL;516516+ const unsigned int buf_size = instance->tx_channel.buf_size;517517+ unsigned int num_written = 0;518518+ u8 *buffer = NULL;519519+520520+ if (!skb)521521+ skb = skb_dequeue(&instance->sndqueue);522522+523523+ while (skb) {524524+ if (!urb) {525525+ urb = usbatm_pop_urb(&instance->tx_channel);526526+ if (!urb)527527+ break; /* no more senders */528528+ buffer = urb->transfer_buffer;529529+ num_written = (urb->status == -EAGAIN) ?530530+ urb->transfer_buffer_length : 0;531531+ }532532+533533+ num_written += usbatm_write_cells(instance, skb,534534+ buffer + num_written,535535+ buf_size - num_written);536536+537537+ vdbg("%s: wrote %u bytes from skb 0x%p to urb 0x%p",538538+ __func__, num_written, skb, urb);539539+540540+ if (!UDSL_SKB(skb)->len) {541541+ struct atm_vcc *vcc = UDSL_SKB(skb)->atm.vcc;542542+543543+ usbatm_pop(vcc, skb);544544+ atomic_inc(&vcc->stats->tx);545545+546546+ skb = skb_dequeue(&instance->sndqueue);547547+ }548548+549549+ if (num_written == buf_size || (!skb && num_written)) {550550+ urb->transfer_buffer_length = num_written;551551+552552+ if (usbatm_submit_urb(urb))553553+ break;554554+ urb = NULL;555555+ }556556+ }557557+558558+ instance->current_skb = skb;559559+}560560+561561+static void usbatm_cancel_send(struct usbatm_data *instance,562562+ struct atm_vcc *vcc)563563+{564564+ struct sk_buff *skb, *n;565565+566566+ atm_dbg(instance, "%s entered\n", __func__);567567+ spin_lock_irq(&instance->sndqueue.lock);568568+ for (skb = instance->sndqueue.next, n = skb->next;569569+ skb != (struct sk_buff *)&instance->sndqueue;570570+ skb = n, n = skb->next)571571+ if (UDSL_SKB(skb)->atm.vcc == vcc) {572572+ atm_dbg(instance, "%s: popping skb 0x%p\n", __func__, skb);573573+ __skb_unlink(skb, &instance->sndqueue);574574+ usbatm_pop(vcc, skb);575575+ }576576+ spin_unlock_irq(&instance->sndqueue.lock);577577+578578+ tasklet_disable(&instance->tx_channel.tasklet);579579+ if ((skb = instance->current_skb) && (UDSL_SKB(skb)->atm.vcc == vcc)) {580580+ atm_dbg(instance, "%s: popping current skb (0x%p)\n", __func__, skb);581581+ instance->current_skb = NULL;582582+ usbatm_pop(vcc, skb);583583+ }584584+ tasklet_enable(&instance->tx_channel.tasklet);585585+ atm_dbg(instance, "%s done\n", __func__);586586+}587587+588588+static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)589589+{590590+ struct usbatm_data *instance = vcc->dev->dev_data;591591+ struct usbatm_control *ctrl = UDSL_SKB(skb);592592+ int err;593593+594594+ vdbg("%s called (skb 0x%p, len %u)", __func__, skb, skb->len);595595+596596+ if (!instance) {597597+ dbg("%s: NULL data!", __func__);598598+ err = -ENODEV;599599+ goto fail;600600+ }601601+602602+ if (vcc->qos.aal != ATM_AAL5) {603603+ atm_dbg(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal);604604+ err = -EINVAL;605605+ goto fail;606606+ }607607+608608+ if (skb->len > ATM_MAX_AAL5_PDU) {609609+ atm_dbg(instance, "%s: packet too long (%d vs %d)!\n",610610+ __func__, skb->len, ATM_MAX_AAL5_PDU);611611+ err = -EINVAL;612612+ goto fail;613613+ }614614+615615+ PACKETDEBUG(skb->data, skb->len);616616+617617+ /* initialize the control block */618618+ ctrl->atm.vcc = vcc;619619+ ctrl->len = skb->len;620620+ ctrl->crc = crc32_be(~0, skb->data, skb->len);621621+622622+ skb_queue_tail(&instance->sndqueue, skb);623623+ tasklet_schedule(&instance->tx_channel.tasklet);624624+625625+ return 0;626626+627627+ fail:628628+ usbatm_pop(vcc, skb);629629+ return err;630630+}631631+632632+633633+/********************634634+** bean counting **635635+********************/636636+637637+static void usbatm_destroy_instance(struct kref *kref)638638+{639639+ struct usbatm_data *instance = container_of(kref, struct usbatm_data, refcount);640640+641641+ dbg("%s", __func__);642642+643643+ tasklet_kill(&instance->rx_channel.tasklet);644644+ tasklet_kill(&instance->tx_channel.tasklet);645645+ usb_put_dev(instance->usb_dev);646646+ kfree(instance);647647+}648648+649649+void usbatm_get_instance(struct usbatm_data *instance)650650+{651651+ dbg("%s", __func__);652652+653653+ kref_get(&instance->refcount);654654+}655655+656656+void usbatm_put_instance(struct usbatm_data *instance)657657+{658658+ dbg("%s", __func__);659659+660660+ kref_put(&instance->refcount, usbatm_destroy_instance);661661+}662662+663663+664664+/**********665665+** ATM **666666+**********/667667+668668+static void usbatm_atm_dev_close(struct atm_dev *dev)669669+{670670+ struct usbatm_data *instance = dev->dev_data;671671+672672+ dbg("%s", __func__);673673+674674+ if (!instance)675675+ return;676676+677677+ dev->dev_data = NULL;678678+ usbatm_put_instance(instance); /* taken in usbatm_atm_init */679679+}680680+681681+static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *page)682682+{683683+ struct usbatm_data *instance = atm_dev->dev_data;684684+ int left = *pos;685685+686686+ if (!instance) {687687+ dbg("%s: NULL instance!", __func__);688688+ return -ENODEV;689689+ }690690+691691+ if (!left--)692692+ return sprintf(page, "%s\n", instance->description);693693+694694+ if (!left--)695695+ return sprintf(page, "MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",696696+ atm_dev->esi[0], atm_dev->esi[1],697697+ atm_dev->esi[2], atm_dev->esi[3],698698+ atm_dev->esi[4], atm_dev->esi[5]);699699+700700+ if (!left--)701701+ return sprintf(page,702702+ "AAL5: tx %d ( %d err ), rx %d ( %d err, %d drop )\n",703703+ atomic_read(&atm_dev->stats.aal5.tx),704704+ atomic_read(&atm_dev->stats.aal5.tx_err),705705+ atomic_read(&atm_dev->stats.aal5.rx),706706+ atomic_read(&atm_dev->stats.aal5.rx_err),707707+ atomic_read(&atm_dev->stats.aal5.rx_drop));708708+709709+ if (!left--)710710+ switch (atm_dev->signal) {711711+ case ATM_PHY_SIG_FOUND:712712+ return sprintf(page, "Line up\n");713713+ case ATM_PHY_SIG_LOST:714714+ return sprintf(page, "Line down\n");715715+ default:716716+ return sprintf(page, "Line state unknown\n");717717+ }718718+719719+ return 0;720720+}721721+722722+static int usbatm_atm_open(struct atm_vcc *vcc)723723+{724724+ struct usbatm_data *instance = vcc->dev->dev_data;725725+ struct usbatm_vcc_data *new = NULL;726726+ int ret;727727+ int vci = vcc->vci;728728+ short vpi = vcc->vpi;729729+730730+ if (!instance) {731731+ dbg("%s: NULL data!", __func__);732732+ return -ENODEV;733733+ }734734+735735+ atm_dbg(instance, "%s: vpi %hd, vci %d\n", __func__, vpi, vci);736736+737737+ /* only support AAL5 */738738+ if ((vcc->qos.aal != ATM_AAL5) || (vcc->qos.rxtp.max_sdu < 0)739739+ || (vcc->qos.rxtp.max_sdu > ATM_MAX_AAL5_PDU)) {740740+ atm_dbg(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal);741741+ return -EINVAL;742742+ }743743+744744+ down(&instance->serialize); /* vs self, usbatm_atm_close */745745+746746+ if (usbatm_find_vcc(instance, vpi, vci)) {747747+ atm_dbg(instance, "%s: %hd/%d already in use!\n", __func__, vpi, vci);748748+ ret = -EADDRINUSE;749749+ goto fail;750750+ }751751+752752+ if (!(new = kmalloc(sizeof(struct usbatm_vcc_data), GFP_KERNEL))) {753753+ atm_dbg(instance, "%s: no memory for vcc_data!\n", __func__);754754+ ret = -ENOMEM;755755+ goto fail;756756+ }757757+758758+ memset(new, 0, sizeof(struct usbatm_vcc_data));759759+ new->vcc = vcc;760760+ new->vpi = vpi;761761+ new->vci = vci;762762+763763+ new->sarb = alloc_skb(usbatm_pdu_length(vcc->qos.rxtp.max_sdu), GFP_KERNEL);764764+ if (!new->sarb) {765765+ atm_dbg(instance, "%s: no memory for SAR buffer!\n", __func__);766766+ ret = -ENOMEM;767767+ goto fail;768768+ }769769+770770+ vcc->dev_data = new;771771+772772+ tasklet_disable(&instance->rx_channel.tasklet);773773+ list_add(&new->list, &instance->vcc_list);774774+ tasklet_enable(&instance->rx_channel.tasklet);775775+776776+ set_bit(ATM_VF_ADDR, &vcc->flags);777777+ set_bit(ATM_VF_PARTIAL, &vcc->flags);778778+ set_bit(ATM_VF_READY, &vcc->flags);779779+780780+ up(&instance->serialize);781781+782782+ atm_dbg(instance, "%s: allocated vcc data 0x%p\n", __func__, new);783783+784784+ return 0;785785+786786+fail:787787+ kfree(new);788788+ up(&instance->serialize);789789+ return ret;790790+}791791+792792+static void usbatm_atm_close(struct atm_vcc *vcc)793793+{794794+ struct usbatm_data *instance = vcc->dev->dev_data;795795+ struct usbatm_vcc_data *vcc_data = vcc->dev_data;796796+797797+ if (!instance || !vcc_data) {798798+ dbg("%s: NULL data!", __func__);799799+ return;800800+ }801801+802802+ atm_dbg(instance, "%s entered\n", __func__);803803+804804+ atm_dbg(instance, "%s: deallocating vcc 0x%p with vpi %d vci %d\n",805805+ __func__, vcc_data, vcc_data->vpi, vcc_data->vci);806806+807807+ usbatm_cancel_send(instance, vcc);808808+809809+ down(&instance->serialize); /* vs self, usbatm_atm_open */810810+811811+ tasklet_disable(&instance->rx_channel.tasklet);812812+ list_del(&vcc_data->list);813813+ tasklet_enable(&instance->rx_channel.tasklet);814814+815815+ kfree_skb(vcc_data->sarb);816816+ vcc_data->sarb = NULL;817817+818818+ kfree(vcc_data);819819+ vcc->dev_data = NULL;820820+821821+ vcc->vpi = ATM_VPI_UNSPEC;822822+ vcc->vci = ATM_VCI_UNSPEC;823823+ clear_bit(ATM_VF_READY, &vcc->flags);824824+ clear_bit(ATM_VF_PARTIAL, &vcc->flags);825825+ clear_bit(ATM_VF_ADDR, &vcc->flags);826826+827827+ up(&instance->serialize);828828+829829+ atm_dbg(instance, "%s successful\n", __func__);830830+}831831+832832+static int usbatm_atm_ioctl(struct atm_dev *dev, unsigned int cmd,833833+ void __user * arg)834834+{835835+ switch (cmd) {836836+ case ATM_QUERYLOOP:837837+ return put_user(ATM_LM_NONE, (int __user *)arg) ? -EFAULT : 0;838838+ default:839839+ return -ENOIOCTLCMD;840840+ }841841+}842842+843843+static int usbatm_atm_init(struct usbatm_data *instance)844844+{845845+ struct atm_dev *atm_dev;846846+ int ret, i;847847+848848+ /* ATM init */849849+ atm_dev = atm_dev_register(instance->driver_name, &usbatm_atm_devops, -1, NULL);850850+ if (!atm_dev) {851851+ usb_dbg(instance, "%s: failed to register ATM device!\n", __func__);852852+ return -1;853853+ }854854+855855+ instance->atm_dev = atm_dev;856856+857857+ atm_dev->ci_range.vpi_bits = ATM_CI_MAX;858858+ atm_dev->ci_range.vci_bits = ATM_CI_MAX;859859+ atm_dev->signal = ATM_PHY_SIG_UNKNOWN;860860+861861+ /* temp init ATM device, set to 128kbit */862862+ atm_dev->link_rate = 128 * 1000 / 424;863863+864864+ if (instance->driver->atm_start && ((ret = instance->driver->atm_start(instance, atm_dev)) < 0)) {865865+ atm_dbg(instance, "%s: atm_start failed: %d!\n", __func__, ret);866866+ goto fail;867867+ }868868+869869+ /* ready for ATM callbacks */870870+ usbatm_get_instance(instance); /* dropped in usbatm_atm_dev_close */871871+ mb();872872+ atm_dev->dev_data = instance;873873+874874+ /* submit all rx URBs */875875+ for (i = 0; i < num_rcv_urbs; i++)876876+ usbatm_submit_urb(instance->urbs[i]);877877+878878+ return 0;879879+880880+ fail:881881+ instance->atm_dev = NULL;882882+ shutdown_atm_dev(atm_dev); /* usbatm_atm_dev_close will eventually be called */883883+ return ret;884884+}885885+886886+887887+/**********888888+** USB **889889+**********/890890+891891+static int usbatm_do_heavy_init(void *arg)892892+{893893+ struct usbatm_data *instance = arg;894894+ int ret;895895+896896+ daemonize(instance->driver->driver_name);897897+ allow_signal(SIGTERM);898898+899899+ complete(&instance->thread_started);900900+901901+ ret = instance->driver->heavy_init(instance, instance->usb_intf);902902+903903+ if (!ret)904904+ ret = usbatm_atm_init(instance);905905+906906+ down(&instance->serialize);907907+ instance->thread_pid = -1;908908+ up(&instance->serialize);909909+910910+ complete_and_exit(&instance->thread_exited, ret);911911+}912912+913913+static int usbatm_heavy_init(struct usbatm_data *instance)914914+{915915+ int ret = kernel_thread(usbatm_do_heavy_init, instance, CLONE_KERNEL);916916+917917+ if (ret < 0) {918918+ usb_dbg(instance, "%s: failed to create kernel_thread (%d)!\n", __func__, ret);919919+ return ret;920920+ }921921+922922+ down(&instance->serialize);923923+ instance->thread_pid = ret;924924+ up(&instance->serialize);925925+926926+ wait_for_completion(&instance->thread_started);927927+928928+ return 0;929929+}930930+931931+static void usbatm_tasklet_schedule(unsigned long data)932932+{933933+ tasklet_schedule((struct tasklet_struct *) data);934934+}935935+936936+static inline void usbatm_init_channel(struct usbatm_channel *channel)937937+{938938+ spin_lock_init(&channel->lock);939939+ INIT_LIST_HEAD(&channel->list);940940+ channel->delay.function = usbatm_tasklet_schedule;941941+ channel->delay.data = (unsigned long) &channel->tasklet;942942+ init_timer(&channel->delay);943943+}944944+945945+int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id,946946+ struct usbatm_driver *driver)947947+{948948+ struct device *dev = &intf->dev;949949+ struct usb_device *usb_dev = interface_to_usbdev(intf);950950+ struct usbatm_data *instance;951951+ char *buf;952952+ int error = -ENOMEM;953953+ int i, length;954954+ int need_heavy;955955+956956+ dev_dbg(dev, "%s: trying driver %s with vendor=0x%x, product=0x%x, ifnum %d\n",957957+ __func__, driver->driver_name,958958+ le16_to_cpu(usb_dev->descriptor.idVendor),959959+ le16_to_cpu(usb_dev->descriptor.idProduct),960960+ intf->altsetting->desc.bInterfaceNumber);961961+962962+ /* instance init */963963+ instance = kcalloc(1, sizeof(*instance) + sizeof(struct urb *) * (num_rcv_urbs + num_snd_urbs), GFP_KERNEL);964964+ if (!instance) {965965+ dev_dbg(dev, "%s: no memory for instance data!\n", __func__);966966+ return -ENOMEM;967967+ }968968+969969+ /* public fields */970970+971971+ instance->driver = driver;972972+ snprintf(instance->driver_name, sizeof(instance->driver_name), driver->driver_name);973973+974974+ instance->usb_dev = usb_dev;975975+ instance->usb_intf = intf;976976+977977+ buf = instance->description;978978+ length = sizeof(instance->description);979979+980980+ if ((i = usb_string(usb_dev, usb_dev->descriptor.iProduct, buf, length)) < 0)981981+ goto bind;982982+983983+ buf += i;984984+ length -= i;985985+986986+ i = scnprintf(buf, length, " (");987987+ buf += i;988988+ length -= i;989989+990990+ if (length <= 0 || (i = usb_make_path(usb_dev, buf, length)) < 0)991991+ goto bind;992992+993993+ buf += i;994994+ length -= i;995995+996996+ snprintf(buf, length, ")");997997+998998+ bind:999999+ need_heavy = 1;10001000+ if (driver->bind && (error = driver->bind(instance, intf, id, &need_heavy)) < 0) {10011001+ dev_dbg(dev, "%s: bind failed: %d!\n", __func__, error);10021002+ goto fail_free;10031003+ }10041004+10051005+ /* private fields */10061006+10071007+ kref_init(&instance->refcount); /* dropped in usbatm_usb_disconnect */10081008+ init_MUTEX(&instance->serialize);10091009+10101010+ instance->thread_pid = -1;10111011+ init_completion(&instance->thread_started);10121012+ init_completion(&instance->thread_exited);10131013+10141014+ INIT_LIST_HEAD(&instance->vcc_list);10151015+10161016+ usbatm_init_channel(&instance->rx_channel);10171017+ usbatm_init_channel(&instance->tx_channel);10181018+ tasklet_init(&instance->rx_channel.tasklet, usbatm_rx_process, (unsigned long)instance);10191019+ tasklet_init(&instance->tx_channel.tasklet, usbatm_tx_process, (unsigned long)instance);10201020+ instance->rx_channel.endpoint = usb_rcvbulkpipe(usb_dev, driver->in);10211021+ instance->tx_channel.endpoint = usb_sndbulkpipe(usb_dev, driver->out);10221022+ instance->rx_channel.stride = ATM_CELL_SIZE + driver->rx_padding;10231023+ instance->tx_channel.stride = ATM_CELL_SIZE + driver->tx_padding;10241024+ instance->rx_channel.buf_size = rcv_buf_size * instance->rx_channel.stride;10251025+ instance->tx_channel.buf_size = snd_buf_size * instance->tx_channel.stride;10261026+ instance->rx_channel.usbatm = instance->tx_channel.usbatm = instance;10271027+10281028+ skb_queue_head_init(&instance->sndqueue);10291029+10301030+ for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) {10311031+ struct urb *urb;10321032+ u8 *buffer;10331033+ unsigned int iso_packets = 0, iso_size = 0;10341034+ struct usbatm_channel *channel = i < num_rcv_urbs ?10351035+ &instance->rx_channel : &instance->tx_channel;10361036+10371037+ if (usb_pipeisoc(channel->endpoint)) {10381038+ /* don't expect iso out endpoints */10391039+ iso_size = usb_maxpacket(instance->usb_dev, channel->endpoint, 0);10401040+ iso_size -= iso_size % channel->stride; /* alignment */10411041+ BUG_ON(!iso_size);10421042+ iso_packets = (channel->buf_size - 1) / iso_size + 1;10431043+ }10441044+10451045+ urb = usb_alloc_urb(iso_packets, GFP_KERNEL);10461046+ if (!urb) {10471047+ dev_dbg(dev, "%s: no memory for urb %d!\n", __func__, i);10481048+ goto fail_unbind;10491049+ }10501050+10511051+ instance->urbs[i] = urb;10521052+10531053+ buffer = kmalloc(channel->buf_size, GFP_KERNEL);10541054+ if (!buffer) {10551055+ dev_dbg(dev, "%s: no memory for buffer %d!\n", __func__, i);10561056+ goto fail_unbind;10571057+ }10581058+ memset(buffer, 0, channel->buf_size);10591059+10601060+ usb_fill_bulk_urb(urb, instance->usb_dev, channel->endpoint,10611061+ buffer, channel->buf_size, usbatm_complete, channel);10621062+ if (iso_packets) {10631063+ int j;10641064+ urb->interval = 1;10651065+ urb->transfer_flags = URB_ISO_ASAP;10661066+ urb->number_of_packets = iso_packets;10671067+ for (j = 0; j < iso_packets; j++) {10681068+ urb->iso_frame_desc[j].offset = iso_size * j;10691069+ urb->iso_frame_desc[j].length = min_t(int, iso_size,10701070+ channel->buf_size - urb->iso_frame_desc[j].offset);10711071+ }10721072+ }10731073+10741074+ /* put all tx URBs on the list of spares */10751075+ if (i >= num_rcv_urbs)10761076+ list_add_tail(&urb->urb_list, &channel->list);10771077+10781078+ vdbg("%s: alloced buffer 0x%p buf size %u urb 0x%p",10791079+ __func__, urb->transfer_buffer, urb->transfer_buffer_length, urb);10801080+ }10811081+10821082+ if (need_heavy && driver->heavy_init) {10831083+ error = usbatm_heavy_init(instance);10841084+ } else {10851085+ complete(&instance->thread_exited); /* pretend that heavy_init was run */10861086+ error = usbatm_atm_init(instance);10871087+ }10881088+10891089+ if (error < 0)10901090+ goto fail_unbind;10911091+10921092+ usb_get_dev(usb_dev);10931093+ usb_set_intfdata(intf, instance);10941094+10951095+ return 0;10961096+10971097+ fail_unbind:10981098+ if (instance->driver->unbind)10991099+ instance->driver->unbind(instance, intf);11001100+ fail_free:11011101+ for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) {11021102+ if (instance->urbs[i])11031103+ kfree(instance->urbs[i]->transfer_buffer);11041104+ usb_free_urb(instance->urbs[i]);11051105+ }11061106+11071107+ kfree (instance);11081108+11091109+ return error;11101110+}11111111+EXPORT_SYMBOL_GPL(usbatm_usb_probe);11121112+11131113+void usbatm_usb_disconnect(struct usb_interface *intf)11141114+{11151115+ struct device *dev = &intf->dev;11161116+ struct usbatm_data *instance = usb_get_intfdata(intf);11171117+ int i;11181118+11191119+ dev_dbg(dev, "%s entered\n", __func__);11201120+11211121+ if (!instance) {11221122+ dev_dbg(dev, "%s: NULL instance!\n", __func__);11231123+ return;11241124+ }11251125+11261126+ usb_set_intfdata(intf, NULL);11271127+11281128+ down(&instance->serialize);11291129+ if (instance->thread_pid >= 0)11301130+ kill_proc(instance->thread_pid, SIGTERM, 1);11311131+ up(&instance->serialize);11321132+11331133+ wait_for_completion(&instance->thread_exited);11341134+11351135+ tasklet_disable(&instance->rx_channel.tasklet);11361136+ tasklet_disable(&instance->tx_channel.tasklet);11371137+11381138+ for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++)11391139+ usb_kill_urb(instance->urbs[i]);11401140+11411141+ del_timer_sync(&instance->rx_channel.delay);11421142+ del_timer_sync(&instance->tx_channel.delay);11431143+11441144+ if (instance->atm_dev && instance->driver->atm_stop)11451145+ instance->driver->atm_stop(instance, instance->atm_dev);11461146+11471147+ if (instance->driver->unbind)11481148+ instance->driver->unbind(instance, intf);11491149+11501150+ instance->driver_data = NULL;11511151+11521152+ /* turn usbatm_[rt]x_process into noop */11531153+ /* no need to take the spinlock */11541154+ INIT_LIST_HEAD(&instance->rx_channel.list);11551155+ INIT_LIST_HEAD(&instance->tx_channel.list);11561156+11571157+ tasklet_enable(&instance->rx_channel.tasklet);11581158+ tasklet_enable(&instance->tx_channel.tasklet);11591159+11601160+ for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) {11611161+ kfree(instance->urbs[i]->transfer_buffer);11621162+ usb_free_urb(instance->urbs[i]);11631163+ }11641164+11651165+ /* ATM finalize */11661166+ if (instance->atm_dev)11671167+ shutdown_atm_dev(instance->atm_dev);11681168+11691169+ usbatm_put_instance(instance); /* taken in usbatm_usb_probe */11701170+}11711171+EXPORT_SYMBOL_GPL(usbatm_usb_disconnect);11721172+11731173+11741174+/***********11751175+** init **11761176+***********/11771177+11781178+static int __init usbatm_usb_init(void)11791179+{11801180+ dbg("%s: driver version %s", __func__, DRIVER_VERSION);11811181+11821182+ if (sizeof(struct usbatm_control) > sizeof(((struct sk_buff *) 0)->cb)) {11831183+ printk(KERN_ERR "%s unusable with this kernel!\n", usbatm_driver_name);11841184+ return -EIO;11851185+ }11861186+11871187+ if ((num_rcv_urbs > UDSL_MAX_RCV_URBS)11881188+ || (num_snd_urbs > UDSL_MAX_SND_URBS)11891189+ || (rcv_buf_size < 1)11901190+ || (rcv_buf_size > UDSL_MAX_RCV_BUF_SIZE)11911191+ || (snd_buf_size < 1)11921192+ || (snd_buf_size > UDSL_MAX_SND_BUF_SIZE))11931193+ return -EINVAL;11941194+11951195+ return 0;11961196+}11971197+module_init(usbatm_usb_init);11981198+11991199+static void __exit usbatm_usb_exit(void)12001200+{12011201+ dbg("%s", __func__);12021202+}12031203+module_exit(usbatm_usb_exit);12041204+12051205+MODULE_AUTHOR(DRIVER_AUTHOR);12061206+MODULE_DESCRIPTION(DRIVER_DESC);12071207+MODULE_LICENSE("GPL");12081208+MODULE_VERSION(DRIVER_VERSION);12091209+12101210+/************12111211+** debug **12121212+************/12131213+12141214+#ifdef VERBOSE_DEBUG12151215+static int usbatm_print_packet(const unsigned char *data, int len)12161216+{12171217+ unsigned char buffer[256];12181218+ int i = 0, j = 0;12191219+12201220+ for (i = 0; i < len;) {12211221+ buffer[0] = '\0';12221222+ sprintf(buffer, "%.3d :", i);12231223+ for (j = 0; (j < 16) && (i < len); j++, i++) {12241224+ sprintf(buffer, "%s %2.2x", buffer, data[i]);12251225+ }12261226+ dbg("%s", buffer);12271227+ }12281228+ return i;12291229+}12301230+#endif
+184
drivers/usb/atm/usbatm.h
···11+/******************************************************************************22+ * usbatm.h - Generic USB xDSL driver core33+ *44+ * Copyright (C) 2001, Alcatel55+ * Copyright (C) 2003, Duncan Sands, SolNegro, Josep Comas66+ * Copyright (C) 2004, David Woodhouse77+ *88+ * This program is free software; you can redistribute it and/or modify it99+ * under the terms of the GNU General Public License as published by the Free1010+ * Software Foundation; either version 2 of the License, or (at your option)1111+ * any later version.1212+ *1313+ * This program is distributed in the hope that it will be useful, but WITHOUT1414+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or1515+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for1616+ * more details.1717+ *1818+ * You should have received a copy of the GNU General Public License along with1919+ * this program; if not, write to the Free Software Foundation, Inc., 592020+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.2121+ *2222+ ******************************************************************************/2323+2424+#ifndef _USBATM_H_2525+#define _USBATM_H_2626+2727+#include <linux/config.h>2828+2929+/*3030+#define DEBUG3131+#define VERBOSE_DEBUG3232+*/3333+3434+#if !defined (DEBUG) && defined (CONFIG_USB_DEBUG)3535+# define DEBUG3636+#endif3737+3838+#include <asm/semaphore.h>3939+#include <linux/atm.h>4040+#include <linux/atmdev.h>4141+#include <linux/completion.h>4242+#include <linux/device.h>4343+#include <linux/kref.h>4444+#include <linux/list.h>4545+#include <linux/stringify.h>4646+#include <linux/usb.h>4747+4848+#ifdef DEBUG4949+#define UDSL_ASSERT(x) BUG_ON(!(x))5050+#else5151+#define UDSL_ASSERT(x) do { if (!(x)) warn("failed assertion '%s' at line %d", __stringify(x), __LINE__); } while(0)5252+#endif5353+5454+#define usb_err(instance, format, arg...) \5555+ dev_err(&(instance)->usb_intf->dev , format , ## arg)5656+#define usb_info(instance, format, arg...) \5757+ dev_info(&(instance)->usb_intf->dev , format , ## arg)5858+#define usb_warn(instance, format, arg...) \5959+ dev_warn(&(instance)->usb_intf->dev , format , ## arg)6060+#define usb_dbg(instance, format, arg...) \6161+ dev_dbg(&(instance)->usb_intf->dev , format , ## arg)6262+6363+/* FIXME: move to dev_* once ATM is driver model aware */6464+#define atm_printk(level, instance, format, arg...) \6565+ printk(level "ATM dev %d: " format , \6666+ (instance)->atm_dev->number , ## arg)6767+6868+#define atm_err(instance, format, arg...) \6969+ atm_printk(KERN_ERR, instance , format , ## arg)7070+#define atm_info(instance, format, arg...) \7171+ atm_printk(KERN_INFO, instance , format , ## arg)7272+#define atm_warn(instance, format, arg...) \7373+ atm_printk(KERN_WARNING, instance , format , ## arg)7474+#ifdef DEBUG7575+#define atm_dbg(instance, format, arg...) \7676+ atm_printk(KERN_DEBUG, instance , format , ## arg)7777+#else7878+#define atm_dbg(instance, format, arg...) \7979+ do {} while (0)8080+#endif8181+8282+8383+/* mini driver */8484+8585+struct usbatm_data;8686+8787+/*8888+* Assuming all methods exist and succeed, they are called in this order:8989+*9090+* bind, heavy_init, atm_start, ..., atm_stop, unbind9191+*/9292+9393+struct usbatm_driver {9494+ struct module *owner;9595+9696+ const char *driver_name;9797+9898+ /*9999+ * init device ... can sleep, or cause probe() failure. Drivers with a heavy_init100100+ * method can avoid having it called by setting need_heavy_init to zero.101101+ */102102+ int (*bind) (struct usbatm_data *, struct usb_interface *,103103+ const struct usb_device_id *id, int *need_heavy_init);104104+105105+ /* additional device initialization that is too slow to be done in probe() */106106+ int (*heavy_init) (struct usbatm_data *, struct usb_interface *);107107+108108+ /* cleanup device ... can sleep, but can't fail */109109+ void (*unbind) (struct usbatm_data *, struct usb_interface *);110110+111111+ /* init ATM device ... can sleep, or cause ATM initialization failure */112112+ int (*atm_start) (struct usbatm_data *, struct atm_dev *);113113+114114+ /* cleanup ATM device ... can sleep, but can't fail */115115+ void (*atm_stop) (struct usbatm_data *, struct atm_dev *);116116+117117+ int in; /* rx endpoint */118118+ int out; /* tx endpoint */119119+120120+ unsigned rx_padding;121121+ unsigned tx_padding;122122+};123123+124124+extern int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id,125125+ struct usbatm_driver *driver);126126+extern void usbatm_usb_disconnect(struct usb_interface *intf);127127+128128+129129+struct usbatm_channel {130130+ int endpoint; /* usb pipe */131131+ unsigned int stride; /* ATM cell size + padding */132132+ unsigned int buf_size; /* urb buffer size */133133+ spinlock_t lock;134134+ struct list_head list;135135+ struct tasklet_struct tasklet;136136+ struct timer_list delay;137137+ struct usbatm_data *usbatm;138138+};139139+140140+/* main driver data */141141+142142+struct usbatm_data {143143+ /******************144144+ * public fields *145145+ ******************/146146+147147+ /* mini driver */148148+ struct usbatm_driver *driver;149149+ void *driver_data;150150+ char driver_name[16];151151+152152+ /* USB device */153153+ struct usb_device *usb_dev;154154+ struct usb_interface *usb_intf;155155+ char description[64];156156+157157+ /* ATM device */158158+ struct atm_dev *atm_dev;159159+160160+ /********************************161161+ * private fields - do not use *162162+ ********************************/163163+164164+ struct kref refcount;165165+ struct semaphore serialize;166166+167167+ /* heavy init */168168+ int thread_pid;169169+ struct completion thread_started;170170+ struct completion thread_exited;171171+172172+ /* ATM device */173173+ struct list_head vcc_list;174174+175175+ struct usbatm_channel rx_channel;176176+ struct usbatm_channel tx_channel;177177+178178+ struct sk_buff_head sndqueue;179179+ struct sk_buff *current_skb; /* being emptied */180180+181181+ struct urb *urbs[0];182182+};183183+184184+#endif /* _USBATM_H_ */
+196
drivers/usb/atm/xusbatm.c
···11+/******************************************************************************22+ * xusbatm.c - dumb usbatm-based driver for modems initialized in userspace33+ *44+ * Copyright (C) 2005 Duncan Sands, Roman Kagan (rkagan % mail ! ru)55+ *66+ * This program is free software; you can redistribute it and/or modify it77+ * under the terms of the GNU General Public License as published by the Free88+ * Software Foundation; either version 2 of the License, or (at your option)99+ * any later version.1010+ *1111+ * This program is distributed in the hope that it will be useful, but WITHOUT1212+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or1313+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for1414+ * more details.1515+ *1616+ * You should have received a copy of the GNU General Public License along with1717+ * this program; if not, write to the Free Software Foundation, Inc., 591818+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.1919+ *2020+ ******************************************************************************/2121+2222+#include <linux/module.h>2323+#include <linux/netdevice.h> /* FIXME: required by linux/etherdevice.h */2424+#include <linux/etherdevice.h> /* for random_ether_addr() */2525+2626+#include "usbatm.h"2727+2828+2929+#define XUSBATM_DRIVERS_MAX 83030+3131+#define XUSBATM_PARM(name, type, parmtype, desc) \3232+ static type name[XUSBATM_DRIVERS_MAX]; \3333+ static int num_##name; \3434+ module_param_array(name, parmtype, &num_##name, 0444); \3535+ MODULE_PARM_DESC(name, desc)3636+3737+XUSBATM_PARM(vendor, unsigned short, ushort, "USB device vendor");3838+XUSBATM_PARM(product, unsigned short, ushort, "USB device product");3939+4040+XUSBATM_PARM(rx_endpoint, unsigned char, byte, "rx endpoint number");4141+XUSBATM_PARM(tx_endpoint, unsigned char, byte, "tx endpoint number");4242+XUSBATM_PARM(rx_padding, unsigned char, byte, "rx padding (default 0)");4343+XUSBATM_PARM(tx_padding, unsigned char, byte, "tx padding (default 0)");4444+4545+static const char xusbatm_driver_name[] = "xusbatm";4646+4747+static struct usbatm_driver xusbatm_drivers[XUSBATM_DRIVERS_MAX];4848+static struct usb_device_id xusbatm_usb_ids[XUSBATM_DRIVERS_MAX + 1];4949+static struct usb_driver xusbatm_usb_driver;5050+5151+static int usb_intf_has_ep(const struct usb_interface *intf, u8 ep)5252+{5353+ int i, j;5454+5555+ for (i = 0; i < intf->num_altsetting; i++) {5656+ struct usb_host_interface *alt = intf->altsetting;5757+ for (j = 0; j < alt->desc.bNumEndpoints; j++)5858+ if ((alt->endpoint[i].desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) == ep)5959+ return 1;6060+ }6161+ return 0;6262+}6363+6464+static int xusbatm_bind(struct usbatm_data *usbatm_instance,6565+ struct usb_interface *intf, const struct usb_device_id *id,6666+ int *need_heavy_init)6767+{6868+ struct usb_device *usb_dev = interface_to_usbdev(intf);6969+ int drv_ix = id - xusbatm_usb_ids;7070+ int rx_ep_present = usb_intf_has_ep(intf, rx_endpoint[drv_ix]);7171+ int tx_ep_present = usb_intf_has_ep(intf, tx_endpoint[drv_ix]);7272+ u8 searched_ep = rx_ep_present ? tx_endpoint[drv_ix] : rx_endpoint[drv_ix];7373+ int i, ret;7474+7575+ usb_dbg(usbatm_instance, "%s: binding driver %d: vendor %#x product %#x"7676+ " rx: ep %#x padd %d tx: ep %#x padd %d\n",7777+ __func__, drv_ix, vendor[drv_ix], product[drv_ix],7878+ rx_endpoint[drv_ix], rx_padding[drv_ix],7979+ tx_endpoint[drv_ix], tx_padding[drv_ix]);8080+8181+ if (!rx_ep_present && !tx_ep_present) {8282+ usb_dbg(usbatm_instance, "%s: intf #%d has neither rx (%#x) nor tx (%#x) endpoint\n",8383+ __func__, intf->altsetting->desc.bInterfaceNumber,8484+ rx_endpoint[drv_ix], tx_endpoint[drv_ix]);8585+ return -ENODEV;8686+ }8787+8888+ if (rx_ep_present && tx_ep_present)8989+ return 0;9090+9191+ for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) {9292+ struct usb_interface *cur_if = usb_dev->actconfig->interface[i];9393+9494+ if (cur_if != intf && usb_intf_has_ep(cur_if, searched_ep)) {9595+ ret = usb_driver_claim_interface(&xusbatm_usb_driver,9696+ cur_if, usbatm_instance);9797+ if (!ret)9898+ usb_err(usbatm_instance, "%s: failed to claim interface #%d (%d)\n",9999+ __func__, cur_if->altsetting->desc.bInterfaceNumber, ret);100100+ return ret;101101+ }102102+ }103103+104104+ usb_err(usbatm_instance, "%s: no interface has endpoint %#x\n",105105+ __func__, searched_ep);106106+ return -ENODEV;107107+}108108+109109+static void xusbatm_unbind(struct usbatm_data *usbatm_instance,110110+ struct usb_interface *intf)111111+{112112+ struct usb_device *usb_dev = interface_to_usbdev(intf);113113+ int i;114114+ usb_dbg(usbatm_instance, "%s entered\n", __func__);115115+116116+ for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) {117117+ struct usb_interface *cur_if = usb_dev->actconfig->interface[i];118118+ usb_set_intfdata(cur_if, NULL);119119+ usb_driver_release_interface(&xusbatm_usb_driver, cur_if);120120+ }121121+}122122+123123+static int xusbatm_atm_start(struct usbatm_data *usbatm_instance,124124+ struct atm_dev *atm_dev)125125+{126126+ atm_dbg(usbatm_instance, "%s entered\n", __func__);127127+128128+ /* use random MAC as we've no way to get it from the device */129129+ random_ether_addr(atm_dev->esi);130130+131131+ return 0;132132+}133133+134134+135135+static int xusbatm_usb_probe(struct usb_interface *intf,136136+ const struct usb_device_id *id)137137+{138138+ return usbatm_usb_probe(intf, id,139139+ xusbatm_drivers + (id - xusbatm_usb_ids));140140+}141141+142142+static struct usb_driver xusbatm_usb_driver = {143143+ .owner = THIS_MODULE,144144+ .name = xusbatm_driver_name,145145+ .probe = xusbatm_usb_probe,146146+ .disconnect = usbatm_usb_disconnect,147147+ .id_table = xusbatm_usb_ids148148+};149149+150150+static int __init xusbatm_init(void)151151+{152152+ int i;153153+154154+ dbg("xusbatm_init");155155+156156+ if (!num_vendor ||157157+ num_vendor != num_product ||158158+ num_vendor != num_rx_endpoint ||159159+ num_vendor != num_tx_endpoint) {160160+ warn("malformed module parameters");161161+ return -EINVAL;162162+ }163163+164164+ for (i = 0; i < num_vendor; i++) {165165+ xusbatm_usb_ids[i].match_flags = USB_DEVICE_ID_MATCH_DEVICE;166166+ xusbatm_usb_ids[i].idVendor = vendor[i];167167+ xusbatm_usb_ids[i].idProduct = product[i];168168+169169+170170+ xusbatm_drivers[i].owner = THIS_MODULE;171171+ xusbatm_drivers[i].driver_name = xusbatm_driver_name;172172+ xusbatm_drivers[i].bind = xusbatm_bind;173173+ xusbatm_drivers[i].unbind = xusbatm_unbind;174174+ xusbatm_drivers[i].atm_start = xusbatm_atm_start;175175+ xusbatm_drivers[i].in = rx_endpoint[i];176176+ xusbatm_drivers[i].out = tx_endpoint[i];177177+ xusbatm_drivers[i].rx_padding = rx_padding[i];178178+ xusbatm_drivers[i].tx_padding = tx_padding[i];179179+ }180180+181181+ return usb_register(&xusbatm_usb_driver);182182+}183183+module_init(xusbatm_init);184184+185185+static void __exit xusbatm_exit(void)186186+{187187+ dbg("xusbatm_exit entered");188188+189189+ usb_deregister(&xusbatm_usb_driver);190190+}191191+module_exit(xusbatm_exit);192192+193193+MODULE_AUTHOR("Roman Kagan, Duncan Sands");194194+MODULE_DESCRIPTION("Driver for USB ADSL modems initialized in userspace");195195+MODULE_LICENSE("GPL");196196+MODULE_VERSION("0.1");
+177-36
drivers/usb/class/cdc-acm.c
···106106 acm_ctrl_msg(acm, USB_CDC_REQ_SEND_BREAK, ms, NULL, 0)107107108108/*109109+ * Write buffer management.110110+ * All of these assume proper locks taken by the caller.111111+ */112112+113113+static int acm_wb_alloc(struct acm *acm)114114+{115115+ int i, wbn;116116+ struct acm_wb *wb;117117+118118+ wbn = acm->write_current;119119+ i = 0;120120+ for (;;) {121121+ wb = &acm->wb[wbn];122122+ if (!wb->use) {123123+ wb->use = 1;124124+ return wbn;125125+ }126126+ wbn = (wbn + 1) % ACM_NWB;127127+ if (++i >= ACM_NWB)128128+ return -1;129129+ }130130+}131131+132132+static void acm_wb_free(struct acm *acm, int wbn)133133+{134134+ acm->wb[wbn].use = 0;135135+}136136+137137+static int acm_wb_is_avail(struct acm *acm)138138+{139139+ int i, n;140140+141141+ n = 0;142142+ for (i = 0; i < ACM_NWB; i++) {143143+ if (!acm->wb[i].use)144144+ n++;145145+ }146146+ return n;147147+}148148+149149+static inline int acm_wb_is_used(struct acm *acm, int wbn)150150+{151151+ return acm->wb[wbn].use;152152+}153153+154154+/*155155+ * Finish write.156156+ */157157+static void acm_write_done(struct acm *acm)158158+{159159+ unsigned long flags;160160+ int wbn;161161+162162+ spin_lock_irqsave(&acm->write_lock, flags);163163+ acm->write_ready = 1;164164+ wbn = acm->write_current;165165+ acm_wb_free(acm, wbn);166166+ acm->write_current = (wbn + 1) % ACM_NWB;167167+ spin_unlock_irqrestore(&acm->write_lock, flags);168168+}169169+170170+/*171171+ * Poke write.172172+ */173173+static int acm_write_start(struct acm *acm)174174+{175175+ unsigned long flags;176176+ int wbn;177177+ struct acm_wb *wb;178178+ int rc;179179+180180+ spin_lock_irqsave(&acm->write_lock, flags);181181+ if (!acm->dev) {182182+ spin_unlock_irqrestore(&acm->write_lock, flags);183183+ return -ENODEV;184184+ }185185+186186+ if (!acm->write_ready) {187187+ spin_unlock_irqrestore(&acm->write_lock, flags);188188+ return 0; /* A white lie */189189+ }190190+191191+ wbn = acm->write_current;192192+ if (!acm_wb_is_used(acm, wbn)) {193193+ spin_unlock_irqrestore(&acm->write_lock, flags);194194+ return 0;195195+ }196196+ wb = &acm->wb[wbn];197197+198198+ acm->write_ready = 0;199199+ spin_unlock_irqrestore(&acm->write_lock, flags);200200+201201+ acm->writeurb->transfer_buffer = wb->buf;202202+ acm->writeurb->transfer_dma = wb->dmah;203203+ acm->writeurb->transfer_buffer_length = wb->len;204204+ acm->writeurb->dev = acm->dev;205205+206206+ if ((rc = usb_submit_urb(acm->writeurb, GFP_ATOMIC)) < 0) {207207+ dbg("usb_submit_urb(write bulk) failed: %d", rc);208208+ acm_write_done(acm);209209+ }210210+ return rc;211211+}212212+213213+/*109214 * Interrupt handlers for various ACM device responses110215 */111216···342237static void acm_write_bulk(struct urb *urb, struct pt_regs *regs)343238{344239 struct acm *acm = (struct acm *)urb->context;240240+345241 dbg("Entering acm_write_bulk with status %d\n", urb->status);346242347347- if (!ACM_READY(acm))348348- goto out;349349-350350- if (urb->status)351351- dbg("nonzero write bulk status received: %d", urb->status);352352-353353- schedule_work(&acm->work);354354-out:355355- acm->ready_for_write = 1;243243+ acm_write_done(acm);244244+ acm_write_start(acm);245245+ if (ACM_READY(acm))246246+ schedule_work(&acm->work);356247}357248358249static void acm_softint(void *private)···452351{453352 struct acm *acm = tty->driver_data;454353 int stat;354354+ unsigned long flags;355355+ int wbn;356356+ struct acm_wb *wb;357357+455358 dbg("Entering acm_tty_write to write %d bytes,\n", count);456359457360 if (!ACM_READY(acm))458361 return -EINVAL;459459- if (!acm->ready_for_write)460460- return 0;461362 if (!count)462363 return 0;463364464464- count = (count > acm->writesize) ? acm->writesize : count;465465-466466- dbg("Get %d bytes...", count);467467- memcpy(acm->write_buffer, buf, count);468468- dbg(" Successfully copied.\n");469469-470470- acm->writeurb->transfer_buffer_length = count;471471- acm->writeurb->dev = acm->dev;472472-473473- acm->ready_for_write = 0;474474- stat = usb_submit_urb(acm->writeurb, GFP_ATOMIC);475475- if (stat < 0) {476476- dbg("usb_submit_urb(write bulk) failed");477477- acm->ready_for_write = 1;478478- return stat;365365+ spin_lock_irqsave(&acm->write_lock, flags);366366+ if ((wbn = acm_wb_alloc(acm)) < 0) {367367+ spin_unlock_irqrestore(&acm->write_lock, flags);368368+ acm_write_start(acm);369369+ return 0;479370 }371371+ wb = &acm->wb[wbn];480372373373+ count = (count > acm->writesize) ? acm->writesize : count;374374+ dbg("Get %d bytes...", count);375375+ memcpy(wb->buf, buf, count);376376+ wb->len = count;377377+ spin_unlock_irqrestore(&acm->write_lock, flags);378378+379379+ if ((stat = acm_write_start(acm)) < 0)380380+ return stat;481381 return count;482382}483383···487385 struct acm *acm = tty->driver_data;488386 if (!ACM_READY(acm))489387 return -EINVAL;490490- return !acm->ready_for_write ? 0 : acm->writesize;388388+ /*389389+ * Do not let the line discipline to know that we have a reserve,390390+ * or it might get too enthusiastic.391391+ */392392+ return (acm->write_ready && acm_wb_is_avail(acm)) ? acm->writesize : 0;491393}492394493395static int acm_tty_chars_in_buffer(struct tty_struct *tty)···499393 struct acm *acm = tty->driver_data;500394 if (!ACM_READY(acm))501395 return -EINVAL;502502- return !acm->ready_for_write ? acm->writeurb->transfer_buffer_length : 0;396396+ /*397397+ * This is inaccurate (overcounts), but it works.398398+ */399399+ return (ACM_NWB - acm_wb_is_avail(acm)) * acm->writesize;503400}504401505402static void acm_tty_throttle(struct tty_struct *tty)···634525/*635526 * USB probe and disconnect routines.636527 */528528+529529+/* Little helper: write buffers free */530530+static void acm_write_buffers_free(struct acm *acm)531531+{532532+ int i;533533+ struct acm_wb *wb;534534+535535+ for (wb = &acm->wb[0], i = 0; i < ACM_NWB; i++, wb++) {536536+ usb_buffer_free(acm->dev, acm->writesize, wb->buf, wb->dmah);537537+ }538538+}539539+540540+/* Little helper: write buffers allocate */541541+static int acm_write_buffers_alloc(struct acm *acm)542542+{543543+ int i;544544+ struct acm_wb *wb;545545+546546+ for (wb = &acm->wb[0], i = 0; i < ACM_NWB; i++, wb++) {547547+ wb->buf = usb_buffer_alloc(acm->dev, acm->writesize, GFP_KERNEL,548548+ &wb->dmah);549549+ if (!wb->buf) {550550+ while (i != 0) {551551+ --i;552552+ --wb;553553+ usb_buffer_free(acm->dev, acm->writesize,554554+ wb->buf, wb->dmah);555555+ }556556+ return -ENOMEM;557557+ }558558+ }559559+ return 0;560560+}637561638562static int acm_probe (struct usb_interface *intf,639563 const struct usb_device_id *id)···842700 acm->bh.data = (unsigned long) acm;843701 INIT_WORK(&acm->work, acm_softint, acm);844702 spin_lock_init(&acm->throttle_lock);845845- acm->ready_for_write = 1;703703+ spin_lock_init(&acm->write_lock);704704+ acm->write_ready = 1;846705847706 buf = usb_buffer_alloc(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma);848707 if (!buf) {···859716 }860717 acm->read_buffer = buf;861718862862- buf = usb_buffer_alloc(usb_dev, acm->writesize, GFP_KERNEL, &acm->write_dma);863863- if (!buf) {719719+ if (acm_write_buffers_alloc(acm) < 0) {864720 dev_dbg(&intf->dev, "out of memory (write buffer alloc)\n");865721 goto alloc_fail4;866722 }867867- acm->write_buffer = buf; 868723869724 acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL);870725 if (!acm->ctrlurb) {···891750 acm->readurb->transfer_dma = acm->read_dma;892751893752 usb_fill_bulk_urb(acm->writeurb, usb_dev, usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),894894- acm->write_buffer, acm->writesize, acm_write_bulk, acm);753753+ NULL, acm->writesize, acm_write_bulk, acm);895754 acm->writeurb->transfer_flags |= URB_NO_FSBR | URB_NO_TRANSFER_DMA_MAP;896896- acm->writeurb->transfer_dma = acm->write_dma;755755+ /* acm->writeurb->transfer_dma = 0; */897756898757 dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor);899758···916775alloc_fail6:917776 usb_free_urb(acm->ctrlurb);918777alloc_fail5:919919- usb_buffer_free(usb_dev, acm->writesize, acm->write_buffer, acm->write_dma);778778+ acm_write_buffers_free(acm);920779alloc_fail4:921780 usb_buffer_free(usb_dev, readsize, acm->read_buffer, acm->read_dma);922781alloc_fail3:···947806948807 flush_scheduled_work(); /* wait for acm_softint */949808950950- usb_buffer_free(usb_dev, acm->writesize, acm->write_buffer, acm->write_dma);809809+ acm_write_buffers_free(acm);951810 usb_buffer_free(usb_dev, acm->readsize, acm->read_buffer, acm->read_dma);952811 usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);953812
+22-3
drivers/usb/class/cdc-acm.h
···5151 * Internal driver structures.5252 */53535454+/*5555+ * The only reason to have several buffers is to accomodate assumptions5656+ * in line disciplines. They ask for empty space amount, receive our URB size,5757+ * and proceed to issue several 1-character writes, assuming they will fit.5858+ * The very first write takes a complete URB. Fortunately, this only happens5959+ * when processing onlcr, so we only need 2 buffers.6060+ */6161+#define ACM_NWB 26262+struct acm_wb {6363+ unsigned char *buf;6464+ dma_addr_t dmah;6565+ int len;6666+ int use;6767+};6868+5469struct acm {5570 struct usb_device *dev; /* the corresponding usb device */5671 struct usb_interface *control; /* control interface */5772 struct usb_interface *data; /* data interface */5873 struct tty_struct *tty; /* the corresponding tty */5974 struct urb *ctrlurb, *readurb, *writeurb; /* urbs */6060- u8 *ctrl_buffer, *read_buffer, *write_buffer; /* buffers of urbs */6161- dma_addr_t ctrl_dma, read_dma, write_dma; /* dma handles of buffers */7575+ u8 *ctrl_buffer, *read_buffer; /* buffers of urbs */7676+ dma_addr_t ctrl_dma, read_dma; /* dma handles of buffers */7777+ struct acm_wb wb[ACM_NWB];7878+ int write_current; /* current write buffer */7979+ int write_used; /* number of non-empty write buffers */8080+ int write_ready; /* write urb is not running */8181+ spinlock_t write_lock;6282 struct usb_cdc_line_coding line; /* bits, stop, parity */6383 struct work_struct work; /* work queue entry for line discipline waking up */6484 struct tasklet_struct bh; /* rx processing */···9171 unsigned int minor; /* acm minor number */9272 unsigned char throttle; /* throttled by tty layer */9373 unsigned char clocal; /* termios CLOCAL */9494- unsigned char ready_for_write; /* write urb can be used */9574 unsigned char resubmit_to_unthrottle; /* throtteling has disabled the read urb */9675 unsigned int ctrl_caps; /* control capabilities from the class specific header */9776};
+3
drivers/usb/class/usblp.c
···379379 usblp->writeurb->transfer_buffer_length = 0;380380 usblp->wcomplete = 1; /* we begin writeable */381381 usblp->rcomplete = 0;382382+ usblp->writeurb->status = 0;383383+ usblp->readurb->status = 0;382384383385 if (usblp->bidir) {384386 usblp->readcount = 0;···753751 schedule();754752 } else {755753 set_current_state(TASK_RUNNING);754754+ down(&usblp->sem);756755 break;757756 }758757 down (&usblp->sem);
+3-3
drivers/usb/core/devio.c
···784784 for (i = 0; i < actconfig->desc.bNumInterfaces; ++i) {785785 if (usb_interface_claimed(actconfig->interface[i])) {786786 dev_warn (&ps->dev->dev,787787- "usbfs: interface %d claimed "787787+ "usbfs: interface %d claimed by %s "788788 "while '%s' sets config #%d\n",789789 actconfig->interface[i]790790 ->cur_altsetting791791 ->desc.bInterfaceNumber,792792+ actconfig->interface[i]793793+ ->dev.driver->name,792794 current->comm, u);793793-#if 0 /* FIXME: enable in 2.6.10 or so */794795 status = -EBUSY;795796 break;796796-#endif797797 }798798 }799799 }
+175-114
drivers/usb/core/hcd.c
···519519/*-------------------------------------------------------------------------*/520520521521/*522522- * Root Hub interrupt transfers are synthesized with a timer.523523- * Completions are called in_interrupt() but not in_irq().522522+ * Root Hub interrupt transfers are polled using a timer if the523523+ * driver requests it; otherwise the driver is responsible for524524+ * calling usb_hcd_poll_rh_status() when an event occurs.524525 *525525- * Note: some root hubs (including common UHCI based designs) can't526526- * correctly issue port change IRQs. They're the ones that _need_ a527527- * timer; most other root hubs don't. Some systems could save a528528- * lot of battery power by eliminating these root hub timer IRQs.526526+ * Completions are called in_interrupt(), but they may or may not527527+ * be in_irq().529528 */530530-531531-static void rh_report_status (unsigned long ptr);532532-533533-static int rh_status_urb (struct usb_hcd *hcd, struct urb *urb) 534534-{535535- int len = 1 + (urb->dev->maxchild / 8);536536-537537- /* rh_timer protected by hcd_data_lock */538538- if (hcd->rh_timer.data || urb->transfer_buffer_length < len) {539539- dev_dbg (hcd->self.controller,540540- "not queuing rh status urb, stat %d\n",541541- urb->status);542542- return -EINVAL;543543- }544544-545545- init_timer (&hcd->rh_timer);546546- hcd->rh_timer.function = rh_report_status;547547- hcd->rh_timer.data = (unsigned long) urb;548548- /* USB 2.0 spec says 256msec; this is close enough */549549- hcd->rh_timer.expires = jiffies + HZ/4;550550- add_timer (&hcd->rh_timer);551551- urb->hcpriv = hcd; /* nonzero to indicate it's queued */552552- return 0;553553-}554554-555555-/* timer callback */556556-557557-static void rh_report_status (unsigned long ptr)529529+void usb_hcd_poll_rh_status(struct usb_hcd *hcd)558530{559531 struct urb *urb;560560- struct usb_hcd *hcd;561561- int length = 0;532532+ int length;562533 unsigned long flags;534534+ char buffer[4]; /* Any root hubs with > 31 ports? */563535564564- urb = (struct urb *) ptr;565565- local_irq_save (flags);566566- spin_lock (&urb->lock);567567-568568- /* do nothing if the urb's been unlinked */569569- if (!urb->dev570570- || urb->status != -EINPROGRESS571571- || (hcd = urb->dev->bus->hcpriv) == NULL) {572572- spin_unlock (&urb->lock);573573- local_irq_restore (flags);536536+ if (!hcd->uses_new_polling && !hcd->status_urb)574537 return;575575- }576538577577- /* complete the status urb, or retrigger the timer */578578- spin_lock (&hcd_data_lock);579579- if (urb->dev->state == USB_STATE_CONFIGURED) {580580- length = hcd->driver->hub_status_data (581581- hcd, urb->transfer_buffer);582582- if (length > 0) {583583- hcd->rh_timer.data = 0;584584- urb->actual_length = length;585585- urb->status = 0;586586- urb->hcpriv = NULL;539539+ length = hcd->driver->hub_status_data(hcd, buffer);540540+ if (length > 0) {541541+542542+ /* try to complete the status urb */543543+ local_irq_save (flags);544544+ spin_lock(&hcd_root_hub_lock);545545+ urb = hcd->status_urb;546546+ if (urb) {547547+ spin_lock(&urb->lock);548548+ if (urb->status == -EINPROGRESS) {549549+ hcd->poll_pending = 0;550550+ hcd->status_urb = NULL;551551+ urb->status = 0;552552+ urb->hcpriv = NULL;553553+ urb->actual_length = length;554554+ memcpy(urb->transfer_buffer, buffer, length);555555+ } else /* urb has been unlinked */556556+ length = 0;557557+ spin_unlock(&urb->lock);587558 } else588588- mod_timer (&hcd->rh_timer, jiffies + HZ/4);589589- }590590- spin_unlock (&hcd_data_lock);591591- spin_unlock (&urb->lock);559559+ length = 0;560560+ spin_unlock(&hcd_root_hub_lock);592561593593- /* local irqs are always blocked in completions */594594- if (length > 0)595595- usb_hcd_giveback_urb (hcd, urb, NULL);596596- local_irq_restore (flags);562562+ /* local irqs are always blocked in completions */563563+ if (length > 0)564564+ usb_hcd_giveback_urb (hcd, urb, NULL);565565+ else566566+ hcd->poll_pending = 1;567567+ local_irq_restore (flags);568568+ }569569+570570+ /* The USB 2.0 spec says 256 ms. This is close enough and won't571571+ * exceed that limit if HZ is 100. */572572+ if (hcd->uses_new_polling ? hcd->poll_rh :573573+ (length == 0 && hcd->status_urb != NULL))574574+ mod_timer (&hcd->rh_timer, jiffies + msecs_to_jiffies(250));575575+}576576+EXPORT_SYMBOL_GPL(usb_hcd_poll_rh_status);577577+578578+/* timer callback */579579+static void rh_timer_func (unsigned long _hcd)580580+{581581+ usb_hcd_poll_rh_status((struct usb_hcd *) _hcd);597582}598583599584/*-------------------------------------------------------------------------*/585585+586586+static int rh_queue_status (struct usb_hcd *hcd, struct urb *urb)587587+{588588+ int retval;589589+ unsigned long flags;590590+ int len = 1 + (urb->dev->maxchild / 8);591591+592592+ spin_lock_irqsave (&hcd_root_hub_lock, flags);593593+ if (urb->status != -EINPROGRESS) /* already unlinked */594594+ retval = urb->status;595595+ else if (hcd->status_urb || urb->transfer_buffer_length < len) {596596+ dev_dbg (hcd->self.controller, "not queuing rh status urb\n");597597+ retval = -EINVAL;598598+ } else {599599+ hcd->status_urb = urb;600600+ urb->hcpriv = hcd; /* indicate it's queued */601601+602602+ if (!hcd->uses_new_polling)603603+ mod_timer (&hcd->rh_timer, jiffies +604604+ msecs_to_jiffies(250));605605+606606+ /* If a status change has already occurred, report it ASAP */607607+ else if (hcd->poll_pending)608608+ mod_timer (&hcd->rh_timer, jiffies);609609+ retval = 0;610610+ }611611+ spin_unlock_irqrestore (&hcd_root_hub_lock, flags);612612+ return retval;613613+}600614601615static int rh_urb_enqueue (struct usb_hcd *hcd, struct urb *urb)602616{603603- if (usb_pipeint (urb->pipe)) {604604- int retval;605605- unsigned long flags;606606-607607- spin_lock_irqsave (&hcd_data_lock, flags);608608- retval = rh_status_urb (hcd, urb);609609- spin_unlock_irqrestore (&hcd_data_lock, flags);610610- return retval;611611- }617617+ if (usb_pipeint (urb->pipe))618618+ return rh_queue_status (hcd, urb);612619 if (usb_pipecontrol (urb->pipe))613620 return rh_call_control (hcd, urb);614614- else615615- return -EINVAL;621621+ return -EINVAL;616622}617623618624/*-------------------------------------------------------------------------*/619625626626+/* Asynchronous unlinks of root-hub control URBs are legal, but they627627+ * don't do anything. Status URB unlinks must be made in process context628628+ * with interrupts enabled.629629+ */620630static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)621631{622622- unsigned long flags;632632+ if (usb_pipeendpoint(urb->pipe) == 0) { /* Control URB */633633+ if (in_interrupt())634634+ return 0; /* nothing to do */623635624624- /* note: always a synchronous unlink */625625- if ((unsigned long) urb == hcd->rh_timer.data) {626626- del_timer_sync (&hcd->rh_timer);627627- hcd->rh_timer.data = 0;628628-629629- local_irq_save (flags);630630- urb->hcpriv = NULL;631631- usb_hcd_giveback_urb (hcd, urb, NULL);632632- local_irq_restore (flags);633633-634634- } else if (usb_pipeendpoint(urb->pipe) == 0) {635636 spin_lock_irq(&urb->lock); /* from usb_kill_urb */636637 ++urb->reject;637638 spin_unlock_irq(&urb->lock);···643642 spin_lock_irq(&urb->lock);644643 --urb->reject;645644 spin_unlock_irq(&urb->lock);646646- } else647647- return -EINVAL;645645+646646+ } else { /* Status URB */647647+ if (!hcd->uses_new_polling)648648+ del_timer_sync (&hcd->rh_timer);649649+ local_irq_disable ();650650+ spin_lock (&hcd_root_hub_lock);651651+ if (urb == hcd->status_urb) {652652+ hcd->status_urb = NULL;653653+ urb->hcpriv = NULL;654654+ } else655655+ urb = NULL; /* wasn't fully queued */656656+ spin_unlock (&hcd_root_hub_lock);657657+ if (urb)658658+ usb_hcd_giveback_urb (hcd, urb, NULL);659659+ local_irq_enable ();660660+ }648661649662 return 0;650663}···832817}833818834819/**835835- * usb_hcd_register_root_hub - called by HCD to register its root hub 820820+ * register_root_hub - called by usb_add_hcd() to register a root hub836821 * @usb_dev: the usb root hub device to be registered.837822 * @hcd: host controller for this root hub838823 *839839- * The USB host controller calls this function to register the root hub840840- * properly with the USB subsystem. It sets up the device properly in841841- * the device tree and stores the root_hub pointer in the bus structure,842842- * then calls usb_new_device() to register the usb device. It also843843- * assigns the root hub's USB address (always 1).824824+ * This function registers the root hub with the USB subsystem. It sets up825825+ * the device properly in the device tree and stores the root_hub pointer826826+ * in the bus structure, then calls usb_new_device() to register the usb827827+ * device. It also assigns the root hub's USB address (always 1).844828 */845845-int usb_hcd_register_root_hub (struct usb_device *usb_dev, struct usb_hcd *hcd)829829+static int register_root_hub (struct usb_device *usb_dev,830830+ struct usb_hcd *hcd)846831{847832 struct device *parent_dev = hcd->self.controller;848833 const int devnum = 1;849834 int retval;850850-851851- /* hcd->driver->start() reported can_wakeup, probably with852852- * assistance from board's boot firmware.853853- * NOTE: normal devices won't enable wakeup by default.854854- */855855- if (hcd->can_wakeup)856856- dev_dbg (parent_dev, "supports USB remote wakeup\n");857857- hcd->remote_wakeup = hcd->can_wakeup;858835859836 usb_dev->devnum = devnum;860837 usb_dev->bus->devnum_next = devnum + 1;···890883891884 return retval;892885}893893-EXPORT_SYMBOL_GPL(usb_hcd_register_root_hub);886886+887887+void usb_enable_root_hub_irq (struct usb_bus *bus)888888+{889889+ struct usb_hcd *hcd;890890+891891+ hcd = container_of (bus, struct usb_hcd, self);892892+ if (hcd->driver->hub_irq_enable && !hcd->poll_rh &&893893+ hcd->state != HC_STATE_HALT)894894+ hcd->driver->hub_irq_enable (hcd);895895+}894896895897896898/*-------------------------------------------------------------------------*/···1364134813651349 hcd = udev->bus->hcpriv;1366135013671367- WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT);13511351+ WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT &&13521352+ udev->state != USB_STATE_NOTATTACHED);1368135313691354 local_irq_disable ();13701355···1629161216301613 spin_lock_irqsave (&hcd_root_hub_lock, flags);16311614 if (hcd->rh_registered) {16151615+ hcd->poll_rh = 0;16161616+ del_timer(&hcd->rh_timer);1632161716331618 /* make khubd clean up old urbs and devices */16341619 usb_set_device_state (hcd->self.root_hub,···16841665 hcd->self.bus_name = bus_name;1685166616861667 init_timer(&hcd->rh_timer);16681668+ hcd->rh_timer.function = rh_timer_func;16691669+ hcd->rh_timer.data = (unsigned long) hcd;1687167016881671 hcd->driver = driver;16891672 hcd->product_desc = (driver->product_desc) ? driver->product_desc :···17151694int usb_add_hcd(struct usb_hcd *hcd,17161695 unsigned int irqnum, unsigned long irqflags)17171696{17181718- int retval;16971697+ int retval;16981698+ struct usb_device *rhdev;1719169917201700 dev_info(hcd->self.controller, "%s\n", hcd->product_desc);17211701···17321710 }1733171117341712 if ((retval = usb_register_bus(&hcd->self)) < 0)17351735- goto err1;17131713+ goto err_register_bus;1736171417371715 if (hcd->driver->irq) {17381716 char buf[8], *bufp = buf;···17491727 hcd->irq_descr, hcd)) != 0) {17501728 dev_err(hcd->self.controller,17511729 "request interrupt %s failed\n", bufp);17521752- goto err2;17301730+ goto err_request_irq;17531731 }17541732 hcd->irq = irqnum;17551733 dev_info(hcd->self.controller, "irq %s, %s 0x%08llx\n", bufp,···17651743 (unsigned long long)hcd->rsrc_start);17661744 }1767174517461746+ /* Allocate the root hub before calling hcd->driver->start(),17471747+ * but don't register it until afterward so that the hardware17481748+ * is running.17491749+ */17501750+ if ((rhdev = usb_alloc_dev(NULL, &hcd->self, 0)) == NULL) {17511751+ dev_err(hcd->self.controller, "unable to allocate root hub\n");17521752+ retval = -ENOMEM;17531753+ goto err_allocate_root_hub;17541754+ }17551755+ rhdev->speed = (hcd->driver->flags & HCD_USB2) ? USB_SPEED_HIGH :17561756+ USB_SPEED_FULL;17571757+17581758+ /* Although in principle hcd->driver->start() might need to use rhdev,17591759+ * none of the current drivers do.17601760+ */17681761 if ((retval = hcd->driver->start(hcd)) < 0) {17691762 dev_err(hcd->self.controller, "startup error %d\n", retval);17701770- goto err3;17631763+ goto err_hcd_driver_start;17711764 }1772176517661766+ /* hcd->driver->start() reported can_wakeup, probably with17671767+ * assistance from board's boot firmware.17681768+ * NOTE: normal devices won't enable wakeup by default.17691769+ */17701770+ if (hcd->can_wakeup)17711771+ dev_dbg(hcd->self.controller, "supports USB remote wakeup\n");17721772+ hcd->remote_wakeup = hcd->can_wakeup;17731773+17741774+ if ((retval = register_root_hub(rhdev, hcd)) != 0)17751775+ goto err_register_root_hub;17761776+17771777+ if (hcd->uses_new_polling && hcd->poll_rh)17781778+ usb_hcd_poll_rh_status(hcd);17731779 return retval;1774178017751775- err3:17811781+ err_register_root_hub:17821782+ hcd->driver->stop(hcd);17831783+17841784+ err_hcd_driver_start:17851785+ usb_put_dev(rhdev);17861786+17871787+ err_allocate_root_hub:17761788 if (hcd->irq >= 0)17771789 free_irq(irqnum, hcd);17781778- err2:17901790+17911791+ err_request_irq:17791792 usb_deregister_bus(&hcd->self);17801780- err1:17931793+17941794+ err_register_bus:17811795 hcd_buffer_destroy(hcd);17821796 return retval;17831797} ···18391781 hcd->rh_registered = 0;18401782 spin_unlock_irq (&hcd_root_hub_lock);18411783 usb_disconnect(&hcd->self.root_hub);17841784+17851785+ hcd->poll_rh = 0;17861786+ del_timer_sync(&hcd->rh_timer);1842178718431788 hcd->driver->stop(hcd);18441789 hcd->state = HC_STATE_HALT;
+15-4
drivers/usb/core/hcd.h
···6565 const char *product_desc; /* product/vendor string */6666 char irq_descr[24]; /* driver + bus # */67676868- struct timer_list rh_timer; /* drives root hub */6868+ struct timer_list rh_timer; /* drives root-hub polling */6969+ struct urb *status_urb; /* the current status urb */69707071 /*7172 * hardware info/state···7776 unsigned remote_wakeup:1;/* sw should use wakeup? */7877 unsigned rh_registered:1;/* is root hub registered? */79787979+ /* The next flag is a stopgap, to be removed when all the HCDs8080+ * support the new root-hub polling mechanism. */8181+ unsigned uses_new_polling:1;8282+ unsigned poll_rh:1; /* poll for rh status? */8383+ unsigned poll_pending:1; /* status has changed? */8484+8085 int irq; /* irq allocated */8186 void __iomem *regs; /* device memory/io */8287 u64 rsrc_start; /* memory/io resource start */8388 u64 rsrc_len; /* memory/io resource length */8989+ unsigned power_budget; /* in mA, 0 = no limit */84908591#define HCD_BUFFER_POOLS 48692 struct dma_pool *pool [HCD_BUFFER_POOLS];···215207 int (*hub_suspend)(struct usb_hcd *);216208 int (*hub_resume)(struct usb_hcd *);217209 int (*start_port_reset)(struct usb_hcd *, unsigned port_num);210210+ void (*hub_irq_enable)(struct usb_hcd *);211211+ /* Needed only if port-change IRQs are level-triggered */218212};219213220214extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs);···253243254244/* generic bus glue, needed for host controllers that don't use PCI */255245extern irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs *r);246246+256247extern void usb_hc_died (struct usb_hcd *hcd);248248+extern void usb_hcd_poll_rh_status(struct usb_hcd *hcd);257249258250/* -------------------------------------------------------------------------- */259251···353341354342extern struct usb_bus *usb_alloc_bus (struct usb_operations *);355343356356-extern int usb_hcd_register_root_hub (struct usb_device *usb_dev,357357- struct usb_hcd *hcd);358358-359344extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd);360345361346extern void usb_set_device_state(struct usb_device *udev,···368359369360extern struct usb_bus *usb_bus_get (struct usb_bus *bus);370361extern void usb_bus_put (struct usb_bus *bus);362362+363363+extern void usb_enable_root_hub_irq (struct usb_bus *bus);371364372365extern int usb_find_interface_driver (struct usb_device *dev,373366 struct usb_interface *interface);
+15-4
drivers/usb/core/hub.c
···643643 message = "can't get hub status";644644 goto fail;645645 }646646- cpu_to_le16s(&hubstatus);647647- if ((hubstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0) {646646+ le16_to_cpus(&hubstatus);647647+ if (hdev == hdev->bus->root_hub) {648648+ struct usb_hcd *hcd =649649+ container_of(hdev->bus, struct usb_hcd, self);650650+651651+ hub->power_budget = min(500u, hcd->power_budget) / 2;652652+ } else if ((hubstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0) {648653 dev_dbg(hub_dev, "hub controller current requirement: %dmA\n",649654 hub->descriptor->bHubContrCurrent);650655 hub->power_budget = (501 - hub->descriptor->bHubContrCurrent)651656 / 2;657657+ }658658+ if (hub->power_budget)652659 dev_dbg(hub_dev, "%dmA bus power budget for children\n",653660 hub->power_budget * 2);654654- }655661656662657663 ret = hub_hub_status(hub, &hubstatus, &hubchange);···17331727 struct usb_driver *driver;1734172817351729 intf = udev->actconfig->interface[i];17361736- if (intf->dev.power.power_state == PMSG_SUSPEND)17301730+ if (intf->dev.power.power_state == PMSG_ON)17371731 continue;17381732 if (!intf->dev.driver) {17391733 /* FIXME maybe force to alt 0 */···27922786 }2793278727942788 hub->activating = 0;27892789+27902790+ /* If this is a root hub, tell the HCD it's okay to27912791+ * re-enable port-change interrupts now. */27922792+ if (!hdev->parent)27932793+ usb_enable_root_hub_irq(hdev->bus);2795279427962795loop:27972796 usb_unlock_device(hdev);
···5353 driver on a new board. Enable these files by choosing "Y"5454 here. If in doubt, or to conserve kernel memory, say "N".55555656+config USB_GADGET_SELECTED5757+ boolean5858+5659#5760# USB Peripheral Controller Support5861#···8885 tristate8986 depends on USB_GADGET_NET22809087 default USB_GADGET8888+ select USB_GADGET_SELECTED91899290config USB_GADGET_PXA2XX9391 boolean "PXA 25x or IXP 4xx"···109105 tristate110106 depends on USB_GADGET_PXA2XX111107 default USB_GADGET108108+ select USB_GADGET_SELECTED112109113110# if there's only one gadget driver, using only two bulk endpoints,114111# don't waste memory for the other endpoints···139134 tristate140135 depends on USB_GADGET_GOKU141136 default USB_GADGET137137+ select USB_GADGET_SELECTED142138143139144140config USB_GADGET_LH7A40X···152146 tristate153147 depends on USB_GADGET_LH7A40X154148 default USB_GADGET149149+ select USB_GADGET_SELECTED155150156151157152config USB_GADGET_OMAP···174167 tristate175168 depends on USB_GADGET_OMAP176169 default USB_GADGET170170+ select USB_GADGET_SELECTED177171178172config USB_OTG179173 boolean "OTG Support"···215207 tristate216208 depends on USB_GADGET_DUMMY_HCD217209 default USB_GADGET210210+ select USB_GADGET_SELECTED218211219212# NOTE: Please keep dummy_hcd LAST so that "real hardware" appears220213# first and will be selected by default.···235226#236227choice237228 tristate "USB Gadget Drivers"238238- depends on USB_GADGET229229+ depends on USB_GADGET && USB_GADGET_SELECTED239230 default USB_ETH240231 help241232 A Linux "Gadget Driver" talks to the USB Peripheral Controller
+510-245
drivers/usb/gadget/dummy_hcd.c
···656566666767#define DRIVER_DESC "USB Host+Gadget Emulator"6868-#define DRIVER_VERSION "17 Dec 2004"6868+#define DRIVER_VERSION "02 May 2005"69697070static const char driver_name [] = "dummy_hcd";7171static const char driver_desc [] = "USB Host+Gadget Emulator";···141141};142142#define DUMMY_ENDPOINTS (sizeof(ep_name)/sizeof(char *))143143144144+/*-------------------------------------------------------------------------*/145145+144146#define FIFO_SIZE 64145147146148struct urbp {147149 struct urb *urb;148150 struct list_head urbp_list;151151+};152152+153153+154154+enum dummy_rh_state {155155+ DUMMY_RH_RESET,156156+ DUMMY_RH_SUSPENDED,157157+ DUMMY_RH_RUNNING149158};150159151160struct dummy {···170161 struct dummy_request fifo_req;171162 u8 fifo_buf [FIFO_SIZE];172163 u16 devstatus;164164+ unsigned udc_suspended:1;165165+ unsigned pullup:1;166166+ unsigned active:1;167167+ unsigned old_active:1;173168174169 /*175170 * MASTER/HOST side support176171 */172172+ enum dummy_rh_state rh_state;177173 struct timer_list timer;178174 u32 port_status;175175+ u32 old_status;179176 unsigned resuming:1;180177 unsigned long re_timeout;181178···204189 return dummy_to_hcd(dum)->self.controller;205190}206191192192+static inline struct device *udc_dev (struct dummy *dum)193193+{194194+ return dum->gadget.dev.parent;195195+}196196+207197static inline struct dummy *ep_to_dummy (struct dummy_ep *ep)208198{209199 return container_of (ep->gadget, struct dummy, gadget);···228208229209/*-------------------------------------------------------------------------*/230210231231-/*232232- * This "hardware" may look a bit odd in diagnostics since it's got both233233- * host and device sides; and it binds different drivers to each side.234234- */235235-static struct platform_device the_pdev;211211+/* SLAVE/GADGET SIDE UTILITY ROUTINES */236212237237-static struct device_driver dummy_driver = {238238- .name = (char *) driver_name,239239- .bus = &platform_bus_type,240240-};213213+/* called with spinlock held */214214+static void nuke (struct dummy *dum, struct dummy_ep *ep)215215+{216216+ while (!list_empty (&ep->queue)) {217217+ struct dummy_request *req;218218+219219+ req = list_entry (ep->queue.next, struct dummy_request, queue);220220+ list_del_init (&req->queue);221221+ req->req.status = -ESHUTDOWN;222222+223223+ spin_unlock (&dum->lock);224224+ req->req.complete (&ep->ep, &req->req);225225+ spin_lock (&dum->lock);226226+ }227227+}228228+229229+/* caller must hold lock */230230+static void231231+stop_activity (struct dummy *dum)232232+{233233+ struct dummy_ep *ep;234234+235235+ /* prevent any more requests */236236+ dum->address = 0;237237+238238+ /* The timer is left running so that outstanding URBs can fail */239239+240240+ /* nuke any pending requests first, so driver i/o is quiesced */241241+ list_for_each_entry (ep, &dum->gadget.ep_list, ep.ep_list)242242+ nuke (dum, ep);243243+244244+ /* driver now does any non-usb quiescing necessary */245245+}246246+247247+/* caller must hold lock */248248+static void249249+set_link_state (struct dummy *dum)250250+{251251+ dum->active = 0;252252+ if ((dum->port_status & USB_PORT_STAT_POWER) == 0)253253+ dum->port_status = 0;254254+255255+ /* UDC suspend must cause a disconnect */256256+ else if (!dum->pullup || dum->udc_suspended) {257257+ dum->port_status &= ~(USB_PORT_STAT_CONNECTION |258258+ USB_PORT_STAT_ENABLE |259259+ USB_PORT_STAT_LOW_SPEED |260260+ USB_PORT_STAT_HIGH_SPEED |261261+ USB_PORT_STAT_SUSPEND);262262+ if ((dum->old_status & USB_PORT_STAT_CONNECTION) != 0)263263+ dum->port_status |= (USB_PORT_STAT_C_CONNECTION << 16);264264+ } else {265265+ dum->port_status |= USB_PORT_STAT_CONNECTION;266266+ if ((dum->old_status & USB_PORT_STAT_CONNECTION) == 0)267267+ dum->port_status |= (USB_PORT_STAT_C_CONNECTION << 16);268268+ if ((dum->port_status & USB_PORT_STAT_ENABLE) == 0)269269+ dum->port_status &= ~USB_PORT_STAT_SUSPEND;270270+ else if ((dum->port_status & USB_PORT_STAT_SUSPEND) == 0 &&271271+ dum->rh_state != DUMMY_RH_SUSPENDED)272272+ dum->active = 1;273273+ }274274+275275+ if ((dum->port_status & USB_PORT_STAT_ENABLE) == 0 || dum->active)276276+ dum->resuming = 0;277277+278278+ if ((dum->port_status & USB_PORT_STAT_CONNECTION) == 0 ||279279+ (dum->port_status & USB_PORT_STAT_RESET) != 0) {280280+ if ((dum->old_status & USB_PORT_STAT_CONNECTION) != 0 &&281281+ (dum->old_status & USB_PORT_STAT_RESET) == 0 &&282282+ dum->driver) {283283+ stop_activity (dum);284284+ spin_unlock (&dum->lock);285285+ dum->driver->disconnect (&dum->gadget);286286+ spin_lock (&dum->lock);287287+ }288288+ } else if (dum->active != dum->old_active) {289289+ if (dum->old_active && dum->driver->suspend) {290290+ spin_unlock (&dum->lock);291291+ dum->driver->suspend (&dum->gadget);292292+ spin_lock (&dum->lock);293293+ } else if (!dum->old_active && dum->driver->resume) {294294+ spin_unlock (&dum->lock);295295+ dum->driver->resume (&dum->gadget);296296+ spin_lock (&dum->lock);297297+ }298298+ }299299+300300+ dum->old_status = dum->port_status;301301+ dum->old_active = dum->active;302302+}241303242304/*-------------------------------------------------------------------------*/243305···426324 _ep->maxpacket = max;427325 ep->desc = desc;428326429429- dev_dbg (dummy_dev(dum), "enabled %s (ep%d%s-%s) maxpacket %d\n",327327+ dev_dbg (udc_dev(dum), "enabled %s (ep%d%s-%s) maxpacket %d\n",430328 _ep->name,431329 desc->bEndpointAddress & 0x0f,432330 (desc->bEndpointAddress & USB_DIR_IN) ? "in" : "out",···447345 return retval;448346}449347450450-/* called with spinlock held */451451-static void nuke (struct dummy *dum, struct dummy_ep *ep)452452-{453453- while (!list_empty (&ep->queue)) {454454- struct dummy_request *req;455455-456456- req = list_entry (ep->queue.next, struct dummy_request, queue);457457- list_del_init (&req->queue);458458- req->req.status = -ESHUTDOWN;459459-460460- spin_unlock (&dum->lock);461461- req->req.complete (&ep->ep, &req->req);462462- spin_lock (&dum->lock);463463- }464464-}465465-466348static int dummy_disable (struct usb_ep *_ep)467349{468350 struct dummy_ep *ep;···465379 nuke (dum, ep);466380 spin_unlock_irqrestore (&dum->lock, flags);467381468468- dev_dbg (dummy_dev(dum), "disabled %s\n", _ep->name);382382+ dev_dbg (udc_dev(dum), "disabled %s\n", _ep->name);469383 return retval;470384}471385···560474 return -ESHUTDOWN;561475562476#if 0563563- dev_dbg (dummy_dev(dum), "ep %p queue req %p to %s, len %d buf %p\n",477477+ dev_dbg (udc_dev(dum), "ep %p queue req %p to %s, len %d buf %p\n",564478 ep, _req, _ep->name, _req->length, _req->buf);565479#endif566480···623537 spin_unlock_irqrestore (&dum->lock, flags);624538625539 if (retval == 0) {626626- dev_dbg (dummy_dev(dum),540540+ dev_dbg (udc_dev(dum),627541 "dequeued req %p from %s, len %d buf %p\n",628542 req, _ep->name, _req->length, _req->buf);629543 _req->complete (_ep, _req);···687601 struct dummy *dum;688602689603 dum = gadget_to_dummy (_gadget);690690- if ((dum->devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) == 0691691- || !(dum->port_status & (1 << USB_PORT_FEAT_SUSPEND)))604604+ if (!(dum->devstatus & ( (1 << USB_DEVICE_B_HNP_ENABLE)605605+ | (1 << USB_DEVICE_REMOTE_WAKEUP))))692606 return -EINVAL;607607+ if ((dum->port_status & USB_PORT_STAT_CONNECTION) == 0)608608+ return -ENOLINK;609609+ if ((dum->port_status & USB_PORT_STAT_SUSPEND) == 0 &&610610+ dum->rh_state != DUMMY_RH_SUSPENDED)611611+ return -EIO;612612+613613+ /* FIXME: What if the root hub is suspended but the port isn't? */693614694615 /* hub notices our request, issues downstream resume, etc */695616 dum->resuming = 1;696696- dum->port_status |= (1 << USB_PORT_FEAT_C_SUSPEND);617617+ dum->re_timeout = jiffies + msecs_to_jiffies(20);618618+ mod_timer (&dummy_to_hcd (dum)->rh_timer, dum->re_timeout);697619 return 0;698620}699621···717623 return 0;718624}719625626626+static int dummy_pullup (struct usb_gadget *_gadget, int value)627627+{628628+ struct dummy *dum;629629+ unsigned long flags;630630+631631+ dum = gadget_to_dummy (_gadget);632632+ spin_lock_irqsave (&dum->lock, flags);633633+ dum->pullup = (value != 0);634634+ set_link_state (dum);635635+ spin_unlock_irqrestore (&dum->lock, flags);636636+637637+ usb_hcd_poll_rh_status (dummy_to_hcd (dum));638638+ return 0;639639+}640640+720641static const struct usb_gadget_ops dummy_ops = {721642 .get_frame = dummy_g_get_frame,722643 .wakeup = dummy_wakeup,723644 .set_selfpowered = dummy_set_selfpowered,645645+ .pullup = dummy_pullup,724646};725647726648/*-------------------------------------------------------------------------*/···751641 return 0;752642 return scnprintf (buf, PAGE_SIZE, "%s\n", dum->driver->function);753643}754754-DEVICE_ATTR (function, S_IRUGO, show_function, NULL);644644+static DEVICE_ATTR (function, S_IRUGO, show_function, NULL);755645756646/*-------------------------------------------------------------------------*/757647···768658 * For this emulator, it might be convenient to create a usb slave device769659 * for each driver that registers: just add to a big root hub.770660 */771771-772772-static void773773-dummy_udc_release (struct device *dev)774774-{775775-}776776-777777-static void778778-dummy_pdev_release (struct device *dev)779779-{780780-}781781-782782-static int783783-dummy_register_udc (struct dummy *dum)784784-{785785- int rc;786786-787787- strcpy (dum->gadget.dev.bus_id, "udc");788788- dum->gadget.dev.parent = dummy_dev(dum);789789- dum->gadget.dev.release = dummy_udc_release;790790-791791- rc = device_register (&dum->gadget.dev);792792- if (rc == 0)793793- device_create_file (&dum->gadget.dev, &dev_attr_function);794794- return rc;795795-}796796-797797-static void798798-dummy_unregister_udc (struct dummy *dum)799799-{800800- device_remove_file (&dum->gadget.dev, &dev_attr_function);801801- device_unregister (&dum->gadget.dev);802802-}803661804662int805663usb_gadget_register_driver (struct usb_gadget_driver *driver)···787709 * SLAVE side init ... the layer above hardware, which788710 * can't enumerate without help from the driver we're binding.789711 */790790- dum->gadget.name = gadget_name;791791- dum->gadget.ops = &dummy_ops;792792- dum->gadget.is_dualspeed = 1;793712794713 dum->devstatus = 0;795795- dum->resuming = 0;796714797715 INIT_LIST_HEAD (&dum->gadget.ep_list);798716 for (i = 0; i < DUMMY_ENDPOINTS; i++) {···814740815741 dum->driver = driver;816742 dum->gadget.dev.driver = &driver->driver;817817- dev_dbg (dummy_dev(dum), "binding gadget driver '%s'\n",743743+ dev_dbg (udc_dev(dum), "binding gadget driver '%s'\n",818744 driver->driver.name);819745 if ((retval = driver->bind (&dum->gadget)) != 0) {820746 dum->driver = NULL;···822748 return retval;823749 }824750825825- // FIXME: Check these calls for errors and re-order826751 driver->driver.bus = dum->gadget.dev.parent->bus;827752 driver_register (&driver->driver);828828-829753 device_bind_driver (&dum->gadget.dev);830754831755 /* khubd will enumerate this in a while */832832- dum->port_status |= USB_PORT_STAT_CONNECTION833833- | (1 << USB_PORT_FEAT_C_CONNECTION);756756+ spin_lock_irq (&dum->lock);757757+ dum->pullup = 1;758758+ set_link_state (dum);759759+ spin_unlock_irq (&dum->lock);760760+761761+ usb_hcd_poll_rh_status (dummy_to_hcd (dum));834762 return 0;835763}836764EXPORT_SYMBOL (usb_gadget_register_driver);837837-838838-/* caller must hold lock */839839-static void840840-stop_activity (struct dummy *dum, struct usb_gadget_driver *driver)841841-{842842- struct dummy_ep *ep;843843-844844- /* prevent any more requests */845845- dum->address = 0;846846-847847- /* The timer is left running so that outstanding URBs can fail */848848-849849- /* nuke any pending requests first, so driver i/o is quiesced */850850- list_for_each_entry (ep, &dum->gadget.ep_list, ep.ep_list)851851- nuke (dum, ep);852852-853853- /* driver now does any non-usb quiescing necessary */854854- if (driver) {855855- spin_unlock (&dum->lock);856856- driver->disconnect (&dum->gadget);857857- spin_lock (&dum->lock);858858- }859859-}860765861766int862767usb_gadget_unregister_driver (struct usb_gadget_driver *driver)···848795 if (!driver || driver != dum->driver)849796 return -EINVAL;850797851851- dev_dbg (dummy_dev(dum), "unregister gadget driver '%s'\n",798798+ dev_dbg (udc_dev(dum), "unregister gadget driver '%s'\n",852799 driver->driver.name);853800854801 spin_lock_irqsave (&dum->lock, flags);855855- stop_activity (dum, driver);856856- dum->port_status &= ~(USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE |857857- USB_PORT_STAT_LOW_SPEED | USB_PORT_STAT_HIGH_SPEED);858858- dum->port_status |= (1 << USB_PORT_FEAT_C_CONNECTION);802802+ dum->pullup = 0;803803+ set_link_state (dum);859804 spin_unlock_irqrestore (&dum->lock, flags);860805861806 driver->unbind (&dum->gadget);862807 dum->driver = NULL;863808864809 device_release_driver (&dum->gadget.dev);865865-866810 driver_unregister (&driver->driver);867811812812+ spin_lock_irqsave (&dum->lock, flags);813813+ dum->pullup = 0;814814+ set_link_state (dum);815815+ spin_unlock_irqrestore (&dum->lock, flags);816816+817817+ usb_hcd_poll_rh_status (dummy_to_hcd (dum));868818 return 0;869819}870820EXPORT_SYMBOL (usb_gadget_unregister_driver);871821872822#undef is_enabled873823824824+/* just declare this in any driver that really need it */825825+extern int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode);826826+874827int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode)875828{876829 return -ENOSYS;877830}878831EXPORT_SYMBOL (net2280_set_fifo_mode);832832+833833+834834+/* The gadget structure is stored inside the hcd structure and will be835835+ * released along with it. */836836+static void837837+dummy_gadget_release (struct device *dev)838838+{839839+#if 0 /* usb_bus_put isn't EXPORTed! */840840+ struct dummy *dum = gadget_dev_to_dummy (dev);841841+842842+ usb_bus_put (&dummy_to_hcd (dum)->self);843843+#endif844844+}845845+846846+static int dummy_udc_probe (struct device *dev)847847+{848848+ struct dummy *dum = the_controller;849849+ int rc;850850+851851+ dum->gadget.name = gadget_name;852852+ dum->gadget.ops = &dummy_ops;853853+ dum->gadget.is_dualspeed = 1;854854+855855+ /* maybe claim OTG support, though we won't complete HNP */856856+ dum->gadget.is_otg = (dummy_to_hcd(dum)->self.otg_port != 0);857857+858858+ strcpy (dum->gadget.dev.bus_id, "gadget");859859+ dum->gadget.dev.parent = dev;860860+ dum->gadget.dev.release = dummy_gadget_release;861861+ rc = device_register (&dum->gadget.dev);862862+ if (rc < 0)863863+ return rc;864864+865865+#if 0 /* usb_bus_get isn't EXPORTed! */866866+ usb_bus_get (&dummy_to_hcd (dum)->self);867867+#endif868868+869869+ dev_set_drvdata (dev, dum);870870+ device_create_file (&dum->gadget.dev, &dev_attr_function);871871+ return rc;872872+}873873+874874+static int dummy_udc_remove (struct device *dev)875875+{876876+ struct dummy *dum = dev_get_drvdata (dev);877877+878878+ dev_set_drvdata (dev, NULL);879879+ device_remove_file (&dum->gadget.dev, &dev_attr_function);880880+ device_unregister (&dum->gadget.dev);881881+ return 0;882882+}883883+884884+static int dummy_udc_suspend (struct device *dev, pm_message_t state,885885+ u32 level)886886+{887887+ struct dummy *dum = dev_get_drvdata(dev);888888+889889+ if (level != SUSPEND_DISABLE)890890+ return 0;891891+892892+ dev_dbg (dev, "%s\n", __FUNCTION__);893893+ spin_lock_irq (&dum->lock);894894+ dum->udc_suspended = 1;895895+ set_link_state (dum);896896+ spin_unlock_irq (&dum->lock);897897+898898+ dev->power.power_state = state;899899+ usb_hcd_poll_rh_status (dummy_to_hcd (dum));900900+ return 0;901901+}902902+903903+static int dummy_udc_resume (struct device *dev, u32 level)904904+{905905+ struct dummy *dum = dev_get_drvdata(dev);906906+907907+ if (level != RESUME_ENABLE)908908+ return 0;909909+910910+ dev_dbg (dev, "%s\n", __FUNCTION__);911911+ spin_lock_irq (&dum->lock);912912+ dum->udc_suspended = 0;913913+ set_link_state (dum);914914+ spin_unlock_irq (&dum->lock);915915+916916+ dev->power.power_state = PMSG_ON;917917+ usb_hcd_poll_rh_status (dummy_to_hcd (dum));918918+ return 0;919919+}920920+921921+static struct device_driver dummy_udc_driver = {922922+ .name = (char *) gadget_name,923923+ .bus = &platform_bus_type,924924+ .probe = dummy_udc_probe,925925+ .remove = dummy_udc_remove,926926+ .suspend = dummy_udc_suspend,927927+ .resume = dummy_udc_resume,928928+};879929880930/*-------------------------------------------------------------------------*/881931···10368801037881static int dummy_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)1038882{10391039- /* giveback happens automatically in timer callback */883883+ struct dummy *dum;884884+ unsigned long flags;885885+886886+ /* giveback happens automatically in timer callback,887887+ * so make sure the callback happens */888888+ dum = hcd_to_dummy (hcd);889889+ spin_lock_irqsave (&dum->lock, flags);890890+ if (dum->rh_state != DUMMY_RH_RUNNING && !list_empty(&dum->urbp_list))891891+ mod_timer (&dum->timer, jiffies);892892+ spin_unlock_irqrestore (&dum->lock, flags);1040893 return 0;1041894}1042895···1190102511911026 /* high bandwidth mode */11921027 tmp = le16_to_cpu(ep->desc->wMaxPacketSize);11931193- tmp = le16_to_cpu (tmp);11941028 tmp = (tmp >> 11) & 0x03;11951029 tmp *= 8 /* applies to entire frame */;11961030 limit += limit * tmp;···12871123 if (urb->status != -EINPROGRESS) {12881124 /* likely it was just unlinked */12891125 goto return_urb;12901290- }11261126+ } else if (dum->rh_state != DUMMY_RH_RUNNING)11271127+ continue;12911128 type = usb_pipetype (urb->pipe);1292112912931130 /* used up this frame's non-periodic bandwidth?···13331168 struct usb_ctrlrequest setup;13341169 int value = 1;13351170 struct dummy_ep *ep2;11711171+ unsigned w_index;11721172+ unsigned w_value;1336117313371174 setup = *(struct usb_ctrlrequest*) urb->setup_packet;13381338- le16_to_cpus (&setup.wIndex);13391339- le16_to_cpus (&setup.wValue);13401340- le16_to_cpus (&setup.wLength);13411341- if (setup.wLength != urb->transfer_buffer_length) {11751175+ w_index = le16_to_cpu(setup.wIndex);11761176+ w_value = le16_to_cpu(setup.wValue);11771177+ if (le16_to_cpu(setup.wLength) !=11781178+ urb->transfer_buffer_length) {13421179 maybe_set_status (urb, -EOVERFLOW);13431180 goto return_urb;13441181 }···13491182 list_for_each_entry (req, &ep->queue, queue) {13501183 list_del_init (&req->queue);13511184 req->req.status = -EOVERFLOW;13521352- dev_dbg (dummy_dev(dum), "stale req = %p\n",11851185+ dev_dbg (udc_dev(dum), "stale req = %p\n",13531186 req);1354118713551188 spin_unlock (&dum->lock);···13701203 case USB_REQ_SET_ADDRESS:13711204 if (setup.bRequestType != Dev_Request)13721205 break;13731373- dum->address = setup.wValue;12061206+ dum->address = w_value;13741207 maybe_set_status (urb, 0);13751375- dev_dbg (dummy_dev(dum), "set_address = %d\n",13761376- setup.wValue);12081208+ dev_dbg (udc_dev(dum), "set_address = %d\n",12091209+ w_value);13771210 value = 0;13781211 break;13791212 case USB_REQ_SET_FEATURE:13801213 if (setup.bRequestType == Dev_Request) {13811214 value = 0;13821382- switch (setup.wValue) {12151215+ switch (w_value) {13831216 case USB_DEVICE_REMOTE_WAKEUP:12171217+ break;12181218+ case USB_DEVICE_B_HNP_ENABLE:12191219+ dum->gadget.b_hnp_enable = 1;12201220+ break;12211221+ case USB_DEVICE_A_HNP_SUPPORT:12221222+ dum->gadget.a_hnp_support = 1;12231223+ break;12241224+ case USB_DEVICE_A_ALT_HNP_SUPPORT:12251225+ dum->gadget.a_alt_hnp_support12261226+ = 1;13841227 break;13851228 default:13861229 value = -EOPNOTSUPP;13871230 }13881231 if (value == 0) {13891232 dum->devstatus |=13901390- (1 << setup.wValue);12331233+ (1 << w_value);13911234 maybe_set_status (urb, 0);13921235 }1393123613941237 } else if (setup.bRequestType == Ep_Request) {13951238 // endpoint halt13961396- ep2 = find_endpoint (dum,13971397- setup.wIndex);12391239+ ep2 = find_endpoint (dum, w_index);13981240 if (!ep2) {13991241 value = -EOPNOTSUPP;14001242 break;···14151239 break;14161240 case USB_REQ_CLEAR_FEATURE:14171241 if (setup.bRequestType == Dev_Request) {14181418- switch (setup.wValue) {12421242+ switch (w_value) {14191243 case USB_DEVICE_REMOTE_WAKEUP:14201244 dum->devstatus &= ~(1 <<14211245 USB_DEVICE_REMOTE_WAKEUP);···14281252 }14291253 } else if (setup.bRequestType == Ep_Request) {14301254 // endpoint halt14311431- ep2 = find_endpoint (dum,14321432- setup.wIndex);12551255+ ep2 = find_endpoint (dum, w_index);14331256 if (!ep2) {14341257 value = -EOPNOTSUPP;14351258 break;···14541279 if (urb->transfer_buffer_length > 0) {14551280 if (setup.bRequestType ==14561281 Ep_InRequest) {14571457- ep2 = find_endpoint (dum, setup.wIndex);12821282+ ep2 = find_endpoint (dum, w_index);14581283 if (!ep2) {14591284 value = -EOPNOTSUPP;14601285 break;···1496132114971322 if (value < 0) {14981323 if (value != -EOPNOTSUPP)14991499- dev_dbg (dummy_dev(dum),13241324+ dev_dbg (udc_dev(dum),15001325 "setup --> %d\n",15011326 value);15021327 maybe_set_status (urb, -EPIPE);···15521377 goto restart;15531378 }1554137915551555- /* want a 1 msec delay here */15561556- if (!list_empty (&dum->urbp_list))15571557- mod_timer (&dum->timer, jiffies + msecs_to_jiffies(1));15581558- else {13801380+ if (list_empty (&dum->urbp_list)) {15591381 usb_put_dev (dum->udev);15601382 dum->udev = NULL;13831383+ } else if (dum->rh_state == DUMMY_RH_RUNNING) {13841384+ /* want a 1 msec delay here */13851385+ mod_timer (&dum->timer, jiffies + msecs_to_jiffies(1));15611386 }1562138715631388 spin_unlock_irqrestore (&dum->lock, flags);···15661391/*-------------------------------------------------------------------------*/1567139215681393#define PORT_C_MASK \15691569- ((1 << USB_PORT_FEAT_C_CONNECTION) \15701570- | (1 << USB_PORT_FEAT_C_ENABLE) \15711571- | (1 << USB_PORT_FEAT_C_SUSPEND) \15721572- | (1 << USB_PORT_FEAT_C_OVER_CURRENT) \15731573- | (1 << USB_PORT_FEAT_C_RESET))13941394+ ((USB_PORT_STAT_C_CONNECTION \13951395+ | USB_PORT_STAT_C_ENABLE \13961396+ | USB_PORT_STAT_C_SUSPEND \13971397+ | USB_PORT_STAT_C_OVERCURRENT \13981398+ | USB_PORT_STAT_C_RESET) << 16)1574139915751400static int dummy_hub_status (struct usb_hcd *hcd, char *buf)15761401{15771402 struct dummy *dum;15781403 unsigned long flags;15791579- int retval;14041404+ int retval = 0;1580140515811406 dum = hcd_to_dummy (hcd);1582140715831408 spin_lock_irqsave (&dum->lock, flags);15841584- if (!(dum->port_status & PORT_C_MASK))15851585- retval = 0;15861586- else {14091409+ if (hcd->state != HC_STATE_RUNNING)14101410+ goto done;14111411+14121412+ if (dum->resuming && time_after_eq (jiffies, dum->re_timeout)) {14131413+ dum->port_status |= (USB_PORT_STAT_C_SUSPEND << 16);14141414+ dum->port_status &= ~USB_PORT_STAT_SUSPEND;14151415+ set_link_state (dum);14161416+ }14171417+14181418+ if ((dum->port_status & PORT_C_MASK) != 0) {15871419 *buf = (1 << 1);15881420 dev_dbg (dummy_dev(dum), "port status 0x%08x has changes\n",15891589- dum->port_status);14211421+ dum->port_status);15901422 retval = 1;14231423+ if (dum->rh_state == DUMMY_RH_SUSPENDED)14241424+ usb_hcd_resume_root_hub (hcd);15911425 }14261426+done:15921427 spin_unlock_irqrestore (&dum->lock, flags);15931428 return retval;15941429}···16091424 memset (desc, 0, sizeof *desc);16101425 desc->bDescriptorType = 0x29;16111426 desc->bDescLength = 9;16121612- desc->wHubCharacteristics = __constant_cpu_to_le16 (0x0001);14271427+ desc->wHubCharacteristics = (__force __u16)14281428+ (__constant_cpu_to_le16 (0x0001));16131429 desc->bNbrPorts = 1;16141430 desc->bitmap [0] = 0xff;16151431 desc->bitmap [1] = 0xff;···16281442 int retval = 0;16291443 unsigned long flags;1630144414451445+ if (hcd->state != HC_STATE_RUNNING)14461446+ return -ETIMEDOUT;14471447+16311448 dum = hcd_to_dummy (hcd);16321449 spin_lock_irqsave (&dum->lock, flags);16331450 switch (typeReq) {···16391450 case ClearPortFeature:16401451 switch (wValue) {16411452 case USB_PORT_FEAT_SUSPEND:16421642- if (dum->port_status & (1 << USB_PORT_FEAT_SUSPEND)) {14531453+ if (dum->port_status & USB_PORT_STAT_SUSPEND) {16431454 /* 20msec resume signaling */16441455 dum->resuming = 1;16451456 dum->re_timeout = jiffies +16461646- msecs_to_jiffies(20);14571457+ msecs_to_jiffies(20);16471458 }16481459 break;16491460 case USB_PORT_FEAT_POWER:16501650- dum->port_status = 0;16511651- dum->resuming = 0;16521652- stop_activity(dum, dum->driver);16531653- break;14611461+ if (dum->port_status & USB_PORT_STAT_POWER)14621462+ dev_dbg (dummy_dev(dum), "power-off\n");14631463+ /* FALLS THROUGH */16541464 default:16551465 dum->port_status &= ~(1 << wValue);14661466+ set_link_state (dum);16561467 }16571468 break;16581469 case GetHubDescriptor:16591470 hub_descriptor ((struct usb_hub_descriptor *) buf);16601471 break;16611472 case GetHubStatus:16621662- *(u32 *) buf = __constant_cpu_to_le32 (0);14731473+ *(__le32 *) buf = __constant_cpu_to_le32 (0);16631474 break;16641475 case GetPortStatus:16651476 if (wIndex != 1)···16681479 /* whoever resets or resumes must GetPortStatus to16691480 * complete it!!16701481 */16711671- if (dum->resuming && time_after (jiffies, dum->re_timeout)) {16721672- dum->port_status |= (1 << USB_PORT_FEAT_C_SUSPEND);16731673- dum->port_status &= ~(1 << USB_PORT_FEAT_SUSPEND);16741674- dum->resuming = 0;16751675- dum->re_timeout = 0;16761676- if (dum->driver && dum->driver->resume) {16771677- spin_unlock (&dum->lock);16781678- dum->driver->resume (&dum->gadget);16791679- spin_lock (&dum->lock);16801680- }14821482+ if (dum->resuming &&14831483+ time_after_eq (jiffies, dum->re_timeout)) {14841484+ dum->port_status |= (USB_PORT_STAT_C_SUSPEND << 16);14851485+ dum->port_status &= ~USB_PORT_STAT_SUSPEND;16811486 }16821682- if ((dum->port_status & (1 << USB_PORT_FEAT_RESET)) != 016831683- && time_after (jiffies, dum->re_timeout)) {16841684- dum->port_status |= (1 << USB_PORT_FEAT_C_RESET);16851685- dum->port_status &= ~(1 << USB_PORT_FEAT_RESET);16861686- dum->re_timeout = 0;16871687- if (dum->driver) {14871487+ if ((dum->port_status & USB_PORT_STAT_RESET) != 0 &&14881488+ time_after_eq (jiffies, dum->re_timeout)) {14891489+ dum->port_status |= (USB_PORT_STAT_C_RESET << 16);14901490+ dum->port_status &= ~USB_PORT_STAT_RESET;14911491+ if (dum->pullup) {16881492 dum->port_status |= USB_PORT_STAT_ENABLE;16891493 /* give it the best speed we agree on */16901494 dum->gadget.speed = dum->driver->speed;···16981516 }16991517 }17001518 }17011701- ((u16 *) buf)[0] = cpu_to_le16 (dum->port_status);17021702- ((u16 *) buf)[1] = cpu_to_le16 (dum->port_status >> 16);15191519+ set_link_state (dum);15201520+ ((__le16 *) buf)[0] = cpu_to_le16 (dum->port_status);15211521+ ((__le16 *) buf)[1] = cpu_to_le16 (dum->port_status >> 16);17031522 break;17041523 case SetHubFeature:17051524 retval = -EPIPE;···17081525 case SetPortFeature:17091526 switch (wValue) {17101527 case USB_PORT_FEAT_SUSPEND:17111711- if ((dum->port_status & (1 << USB_PORT_FEAT_SUSPEND))17121712- == 0) {17131713- dum->port_status |=17141714- (1 << USB_PORT_FEAT_SUSPEND);17151715- if (dum->driver && dum->driver->suspend) {17161716- spin_unlock (&dum->lock);17171717- dum->driver->suspend (&dum->gadget);17181718- spin_lock (&dum->lock);17191719- }15281528+ if (dum->active) {15291529+ dum->port_status |= USB_PORT_STAT_SUSPEND;15301530+15311531+ /* HNP would happen here; for now we15321532+ * assume b_bus_req is always true.15331533+ */15341534+ set_link_state (dum);15351535+ if (((1 << USB_DEVICE_B_HNP_ENABLE)15361536+ & dum->devstatus) != 0)15371537+ dev_dbg (dummy_dev(dum),15381538+ "no HNP yet!\n");17201539 }17211540 break;15411541+ case USB_PORT_FEAT_POWER:15421542+ dum->port_status |= USB_PORT_STAT_POWER;15431543+ set_link_state (dum);15441544+ break;17221545 case USB_PORT_FEAT_RESET:17231723- /* if it's already running, disconnect first */17241724- if (dum->port_status & USB_PORT_STAT_ENABLE) {17251725- dum->port_status &= ~(USB_PORT_STAT_ENABLE17261726- | USB_PORT_STAT_LOW_SPEED17271727- | USB_PORT_STAT_HIGH_SPEED);17281728- if (dum->driver) {17291729- dev_dbg (dummy_dev(dum),17301730- "disconnect\n");17311731- stop_activity (dum, dum->driver);17321732- }17331733-17341734- /* FIXME test that code path! */17351735- }15461546+ /* if it's already enabled, disable */15471547+ dum->port_status &= ~(USB_PORT_STAT_ENABLE15481548+ | USB_PORT_STAT_LOW_SPEED15491549+ | USB_PORT_STAT_HIGH_SPEED);15501550+ dum->devstatus = 0;17361551 /* 50msec reset signaling */17371552 dum->re_timeout = jiffies + msecs_to_jiffies(50);17381738- /* FALLTHROUGH */15531553+ /* FALLS THROUGH */17391554 default:17401740- dum->port_status |= (1 << wValue);15551555+ if ((dum->port_status & USB_PORT_STAT_POWER) != 0) {15561556+ dum->port_status |= (1 << wValue);15571557+ set_link_state (dum);15581558+ }17411559 }17421560 break;17431561···17511567 retval = -EPIPE;17521568 }17531569 spin_unlock_irqrestore (&dum->lock, flags);15701570+15711571+ if ((dum->port_status & PORT_C_MASK) != 0)15721572+ usb_hcd_poll_rh_status (hcd);17541573 return retval;17551574}1756157515761576+static int dummy_hub_suspend (struct usb_hcd *hcd)15771577+{15781578+ struct dummy *dum = hcd_to_dummy (hcd);15791579+15801580+ spin_lock_irq (&dum->lock);15811581+ dum->rh_state = DUMMY_RH_SUSPENDED;15821582+ set_link_state (dum);15831583+ spin_unlock_irq (&dum->lock);15841584+ return 0;15851585+}15861586+15871587+static int dummy_hub_resume (struct usb_hcd *hcd)15881588+{15891589+ struct dummy *dum = hcd_to_dummy (hcd);15901590+15911591+ spin_lock_irq (&dum->lock);15921592+ dum->rh_state = DUMMY_RH_RUNNING;15931593+ set_link_state (dum);15941594+ if (!list_empty(&dum->urbp_list))15951595+ mod_timer (&dum->timer, jiffies);15961596+ spin_unlock_irq (&dum->lock);15971597+ return 0;15981598+}1757159917581600/*-------------------------------------------------------------------------*/17591601···18351625static int dummy_start (struct usb_hcd *hcd)18361626{18371627 struct dummy *dum;18381838- struct usb_device *root;18391839- int retval;1840162818411629 dum = hcd_to_dummy (hcd);18421630···18471639 init_timer (&dum->timer);18481640 dum->timer.function = dummy_timer;18491641 dum->timer.data = (unsigned long) dum;16421642+ dum->rh_state = DUMMY_RH_RUNNING;1850164318511644 INIT_LIST_HEAD (&dum->urbp_list);1852164518531853- root = usb_alloc_dev (NULL, &hcd->self, 0);18541854- if (!root)18551855- return -ENOMEM;18561856-18571857- /* root hub enters addressed state... */18581858- hcd->state = HC_STATE_RUNNING;18591859- root->speed = USB_SPEED_HIGH;18601860-18611861- /* ...then configured, so khubd sees us. */18621862- if ((retval = usb_hcd_register_root_hub (root, hcd)) != 0) {18631863- goto err1;18641864- }18651865-18661646 /* only show a low-power port: just 8mA */18671867- hub_set_power_budget (root, 8);16471647+ hcd->power_budget = 8;16481648+ hcd->state = HC_STATE_RUNNING;16491649+ hcd->uses_new_polling = 1;1868165018691869- if ((retval = dummy_register_udc (dum)) != 0)18701870- goto err2;16511651+#ifdef CONFIG_USB_OTG16521652+ hcd->self.otg_port = 1;16531653+#endif1871165418721655 /* FIXME 'urbs' should be a per-device thing, maybe in usbcore */18731656 device_create_file (dummy_dev(dum), &dev_attr_urbs);18741657 return 0;18751875-18761876- err2:18771877- usb_disconnect (&hcd->self.root_hub);18781878- err1:18791879- usb_put_dev (root);18801880- hcd->state = HC_STATE_QUIESCING;18811881- return retval;18821658}1883165918841660static void dummy_stop (struct usb_hcd *hcd)···18721680 dum = hcd_to_dummy (hcd);1873168118741682 device_remove_file (dummy_dev(dum), &dev_attr_urbs);18751875-18761683 usb_gadget_unregister_driver (dum->driver);18771877- dummy_unregister_udc (dum);18781878-18791684 dev_info (dummy_dev(dum), "stopped\n");18801685}18811686···1900171119011712 .hub_status_data = dummy_hub_status,19021713 .hub_control = dummy_hub_control,17141714+ .hub_suspend = dummy_hub_suspend,17151715+ .hub_resume = dummy_hub_resume,19031716};1904171719051905-static int dummy_probe (struct device *dev)17181718+static int dummy_hcd_probe (struct device *dev)19061719{19071720 struct usb_hcd *hcd;19081721 int retval;···19241733 return retval;19251734}1926173519271927-static void dummy_remove (struct device *dev)17361736+static int dummy_hcd_remove (struct device *dev)19281737{19291738 struct usb_hcd *hcd;19301739···19321741 usb_remove_hcd (hcd);19331742 usb_put_hcd (hcd);19341743 the_controller = NULL;17441744+ return 0;19351745}17461746+17471747+static int dummy_hcd_suspend (struct device *dev, pm_message_t state,17481748+ u32 level)17491749+{17501750+ struct usb_hcd *hcd;17511751+17521752+ if (level != SUSPEND_DISABLE)17531753+ return 0;17541754+17551755+ dev_dbg (dev, "%s\n", __FUNCTION__);17561756+ hcd = dev_get_drvdata (dev);17571757+17581758+#ifndef CONFIG_USB_SUSPEND17591759+ /* Otherwise this would never happen */17601760+ usb_lock_device (hcd->self.root_hub);17611761+ dummy_hub_suspend (hcd);17621762+ usb_unlock_device (hcd->self.root_hub);17631763+#endif17641764+17651765+ hcd->state = HC_STATE_SUSPENDED;17661766+ return 0;17671767+}17681768+17691769+static int dummy_hcd_resume (struct device *dev, u32 level)17701770+{17711771+ struct usb_hcd *hcd;17721772+17731773+ if (level != RESUME_ENABLE)17741774+ return 0;17751775+17761776+ dev_dbg (dev, "%s\n", __FUNCTION__);17771777+ hcd = dev_get_drvdata (dev);17781778+ hcd->state = HC_STATE_RUNNING;17791779+17801780+#ifndef CONFIG_USB_SUSPEND17811781+ /* Otherwise this would never happen */17821782+ usb_lock_device (hcd->self.root_hub);17831783+ dummy_hub_resume (hcd);17841784+ usb_unlock_device (hcd->self.root_hub);17851785+#endif17861786+17871787+ usb_hcd_poll_rh_status (hcd);17881788+ return 0;17891789+}17901790+17911791+static struct device_driver dummy_hcd_driver = {17921792+ .name = (char *) driver_name,17931793+ .bus = &platform_bus_type,17941794+ .probe = dummy_hcd_probe,17951795+ .remove = dummy_hcd_remove,17961796+ .suspend = dummy_hcd_suspend,17971797+ .resume = dummy_hcd_resume,17981798+};1936179919371800/*-------------------------------------------------------------------------*/1938180119391939-static int dummy_pdev_detect (void)19401940-{19411941- int retval;18021802+/* These don't need to do anything because the pdev structures are18031803+ * statically allocated. */18041804+static void18051805+dummy_udc_release (struct device *dev) {}1942180619431943- retval = driver_register (&dummy_driver);19441944- if (retval < 0)19451945- return retval;18071807+static void18081808+dummy_hcd_release (struct device *dev) {}1946180919471947- the_pdev.name = "hc";19481948- the_pdev.dev.driver = &dummy_driver;19491949- the_pdev.dev.release = dummy_pdev_release;18101810+static struct platform_device the_udc_pdev = {18111811+ .name = (char *) gadget_name,18121812+ .id = -1,18131813+ .dev = {18141814+ .release = dummy_udc_release,18151815+ },18161816+};1950181719511951- retval = platform_device_register (&the_pdev);19521952- if (retval < 0)19531953- driver_unregister (&dummy_driver);19541954- return retval;19551955-}19561956-19571957-static void dummy_pdev_remove (void)19581958-{19591959- platform_device_unregister (&the_pdev);19601960- driver_unregister (&dummy_driver);19611961-}19621962-19631963-/*-------------------------------------------------------------------------*/18181818+static struct platform_device the_hcd_pdev = {18191819+ .name = (char *) driver_name,18201820+ .id = -1,18211821+ .dev = {18221822+ .release = dummy_hcd_release,18231823+ },18241824+};1964182519651826static int __init init (void)19661827{···2020177720211778 if (usb_disabled ())20221779 return -ENODEV;20232023- if ((retval = dummy_pdev_detect ()) != 0)17801780+17811781+ retval = driver_register (&dummy_hcd_driver);17821782+ if (retval < 0)20241783 return retval;20252025- if ((retval = dummy_probe (&the_pdev.dev)) != 0)20262026- dummy_pdev_remove ();17841784+17851785+ retval = driver_register (&dummy_udc_driver);17861786+ if (retval < 0)17871787+ goto err_register_udc_driver;17881788+17891789+ retval = platform_device_register (&the_hcd_pdev);17901790+ if (retval < 0)17911791+ goto err_register_hcd;17921792+17931793+ retval = platform_device_register (&the_udc_pdev);17941794+ if (retval < 0)17951795+ goto err_register_udc;17961796+ return retval;17971797+17981798+err_register_udc:17991799+ platform_device_unregister (&the_hcd_pdev);18001800+err_register_hcd:18011801+ driver_unregister (&dummy_udc_driver);18021802+err_register_udc_driver:18031803+ driver_unregister (&dummy_hcd_driver);20271804 return retval;20281805}20291806module_init (init);2030180720311808static void __exit cleanup (void)20321809{20332033- dummy_remove (&the_pdev.dev);20342034- dummy_pdev_remove ();18101810+ platform_device_unregister (&the_udc_pdev);18111811+ platform_device_unregister (&the_hcd_pdev);18121812+ driver_unregister (&dummy_udc_driver);18131813+ driver_unregister (&dummy_hcd_driver);20351814}20361815module_exit (cleanup);
+138-217
drivers/usb/gadget/ether.c
···8484 */85858686#define DRIVER_DESC "Ethernet Gadget"8787-#define DRIVER_VERSION "Equinox 2004"8787+#define DRIVER_VERSION "May Day 2005"88888989static const char shortname [] = "ether";9090static const char driver_desc [] = DRIVER_DESC;91919292#define RX_EXTRA 20 /* guard against rx overflows */93939494-#ifdef CONFIG_USB_ETH_RNDIS9594#include "rndis.h"9696-#else9797-#define rndis_init() 09898-#define rndis_exit() do{}while(0)9595+9696+#ifndef CONFIG_USB_ETH_RNDIS9797+#define rndis_uninit(x) do{}while(0)9898+#define rndis_deregister(c) do{}while(0)9999+#define rndis_exit() do{}while(0)99100#endif100101101102/* CDC and RNDIS support the same host-chosen outgoing packet filters. */···141140 * It also ASSUMES a self-powered device, without remote wakeup,142141 * although remote wakeup support would make sense.143142 */144144-static const char *EP_IN_NAME;145145-static const char *EP_OUT_NAME;146146-static const char *EP_STATUS_NAME;147143148144/*-------------------------------------------------------------------------*/149145···310312#define FS_BPS (19 * 64 * 1 * 1000 * 8)311313312314#ifdef CONFIG_USB_GADGET_DUALSPEED315315+#define DEVSPEED USB_SPEED_HIGH313316314317static unsigned qmult = 5;315318module_param (qmult, uint, S_IRUGO|S_IWUSR);···329330}330331331332#else /* full speed (low speed doesn't do bulk) */333333+#define DEVSPEED USB_SPEED_FULL334334+332335#define qlen(gadget) DEFAULT_QLEN333336334337static inline int BITRATE(struct usb_gadget *g)···396395#define STRING_SUBSET 8397396#define STRING_RNDIS 9398397399399-#define USB_BUFSIZ 256 /* holds our biggest descriptor */398398+/* holds our biggest descriptor (or RNDIS response) */399399+#define USB_BUFSIZ 256400400401401/*402402 * This device advertises one configuration, eth_config, unless RNDIS···540538 .bDataInterface = 0x01,541539};542540543543-static struct usb_cdc_acm_descriptor acm_descriptor = {541541+static const struct usb_cdc_acm_descriptor acm_descriptor = {544542 .bLength = sizeof acm_descriptor,545543 .bDescriptorType = USB_DT_CS_INTERFACE,546544 .bDescriptorSubType = USB_CDC_ACM_TYPE,···848846#else849847850848/* if there's no high speed support, maxpacket doesn't change. */851851-#define ep_desc(g,hs,fs) fs849849+#define ep_desc(g,hs,fs) (((void)(g)), (fs))852850853851static inline void __init hs_subset_descriptors(void)854852{···948946static void eth_start (struct eth_dev *dev, int gfp_flags);949947static int alloc_requests (struct eth_dev *dev, unsigned n, int gfp_flags);950948951951-#ifdef DEV_CONFIG_CDC952952-static inline int ether_alt_ep_setup (struct eth_dev *dev, struct usb_ep *ep)949949+static int950950+set_ether_config (struct eth_dev *dev, int gfp_flags)953951{954954- const struct usb_endpoint_descriptor *d;952952+ int result = 0;953953+ struct usb_gadget *gadget = dev->gadget;954954+955955+ /* status endpoint used for RNDIS and (optionally) CDC */956956+ if (!subset_active(dev) && dev->status_ep) {957957+ dev->status = ep_desc (gadget, &hs_status_desc,958958+ &fs_status_desc);959959+ dev->status_ep->driver_data = dev;960960+961961+ result = usb_ep_enable (dev->status_ep, dev->status);962962+ if (result != 0) {963963+ DEBUG (dev, "enable %s --> %d\n", 964964+ dev->status_ep->name, result);965965+ goto done;966966+ }967967+ }968968+969969+ dev->in = ep_desc (dev->gadget, &hs_source_desc, &fs_source_desc);970970+ dev->in_ep->driver_data = dev;971971+972972+ dev->out = ep_desc (dev->gadget, &hs_sink_desc, &fs_sink_desc);973973+ dev->out_ep->driver_data = dev;955974956975 /* With CDC, the host isn't allowed to use these two data957976 * endpoints in the default altsetting for the interface.···982959 * a side effect of setting a packet filter. Deactivation is983960 * from REMOTE_NDIS_HALT_MSG, reset from REMOTE_NDIS_RESET_MSG.984961 */985985-986986- /* one endpoint writes data back IN to the host */987987- if (strcmp (ep->name, EP_IN_NAME) == 0) {988988- d = ep_desc (dev->gadget, &hs_source_desc, &fs_source_desc);989989- ep->driver_data = dev;990990- dev->in = d;991991-992992- /* one endpoint just reads OUT packets */993993- } else if (strcmp (ep->name, EP_OUT_NAME) == 0) {994994- d = ep_desc (dev->gadget, &hs_sink_desc, &fs_sink_desc);995995- ep->driver_data = dev;996996- dev->out = d;997997-998998- /* optional status/notification endpoint */999999- } else if (EP_STATUS_NAME &&10001000- strcmp (ep->name, EP_STATUS_NAME) == 0) {10011001- int result;10021002-10031003- d = ep_desc (dev->gadget, &hs_status_desc, &fs_status_desc);10041004- result = usb_ep_enable (ep, d);10051005- if (result < 0)10061006- return result;10071007-10081008- ep->driver_data = dev;10091009- dev->status = d;10101010- }10111011- return 0;10121012-}10131013-#endif10141014-10151015-#if defined(DEV_CONFIG_SUBSET) || defined(CONFIG_USB_ETH_RNDIS)10161016-static inline int ether_ep_setup (struct eth_dev *dev, struct usb_ep *ep)10171017-{10181018- int result;10191019- const struct usb_endpoint_descriptor *d;10201020-10211021- /* CDC subset is simpler: if the device is there,10221022- * it's live with rx and tx endpoints.10231023- *10241024- * Do this as a shortcut for RNDIS too.10251025- */10261026-10271027- /* one endpoint writes data back IN to the host */10281028- if (strcmp (ep->name, EP_IN_NAME) == 0) {10291029- d = ep_desc (dev->gadget, &hs_source_desc, &fs_source_desc);10301030- result = usb_ep_enable (ep, d);10311031- if (result < 0)10321032- return result;10331033-10341034- ep->driver_data = dev;10351035- dev->in = d;10361036-10371037- /* one endpoint just reads OUT packets */10381038- } else if (strcmp (ep->name, EP_OUT_NAME) == 0) {10391039- d = ep_desc (dev->gadget, &hs_sink_desc, &fs_sink_desc);10401040- result = usb_ep_enable (ep, d);10411041- if (result < 0)10421042- return result;10431043-10441044- ep->driver_data = dev;10451045- dev->out = d;10461046- }10471047-10481048- return 0;10491049-}10501050-#endif10511051-10521052-static int10531053-set_ether_config (struct eth_dev *dev, int gfp_flags)10541054-{10551055- int result = 0;10561056- struct usb_ep *ep;10571057- struct usb_gadget *gadget = dev->gadget;10581058-10591059- gadget_for_each_ep (ep, gadget) {10601060-#ifdef DEV_CONFIG_CDC10611061- if (!dev->rndis && dev->cdc) {10621062- result = ether_alt_ep_setup (dev, ep);10631063- if (result == 0)10641064- continue;10651065- }10661066-#endif10671067-10681068-#ifdef CONFIG_USB_ETH_RNDIS10691069- if (dev->rndis && strcmp (ep->name, EP_STATUS_NAME) == 0) {10701070- const struct usb_endpoint_descriptor *d;10711071- d = ep_desc (gadget, &hs_status_desc, &fs_status_desc);10721072- result = usb_ep_enable (ep, d);10731073- if (result == 0) {10741074- ep->driver_data = dev;10751075- dev->status = d;10761076- continue;10771077- }10781078- } else10791079-#endif10801080-10811081- {10821082-#if defined(DEV_CONFIG_SUBSET) || defined(CONFIG_USB_ETH_RNDIS)10831083- result = ether_ep_setup (dev, ep);10841084- if (result == 0)10851085- continue;10861086-#endif962962+ if (!cdc_active(dev)) {963963+ result = usb_ep_enable (dev->in_ep, dev->in);964964+ if (result != 0) {965965+ DEBUG(dev, "enable %s --> %d\n", 966966+ dev->in_ep->name, result);967967+ goto done;1087968 }108896910891089- /* stop on error */10901090- ERROR (dev, "can't enable %s, result %d\n", ep->name, result);10911091- break;970970+ result = usb_ep_enable (dev->out_ep, dev->out);971971+ if (result != 0) {972972+ DEBUG (dev, "enable %s --> %d\n", 973973+ dev->in_ep->name, result);974974+ goto done;975975+ }1092976 }10931093- if (!result && (!dev->in_ep || !dev->out_ep))10941094- result = -ENODEV;1095977978978+done:1096979 if (result == 0)1097980 result = alloc_requests (dev, qlen (gadget), gfp_flags);10989811099982 /* on error, disable any endpoints */1100983 if (result < 0) {11011101-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)11021102- if (dev->status)984984+ if (!subset_active(dev))1103985 (void) usb_ep_disable (dev->status_ep);11041104-#endif1105986 dev->status = NULL;11061106-#if defined(DEV_CONFIG_SUBSET) || defined(CONFIG_USB_ETH_RNDIS)11071107- if (dev->rndis || !dev->cdc) {11081108- if (dev->in)11091109- (void) usb_ep_disable (dev->in_ep);11101110- if (dev->out)11111111- (void) usb_ep_disable (dev->out_ep);11121112- }11131113-#endif987987+ (void) usb_ep_disable (dev->in_ep);988988+ (void) usb_ep_disable (dev->out_ep);1114989 dev->in = NULL;1115990 dev->out = NULL;1116991 } else···10161095 /* activate non-CDC configs right away10171096 * this isn't strictly according to the RNDIS spec10181097 */10191019-#if defined(DEV_CONFIG_SUBSET) || defined(CONFIG_USB_ETH_RNDIS)10201020- if (dev->rndis || !dev->cdc) {10981098+ if (!cdc_active (dev)) {10211099 netif_carrier_on (dev->net);10221100 if (netif_running (dev->net)) {10231101 spin_unlock (&dev->lock);···10241104 spin_lock (&dev->lock);10251105 }10261106 }10271027-#endif1028110710291108 if (result == 0)10301109 DEBUG (dev, "qlen %d\n", qlen (gadget));···1043112410441125 netif_stop_queue (dev->net);10451126 netif_carrier_off (dev->net);11271127+ rndis_uninit(dev->rndis_config);1046112810471129 /* disable endpoints, forcing (synchronous) completion of10481130 * pending i/o. then free the requests.···10701150 if (dev->status) {10711151 usb_ep_disable (dev->status_ep);10721152 }11531153+ dev->rndis = 0;11541154+ dev->cdc_filter = 0;10731155 dev->config = 0;10741156}10751157···10841162 int result = 0;10851163 struct usb_gadget *gadget = dev->gadget;1086116410871087- if (number == dev->config)10881088- return 0;10891089-10901165 if (gadget_is_sa1100 (gadget)10911166 && dev->config10921167 && atomic_read (&dev->tx_qlen) != 0) {···10931174 }10941175 eth_reset_config (dev);1095117610961096- /* default: pass all packets, no multicast filtering */10971097- dev->cdc_filter = DEFAULT_FILTER;10981098-10991177 switch (number) {11001178 case DEV_CONFIG_VALUE:11011101- dev->rndis = 0;11021179 result = set_ether_config (dev, gfp_flags);11031180 break;11041181#ifdef CONFIG_USB_ETH_RNDIS···11331218 dev->config = number;11341219 INFO (dev, "%s speed config #%d: %d mA, %s, using %s\n",11351220 speed, number, power, driver_desc,11361136- dev->rndis12211221+ rndis_active(dev)11371222 ? "RNDIS"11381138- : (dev->cdc12231223+ : (cdc_active(dev)11391224 ? "CDC Ethernet"11401225 : "CDC Ethernet Subset"));11411226 }···11451230/*-------------------------------------------------------------------------*/1146123111471232#ifdef DEV_CONFIG_CDC12331233+12341234+/* The interrupt endpoint is used in CDC networking models (Ethernet, ATM)12351235+ * only to notify the host about link status changes (which we support) or12361236+ * report completion of some encapsulated command (as used in RNDIS). Since12371237+ * we want this CDC Ethernet code to be vendor-neutral, we don't use that12381238+ * command mechanism; and only one status request is ever queued.12391239+ */1148124011491241static void eth_status_complete (struct usb_ep *ep, struct usb_request *req)11501242{···11811259 } else if (value != -ECONNRESET)11821260 DEBUG (dev, "event %02x --> %d\n",11831261 event->bNotificationType, value);11841184- event->bmRequestType = 0xff;12621262+ req->context = NULL;11851263}1186126411871265static void issue_start_status (struct eth_dev *dev)···11981276 * a "cancel the whole queue" primitive since any11991277 * unlink-one primitive has way too many error modes.12001278 * here, we "know" toggle is already clear...12791279+ *12801280+ * FIXME iff req->context != null just dequeue it12011281 */12021282 usb_ep_disable (dev->status_ep);12031283 usb_ep_enable (dev->status_ep, dev->status);···1216129212171293 req->length = sizeof *event;12181294 req->complete = eth_status_complete;12951295+ req->context = dev;12961296+12191297 value = usb_ep_queue (dev->status_ep, req, GFP_ATOMIC);12201298 if (value < 0)12211299 DEBUG (dev, "status buf queue --> %d\n", value);···12771351 struct eth_dev *dev = get_gadget_data (gadget);12781352 struct usb_request *req = dev->req;12791353 int value = -EOPNOTSUPP;12801280- u16 wIndex = (__force u16) ctrl->wIndex;12811281- u16 wValue = (__force u16) ctrl->wValue;12821282- u16 wLength = (__force u16) ctrl->wLength;13541354+ u16 wIndex = le16_to_cpu(ctrl->wIndex);13551355+ u16 wValue = le16_to_cpu(ctrl->wValue);13561356+ u16 wLength = le16_to_cpu(ctrl->wLength);1283135712841358 /* descriptors just go into the pre-allocated ep0 buffer,12851359 * while config change events may enable network traffic.···13501424 || !dev->config13511425 || wIndex > 1)13521426 break;13531353- if (!dev->cdc && wIndex != 0)14271427+ if (!cdc_active(dev) && wIndex != 0)13541428 break;13551429 spin_lock (&dev->lock);13561430···1382145613831457 /* CDC requires the data transfers not be done from13841458 * the default interface setting ... also, setting13851385- * the non-default interface clears filters etc.14591459+ * the non-default interface resets filters etc.13861460 */13871461 if (wValue == 1) {14621462+ if (!cdc_active (dev))14631463+ break;13881464 usb_ep_enable (dev->in_ep, dev->in);13891465 usb_ep_enable (dev->out_ep, dev->out);13901466 dev->cdc_filter = DEFAULT_FILTER;···14201492 || !dev->config14211493 || wIndex > 1)14221494 break;14231423- if (!(dev->cdc || dev->rndis) && wIndex != 0)14951495+ if (!(cdc_active(dev) || rndis_active(dev)) && wIndex != 0)14241496 break;1425149714261498 /* for CDC, iff carrier is on, data interface is active. */14271427- if (dev->rndis || wIndex != 1)14991499+ if (rndis_active(dev) || wIndex != 1)14281500 *(u8 *)req->buf = 0;14291501 else14301502 *(u8 *)req->buf = netif_carrier_ok (dev->net) ? 1 : 0;···14371509 * wValue = packet filter bitmap14381510 */14391511 if (ctrl->bRequestType != (USB_TYPE_CLASS|USB_RECIP_INTERFACE)14401440- || !dev->cdc14411441- || dev->rndis15121512+ || !cdc_active(dev)14421513 || wLength != 014431514 || wIndex > 1)14441515 break;···14611534 */14621535 case USB_CDC_SEND_ENCAPSULATED_COMMAND:14631536 if (ctrl->bRequestType != (USB_TYPE_CLASS|USB_RECIP_INTERFACE)14641464- || !dev->rndis15371537+ || !rndis_active(dev)14651538 || wLength > USB_BUFSIZ14661539 || wValue14671540 || rndis_control_intf.bInterfaceNumber···14761549 case USB_CDC_GET_ENCAPSULATED_RESPONSE:14771550 if ((USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE)14781551 == ctrl->bRequestType14791479- && dev->rndis15521552+ && rndis_active(dev)14801553 // && wLength >= 0x040014811554 && !wValue14821555 && rndis_control_intf.bInterfaceNumber···16151688 */16161689 size = (sizeof (struct ethhdr) + dev->net->mtu + RX_EXTRA);16171690 size += dev->out_ep->maxpacket - 1;16181618-#ifdef CONFIG_USB_ETH_RNDIS16191619- if (dev->rndis)16911691+ if (rndis_active(dev))16201692 size += sizeof (struct rndis_packet_msg_type);16211621-#endif 16221693 size -= size % dev->out_ep->maxpacket;1623169416241695 if ((skb = alloc_skb (size + NET_IP_ALIGN, gfp_flags)) == 0) {···16601735 /* normal completion */16611736 case 0:16621737 skb_put (skb, req->actual);16631663-#ifdef CONFIG_USB_ETH_RNDIS16641738 /* we know MaxPacketsPerTransfer == 1 here */16651665- if (dev->rndis)17391739+ if (rndis_active(dev))16661740 status = rndis_rm_hdr (skb);16671667-#endif16681741 if (status < 016691742 || ETH_HLEN > skb->len16701743 || skb->len > ETH_FRAME_LEN) {···17821859 struct usb_request *req;17831860 unsigned long flags;1784186117851785- clear_bit (WORK_RX_MEMORY, &dev->todo);17861786-17871862 /* fill unused rxq slots with some skb */17881863 spin_lock_irqsave (&dev->lock, flags);17891864 while (!list_empty (&dev->rx_reqs)) {···18041883{18051884 struct eth_dev *dev = _dev;1806188518071807- if (test_bit (WORK_RX_MEMORY, &dev->todo)) {18861886+ if (test_and_clear_bit (WORK_RX_MEMORY, &dev->todo)) {18081887 if (netif_running (dev->net))18091888 rx_fill (dev, GFP_KERNEL);18101810- else18111811- clear_bit (WORK_RX_MEMORY, &dev->todo);18121889 }1813189018141891 if (dev->todo)···18901971 * or the hardware can't use skb buffers.18911972 * or there's not enough space for any RNDIS headers we need18921973 */18931893-#ifdef CONFIG_USB_ETH_RNDIS18941894- if (dev->rndis) {19741974+ if (rndis_active(dev)) {18951975 struct sk_buff *skb_rndis;1896197618971977 skb_rndis = skb_realloc_headroom (skb,···19031985 rndis_add_hdr (skb);19041986 length = skb->len;19051987 }19061906-#endif19071988 req->buf = skb->data;19081989 req->context = skb;19091990 req->complete = tx_complete;···19352018 }1936201919372020 if (retval) {19381938-#ifdef CONFIG_USB_ETH_RNDIS19392021drop:19401940-#endif19412022 dev->stats.tx_dropped++;19422023 dev_kfree_skb_any (skb);19432024 spin_lock_irqsave (&dev->lock, flags);···1951203619522037#ifdef CONFIG_USB_ETH_RNDIS1953203819541954-static void rndis_send_media_state (struct eth_dev *dev, int connect)19551955-{19561956- if (!dev)19571957- return;19581958-19591959- if (connect) {19601960- if (rndis_signal_connect (dev->rndis_config))19611961- return;19621962- } else {19631963- if (rndis_signal_disconnect (dev->rndis_config))19641964- return;19651965- }19661966-}20392039+/* The interrupt endpoint is used in RNDIS to notify the host when messages20402040+ * other than data packets are available ... notably the REMOTE_NDIS_*_CMPLT20412041+ * messages, but also REMOTE_NDIS_INDICATE_STATUS_MSG and potentially even20422042+ * REMOTE_NDIS_KEEPALIVE_MSG.20432043+ *20442044+ * The RNDIS control queue is processed by GET_ENCAPSULATED_RESPONSE, and20452045+ * normally just one notification will be queued.20462046+ */20472047+20482048+static struct usb_request *eth_req_alloc (struct usb_ep *, unsigned, unsigned);20492049+static void eth_req_free (struct usb_ep *ep, struct usb_request *req);1967205019682051static void19692052rndis_control_ack_complete (struct usb_ep *ep, struct usb_request *req)19702053{20542054+ struct eth_dev *dev = ep->driver_data;20552055+19712056 if (req->status || req->actual != req->length)19721972- DEBUG ((struct eth_dev *) ep->driver_data,20572057+ DEBUG (dev,19732058 "rndis control ack complete --> %d, %d/%d\n",19742059 req->status, req->actual, req->length);20602060+ req->context = NULL;20612061+20622062+ if (req != dev->stat_req)20632063+ eth_req_free(ep, req);19752064}1976206519772066static int rndis_control_ack (struct net_device *net)···19902071 return -ENODEV;19912072 }1992207320742074+ /* in case queue length > 1 */20752075+ if (resp->context) {20762076+ resp = eth_req_alloc (dev->status_ep, 8, GFP_ATOMIC);20772077+ if (!resp)20782078+ return -ENOMEM;20792079+ }20802080+19932081 /* Send RNDIS RESPONSE_AVAILABLE notification;19942082 * USB_CDC_NOTIFY_RESPONSE_AVAILABLE should work too19952083 */19962084 resp->length = 8;19972085 resp->complete = rndis_control_ack_complete;20862086+ resp->context = dev;1998208719992088 *((__le32 *) resp->buf) = __constant_cpu_to_le32 (1);20002089 *((__le32 *) resp->buf + 1) = __constant_cpu_to_le32 (0);···20162089 return 0;20172090}2018209120922092+#else20932093+20942094+#define rndis_control_ack NULL20952095+20192096#endif /* RNDIS */2020209720212098static void eth_start (struct eth_dev *dev, int gfp_flags)···20322101 /* and open the tx floodgates */ 20332102 atomic_set (&dev->tx_qlen, 0);20342103 netif_wake_queue (dev->net);20352035-#ifdef CONFIG_USB_ETH_RNDIS20362036- if (dev->rndis) {21042104+ if (rndis_active(dev)) {20372105 rndis_set_param_medium (dev->rndis_config,20382106 NDIS_MEDIUM_802_3,20392107 BITRATE(dev->gadget)/100);20402040- rndis_send_media_state (dev, 1);21082108+ (void) rndis_signal_connect (dev->rndis_config);20412109 }20422042-#endif 20432110}2044211120452112static int eth_open (struct net_device *net)···20782149 }20792150 }2080215120812081-#ifdef CONFIG_USB_ETH_RNDIS20822082- if (dev->rndis) {21522152+ if (rndis_active(dev)) {20832153 rndis_set_param_medium (dev->rndis_config,20842154 NDIS_MEDIUM_802_3, 0);20852085- rndis_send_media_state (dev, 0);21552155+ (void) rndis_signal_disconnect (dev->rndis_config);20862156 }20872087-#endif2088215720892158 return 0;20902159}2091216020922161/*-------------------------------------------------------------------------*/2093216220942094-static struct usb_request *eth_req_alloc (struct usb_ep *ep, unsigned size)21632163+static struct usb_request *21642164+eth_req_alloc (struct usb_ep *ep, unsigned size, unsigned gfp_flags)20952165{20962166 struct usb_request *req;2097216720982098- req = usb_ep_alloc_request (ep, GFP_KERNEL);21682168+ req = usb_ep_alloc_request (ep, gfp_flags);20992169 if (!req)21002170 return NULL;2101217121022102- req->buf = kmalloc (size, GFP_KERNEL);21722172+ req->buf = kmalloc (size, gfp_flags);21032173 if (!req->buf) {21042174 usb_ep_free_request (ep, req);21052175 req = NULL;···21202192 struct eth_dev *dev = get_gadget_data (gadget);2121219321222194 DEBUG (dev, "unbind\n");21232123-#ifdef CONFIG_USB_ETH_RNDIS21242195 rndis_deregister (dev->rndis_config);21252196 rndis_exit ();21262126-#endif2127219721282198 /* we've already been disconnected ... no i/o is active */21292199 if (dev->req) {···22942368 gadget->name);22952369 return -ENODEV;22962370 }22972297- EP_IN_NAME = in_ep->name;22982371 in_ep->driver_data = in_ep; /* claim */2299237223002373 out_ep = usb_ep_autoconfig (gadget, &fs_sink_desc);23012374 if (!out_ep)23022375 goto autoconf_fail;23032303- EP_OUT_NAME = out_ep->name;23042376 out_ep->driver_data = out_ep; /* claim */2305237723062378#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)···23082384 if (cdc || rndis) {23092385 status_ep = usb_ep_autoconfig (gadget, &fs_status_desc);23102386 if (status_ep) {23112311- EP_STATUS_NAME = status_ep->name;23122387 status_ep->driver_data = status_ep; /* claim */23132388 } else if (rndis) {23142389 dev_err (&gadget->dev,···23492426 hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;23502427 hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;23512428#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)23522352- if (EP_STATUS_NAME)24292429+ if (status_ep)23532430 hs_status_desc.bEndpointAddress =23542431 fs_status_desc.bEndpointAddress;23552432#endif···24222499 SET_ETHTOOL_OPS(net, &ops);2423250024242501 /* preallocate control message data and buffer */24252425- dev->req = eth_req_alloc (gadget->ep0, USB_BUFSIZ);25022502+ dev->req = eth_req_alloc (gadget->ep0, USB_BUFSIZ, GFP_KERNEL);24262503 if (!dev->req)24272504 goto fail;24282505 dev->req->complete = eth_setup_complete;2429250624302507 /* ... and maybe likewise for status transfer */25082508+#ifdef DEV_CONFIG_CDC24312509 if (dev->status_ep) {24322510 dev->stat_req = eth_req_alloc (dev->status_ep,24332433- STATUS_BYTECOUNT);25112511+ STATUS_BYTECOUNT, GFP_KERNEL);24342512 if (!dev->stat_req) {24352513 eth_req_free (gadget->ep0, dev->req);24362514 goto fail;24372515 }25162516+ dev->stat_req->context = NULL;24382517 }25182518+#endif2439251924402520 /* finish hookup to lower layer ... */24412521 dev->gadget = gadget;···24522526 netif_stop_queue (dev->net);24532527 netif_carrier_off (dev->net);2454252824552455- // SET_NETDEV_DEV (dev->net, &gadget->dev);25292529+ SET_NETDEV_DEV (dev->net, &gadget->dev);24562530 status = register_netdev (dev->net);24572531 if (status < 0)24582532 goto fail1;2459253324602534 INFO (dev, "%s, version: " DRIVER_VERSION "\n", driver_desc);24612535 INFO (dev, "using %s, OUT %s IN %s%s%s\n", gadget->name,24622462- EP_OUT_NAME, EP_IN_NAME,24632463- EP_STATUS_NAME ? " STATUS " : "",24642464- EP_STATUS_NAME ? EP_STATUS_NAME : ""25362536+ out_ep->name, in_ep->name,25372537+ status_ep ? " STATUS " : "",25382538+ status_ep ? status_ep->name : ""24652539 );24662540 INFO (dev, "MAC %02x:%02x:%02x:%02x:%02x:%02x\n",24672541 net->dev_addr [0], net->dev_addr [1],···24742548 dev->host_mac [2], dev->host_mac [3],24752549 dev->host_mac [4], dev->host_mac [5]);2476255024772477-#ifdef CONFIG_USB_ETH_RNDIS24782551 if (rndis) {24792552 u32 vendorID = 0;24802553···24902565 /* these set up a lot of the OIDs that RNDIS needs */24912566 rndis_set_host_mac (dev->rndis_config, dev->host_mac);24922567 if (rndis_set_param_dev (dev->rndis_config, dev->net,24932493- &dev->stats))25682568+ &dev->stats, &dev->cdc_filter))24942569 goto fail0;24952570 if (rndis_set_param_vendor (dev->rndis_config, vendorID,24962571 manufacturer))···25012576 goto fail0;25022577 INFO (dev, "RNDIS ready\n");25032578 }25042504-#endif 2505257925062580 return status;25072581···25342610/*-------------------------------------------------------------------------*/2535261125362612static struct usb_gadget_driver eth_driver = {25372537-#ifdef CONFIG_USB_GADGET_DUALSPEED25382538- .speed = USB_SPEED_HIGH,25392539-#else25402540- .speed = USB_SPEED_FULL,25412541-#endif26132613+ .speed = DEVSPEED,26142614+25422615 .function = (char *) driver_desc,25432616 .bind = eth_bind,25442617 .unbind = eth_unbind,
+29-32
drivers/usb/gadget/file_storage.c
···8181 * removable Default false, boolean for removable media8282 * luns=N Default N = number of filenames, number of8383 * LUNs to support8484+ * stall Default determined according to the type of8585+ * USB device controller (usually true),8686+ * boolean to permit the driver to halt8787+ * bulk endpoints8488 * transport=XXX Default BBB, transport name (CB, CBI, or BBB)8589 * protocol=YYY Default SCSI, protocol name (RBC, 8020 or8690 * ATAPI, QIC, UFI, 8070, or SCSI;···9591 * buflen=N Default N=16384, buffer size used (will be9692 * rounded down to a multiple of9793 * PAGE_CACHE_SIZE)9898- * stall Default determined according to the type of9999- * USB device controller (usually true),100100- * boolean to permit the driver to halt101101- * bulk endpoints10294 *10395 * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "ro",104104- * "removable", and "luns" options are available; default values are used105105- * for everything else.9696+ * "removable", "luns", and "stall" options are available; default values9797+ * are used for everything else.10698 *10799 * The pathnames of the backing files and the ro settings are available in108100 * the attribute files "file" and "ro" in the lun<n> subdirectory of the···342342 int num_ros;343343 unsigned int nluns;344344345345+ int removable;346346+ int can_stall;347347+345348 char *transport_parm;346349 char *protocol_parm;347347- int removable;348350 unsigned short vendor;349351 unsigned short product;350352 unsigned short release;351353 unsigned int buflen;352352- int can_stall;353354354355 int transport_type;355356 char *transport_name;···361360 .transport_parm = "BBB",362361 .protocol_parm = "SCSI",363362 .removable = 0,363363+ .can_stall = 1,364364 .vendor = DRIVER_VENDOR_ID,365365 .product = DRIVER_PRODUCT_ID,366366 .release = 0xffff, // Use controller chip type367367 .buflen = 16384,368368- .can_stall = 1,369368 };370369371370···380379381380module_param_named(removable, mod_data.removable, bool, S_IRUGO);382381MODULE_PARM_DESC(removable, "true to simulate removable media");382382+383383+module_param_named(stall, mod_data.can_stall, bool, S_IRUGO);384384+MODULE_PARM_DESC(stall, "false to prevent bulk stalls");383385384386385387/* In the non-TEST version, only the module parameters listed above···407403408404module_param_named(buflen, mod_data.buflen, uint, S_IRUGO);409405MODULE_PARM_DESC(buflen, "I/O buffer size");410410-411411-module_param_named(stall, mod_data.can_stall, bool, S_IRUGO);412412-MODULE_PARM_DESC(stall, "false to prevent bulk stalls");413406414407#endif /* CONFIG_USB_FILE_STORAGE_TEST */415408···819818 buf[0] = val >> 24;820819 buf[1] = val >> 16;821820 buf[2] = val >> 8;822822- buf[3] = val;821821+ buf[3] = val & 0xff;823822}824823825824···12771276{12781277 struct usb_request *req = fsg->ep0req;12791278 int value = -EOPNOTSUPP;12801280- u16 w_index = ctrl->wIndex;12811281- u16 w_length = ctrl->wLength;12791279+ u16 w_index = le16_to_cpu(ctrl->wIndex);12801280+ u16 w_length = le16_to_cpu(ctrl->wLength);1282128112831282 if (!fsg->config)12841283 return value;···13131312 }13141313 VDBG(fsg, "get max LUN\n");13151314 *(u8 *) req->buf = fsg->nluns - 1;13161316- value = min(w_length, (u16) 1);13151315+ value = 1;13171316 break;13181317 }13191318 }···13451344 "unknown class-specific control req "13461345 "%02x.%02x v%04x i%04x l%u\n",13471346 ctrl->bRequestType, ctrl->bRequest,13481348- ctrl->wValue, w_index, w_length);13471347+ le16_to_cpu(ctrl->wValue), w_index, w_length);13491348 return value;13501349}13511350···13591358{13601359 struct usb_request *req = fsg->ep0req;13611360 int value = -EOPNOTSUPP;13621362- u16 w_index = ctrl->wIndex;13631363- u16 w_value = ctrl->wValue;13641364- u16 w_length = ctrl->wLength;13611361+ u16 w_index = le16_to_cpu(ctrl->wIndex);13621362+ u16 w_value = le16_to_cpu(ctrl->wValue);1365136313661364 /* Usually this just stores reply data in the pre-allocated ep0 buffer,13671365 * but config change events will also reconfigure hardware. */···1374137413751375 case USB_DT_DEVICE:13761376 VDBG(fsg, "get device descriptor\n");13771377- value = min(w_length, (u16) sizeof device_desc);13771377+ value = sizeof device_desc;13781378 memcpy(req->buf, &device_desc, value);13791379 break;13801380#ifdef CONFIG_USB_GADGET_DUALSPEED···13821382 VDBG(fsg, "get device qualifier\n");13831383 if (!fsg->gadget->is_dualspeed)13841384 break;13851385- value = min(w_length, (u16) sizeof dev_qualifier);13851385+ value = sizeof dev_qualifier;13861386 memcpy(req->buf, &dev_qualifier, value);13871387 break;13881388···14011401 req->buf,14021402 w_value >> 8,14031403 w_value & 0xff);14041404- if (value >= 0)14051405- value = min(w_length, (u16) value);14061404 break;1407140514081406 case USB_DT_STRING:···14091411 /* wIndex == language code */14101412 value = usb_gadget_get_string(&stringtab,14111413 w_value & 0xff, req->buf);14121412- if (value >= 0)14131413- value = min(w_length, (u16) value);14141414 break;14151415 }14161416 break;···14341438 break;14351439 VDBG(fsg, "get configuration\n");14361440 *(u8 *) req->buf = fsg->config;14371437- value = min(w_length, (u16) 1);14411441+ value = 1;14381442 break;1439144314401444 case USB_REQ_SET_INTERFACE:···14621466 }14631467 VDBG(fsg, "get interface\n");14641468 *(u8 *) req->buf = 0;14651465- value = min(w_length, (u16) 1);14691469+ value = 1;14661470 break;1467147114681472 default:14691473 VDBG(fsg,14701474 "unknown control req %02x.%02x v%04x i%04x l%u\n",14711475 ctrl->bRequestType, ctrl->bRequest,14721472- w_value, w_index, w_length);14761476+ w_value, w_index, le16_to_cpu(ctrl->wLength));14731477 }1474147814751479 return value;···14811485{14821486 struct fsg_dev *fsg = get_gadget_data(gadget);14831487 int rc;14881488+ int w_length = le16_to_cpu(ctrl->wLength);1484148914851490 ++fsg->ep0_req_tag; // Record arrival of a new request14861491 fsg->ep0req->context = NULL;···1495149814961499 /* Respond with data/status or defer until later? */14971500 if (rc >= 0 && rc != DELAYED_STATUS) {15011501+ rc = min(rc, w_length);14981502 fsg->ep0req->length = rc;14991499- fsg->ep0req->zero = (rc < ctrl->wLength &&15001500- (rc % gadget->ep0->maxpacket) == 0);15031503+ fsg->ep0req->zero = rc < w_length;15011504 fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ?15021505 "ep0-in" : "ep0-out");15031506 rc = ep0_queue(fsg);···26572660 }26582661 }2659266226602660- /* Check that the LUN values are oonsistent */26632663+ /* Check that the LUN values are consistent */26612664 if (transport_is_bbb()) {26622665 if (fsg->lun != lun)26632666 DBG(fsg, "using LUN %d from CBW, "
+17-11
drivers/usb/gadget/goku_udc.c
···7070 * seem to behave quite as expected. Used by default.7171 *7272 * OUT dma documents design problems handling the common "short packet"7373- * transfer termination policy; it couldn't enabled by default, even7373+ * transfer termination policy; it couldn't be enabled by default, even7474 * if the OUT-dma abort problems had a resolution.7575 */7676static unsigned use_dma = 1;···313313#if defined(CONFIG_X86)314314#define USE_KMALLOC315315316316-#elif defined(CONFIG_MIPS) && !defined(CONFIG_NONCOHERENT_IO)316316+#elif defined(CONFIG_MIPS) && !defined(CONFIG_DMA_NONCOHERENT)317317#define USE_KMALLOC318318319319#elif defined(CONFIG_PPC) && !defined(CONFIG_NOT_COHERENT_CACHE)···15241524 /* read SETUP packet and enter DATA stage */15251525 ctrl.bRequestType = readl(®s->bRequestType);15261526 ctrl.bRequest = readl(®s->bRequest);15271527- ctrl.wValue = (readl(®s->wValueH) << 8) | readl(®s->wValueL);15281528- ctrl.wIndex = (readl(®s->wIndexH) << 8) | readl(®s->wIndexL);15291529- ctrl.wLength = (readl(®s->wLengthH) << 8) | readl(®s->wLengthL);15271527+ ctrl.wValue = cpu_to_le16((readl(®s->wValueH) << 8)15281528+ | readl(®s->wValueL));15291529+ ctrl.wIndex = cpu_to_le16((readl(®s->wIndexH) << 8)15301530+ | readl(®s->wIndexL));15311531+ ctrl.wLength = cpu_to_le16((readl(®s->wLengthH) << 8)15321532+ | readl(®s->wLengthL));15301533 writel(0, ®s->SetupRecv);1531153415321535 nuke(&dev->ep[0], 0);···15511548 case USB_REQ_CLEAR_FEATURE:15521549 switch (ctrl.bRequestType) {15531550 case USB_RECIP_ENDPOINT:15541554- tmp = ctrl.wIndex & 0x0f;15511551+ tmp = le16_to_cpu(ctrl.wIndex) & 0x0f;15551552 /* active endpoint */15561553 if (tmp > 3 || (!dev->ep[tmp].desc && tmp != 0))15571554 goto stall;15581558- if (ctrl.wIndex & USB_DIR_IN) {15551555+ if (ctrl.wIndex & __constant_cpu_to_le16(15561556+ USB_DIR_IN)) {15591557 if (!dev->ep[tmp].is_in)15601558 goto stall;15611559 } else {15621560 if (dev->ep[tmp].is_in)15631561 goto stall;15641562 }15651565- if (ctrl.wValue != USB_ENDPOINT_HALT)15631563+ if (ctrl.wValue != __constant_cpu_to_le16(15641564+ USB_ENDPOINT_HALT))15661565 goto stall;15671566 if (tmp)15681567 goku_clear_halt(&dev->ep[tmp]);···15761571 return;15771572 case USB_RECIP_DEVICE:15781573 /* device remote wakeup: always clear */15791579- if (ctrl.wValue != 1)15741574+ if (ctrl.wValue != __constant_cpu_to_le16(1))15801575 goto stall;15811576 VDBG(dev, "clear dev remote wakeup\n");15821577 goto succeed;···15941589#ifdef USB_TRACE15951590 VDBG(dev, "SETUP %02x.%02x v%04x i%04x l%04x\n",15961591 ctrl.bRequestType, ctrl.bRequest,15971597- ctrl.wValue, ctrl.wIndex, ctrl.wLength);15921592+ le16_to_cpu(ctrl.wValue), le16_to_cpu(ctrl.wIndex),15931593+ le16_to_cpu(ctrl.wLength));15981594#endif1599159516001596 /* hw wants to know when we're configured (or not) */16011597 dev->req_config = (ctrl.bRequest == USB_REQ_SET_CONFIGURATION16021598 && ctrl.bRequestType == USB_RECIP_DEVICE);16031599 if (unlikely(dev->req_config))16041604- dev->configured = (ctrl.wValue != 0);16001600+ dev->configured = (ctrl.wValue != __constant_cpu_to_le16(0));1605160116061602 /* delegate everything to the gadget driver.16071603 * it may respond after this irq handler returns.
+6-6
drivers/usb/gadget/inode.c
···417417 goto free1;418418419419 value = ep_io (data, kbuf, len);420420- VDEBUG (data->dev, "%s read %d OUT, status %d\n",421421- data->name, len, value);420420+ VDEBUG (data->dev, "%s read %zu OUT, status %d\n",421421+ data->name, len, (int) value);422422 if (value >= 0 && copy_to_user (buf, kbuf, value))423423 value = -EFAULT;424424···465465 }466466467467 value = ep_io (data, kbuf, len);468468- VDEBUG (data->dev, "%s write %d IN, status %d\n",469469- data->name, len, value);468468+ VDEBUG (data->dev, "%s write %zu IN, status %d\n",469469+ data->name, len, (int) value);470470free1:471471 up (&data->lock);472472 kfree (kbuf);···13181318 struct usb_request *req = dev->req;13191319 int value = -EOPNOTSUPP;13201320 struct usb_gadgetfs_event *event;13211321- u16 w_value = ctrl->wValue;13221322- u16 w_length = ctrl->wLength;13211321+ u16 w_value = le16_to_cpu(ctrl->wValue);13221322+ u16 w_length = le16_to_cpu(ctrl->wLength);1323132313241324 spin_lock (&dev->lock);13251325 dev->setup_abort = 0;
···11/*22 * linux/drivers/usb/gadget/pxa2xx_udc.c33- * Intel PXA2xx and IXP4xx on-chip full speed USB device controllers33+ * Intel PXA25x and IXP4xx on-chip full speed USB device controllers44 *55 * Copyright (C) 2002 Intrinsyc, Inc. (Frank Becker)66 * Copyright (C) 2003 Robert Schwebel, Pengutronix···636364646565/*6666- * This driver handles the USB Device Controller (UDC) in Intel's PXA 2xx6666+ * This driver handles the USB Device Controller (UDC) in Intel's PXA 25x6767 * series processors. The UDC for the IXP 4xx series is very similar.6868 * There are fifteen endpoints, in addition to ep0.6969 *···7979 * pxa250 a0/a1 b0/b1/b2 sure act like they're still there.8080 */81818282-#define DRIVER_VERSION "14-Dec-2003"8383-#define DRIVER_DESC "PXA 2xx USB Device Controller driver"8282+#define DRIVER_VERSION "4-May-2005"8383+#define DRIVER_DESC "PXA 25x USB Device Controller driver"848485858686static const char driver_name [] = "pxa2xx_udc";···290290static int pxa2xx_ep_disable (struct usb_ep *_ep)291291{292292 struct pxa2xx_ep *ep;293293+ unsigned long flags;293294294295 ep = container_of (_ep, struct pxa2xx_ep, ep);295296 if (!_ep || !ep->desc) {···298297 _ep ? ep->ep.name : NULL);299298 return -EINVAL;300299 }300300+ local_irq_save(flags);301301+301302 nuke (ep, -ESHUTDOWN);302303303304#ifdef USE_DMA···316313 ep->desc = NULL;317314 ep->stopped = 1;318315316316+ local_irq_restore(flags);319317 DBG(DBG_VERBOSE, "%s disabled\n", _ep->name);320318 return 0;321319}···975971 kick_dma(ep, req);976972#endif977973 /* can the FIFO can satisfy the request immediately? */978978- } else if ((ep->bEndpointAddress & USB_DIR_IN) != 0979979- && (*ep->reg_udccs & UDCCS_BI_TFS) != 0980980- && write_fifo(ep, req)) {981981- req = NULL;974974+ } else if ((ep->bEndpointAddress & USB_DIR_IN) != 0) {975975+ if ((*ep->reg_udccs & UDCCS_BI_TFS) != 0976976+ && write_fifo(ep, req))977977+ req = NULL;982978 } else if ((*ep->reg_udccs & UDCCS_BO_RFS) != 0983979 && read_fifo(ep, req)) {984980 req = NULL;···12941290 "%s version: %s\nGadget driver: %s\nHost %s\n\n",12951291 driver_name, DRIVER_VERSION SIZE_STR DMASTR,12961292 dev->driver ? dev->driver->driver.name : "(none)",12971297- is_usb_connected() ? "full speed" : "disconnected");12931293+ is_vbus_present() ? "full speed" : "disconnected");12981294 size -= t;12991295 next += t;13001296···13431339 next += t;13441340 }1345134113461346- if (!is_usb_connected() || !dev->driver)13421342+ if (!is_vbus_present() || !dev->driver)13471343 goto done;1348134413491345 t = scnprintf(next, size, "ep0 IN %lu/%lu, OUT %lu/%lu\nirqs %lu\n\n",···14581454 UFNRH = UFNRH_SIM;1459145514601456 /* if hardware supports it, disconnect from usb */14611461- make_usb_disappear();14571457+ pullup_off();1462145814631459 udc_clear_mask_UDCCR(UDCCR_UDE);14641460···15711567 UICR0 &= ~UICR0_IM0;1572156815731569 /* if hardware supports it, pullup D+ and wait for reset */15741574- let_usb_appear();15701570+ pullup_on();15751571}1576157215771573···20562052 if (unlikely(udccr & UDCCR_SUSIR)) {20572053 udc_ack_int_UDCCR(UDCCR_SUSIR);20582054 handled = 1;20592059- DBG(DBG_VERBOSE, "USB suspend%s\n", is_usb_connected()20552055+ DBG(DBG_VERBOSE, "USB suspend%s\n", is_vbus_present()20602056 ? "" : "+disconnect");2061205720622062- if (!is_usb_connected())20582058+ if (!is_vbus_present())20632059 stop_activity(dev, dev->driver);20642060 else if (dev->gadget.speed != USB_SPEED_UNKNOWN20652061 && dev->driver···20772073 if (dev->gadget.speed != USB_SPEED_UNKNOWN20782074 && dev->driver20792075 && dev->driver->resume20802080- && is_usb_connected())20762076+ && is_vbus_present())20812077 dev->driver->resume(&dev->gadget);20822078 }20832079···25132509 udc_disable(dev);25142510 udc_reinit(dev);2515251125162516- dev->vbus = is_usb_connected();25122512+ dev->vbus = is_vbus_present();2517251325182514 /* irq setup after old hardware state is cleaned up */25192515 retval = request_irq(IRQ_USB, pxa2xx_udc_irq,···2559255525602556 return 0;25612557}25582558+25592559+static void pxa2xx_udc_shutdown(struct device *_dev)25602560+{25612561+ pullup_off();25622562+}25632563+25622564static int __exit pxa2xx_udc_remove(struct device *_dev)25632565{25642566 struct pxa2xx_udc *dev = dev_get_drvdata(_dev);···26342624 .name = "pxa2xx-udc",26352625 .bus = &platform_bus_type,26362626 .probe = pxa2xx_udc_probe,26272627+ .shutdown = pxa2xx_udc_shutdown,26372628 .remove = __exit_p(pxa2xx_udc_remove),26382629 .suspend = pxa2xx_udc_suspend,26392630 .resume = pxa2xx_udc_resume,
+5-5
drivers/usb/gadget/pxa2xx_udc.h
···177177178178static struct pxa2xx_udc *the_controller;179179180180-/* one GPIO should be used to detect host disconnect */181181-static inline int is_usb_connected(void)180180+/* one GPIO should be used to detect VBUS from the host */181181+static inline int is_vbus_present(void)182182{183183 if (!the_controller->mach->udc_is_connected)184184 return 1;185185 return the_controller->mach->udc_is_connected();186186}187187188188-/* one GPIO should force the host to see this device (or not) */189189-static inline void make_usb_disappear(void)188188+/* one GPIO should control a D+ pullup, so host sees this device (or not) */189189+static inline void pullup_off(void)190190{191191 if (!the_controller->mach->udc_command)192192 return;193193 the_controller->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);194194}195195196196-static inline void let_usb_appear(void)196196+static inline void pullup_on(void)197197{198198 if (!the_controller->mach->udc_command)199199 return;
+269-246
drivers/usb/gadget/rndis.c
···414142424343#undef RNDIS_PM4444+#undef RNDIS_WAKEUP4445#undef VERBOSE45464647#include "rndis.h"···6160 } while (0)6261static int rndis_debug = 0;63626464-module_param (rndis_debug, bool, 0);6363+module_param (rndis_debug, int, 0);6564MODULE_PARM_DESC (rndis_debug, "enable debugging");66656766#else···7978static const __le32 rndis_driver_version = __constant_cpu_to_le32 (1);80798180/* Function Prototypes */8282-static int rndis_init_response (int configNr, rndis_init_msg_type *buf);8383-static int rndis_query_response (int configNr, rndis_query_msg_type *buf);8484-static int rndis_set_response (int configNr, rndis_set_msg_type *buf);8585-static int rndis_reset_response (int configNr, rndis_reset_msg_type *buf);8686-static int rndis_keepalive_response (int configNr, 8787- rndis_keepalive_msg_type *buf);8888-8981static rndis_resp_t *rndis_add_response (int configNr, u32 length);908291838484+/* supported OIDs */8585+static const u32 oid_supported_list [] = 8686+{8787+ /* the general stuff */8888+ OID_GEN_SUPPORTED_LIST,8989+ OID_GEN_HARDWARE_STATUS,9090+ OID_GEN_MEDIA_SUPPORTED,9191+ OID_GEN_MEDIA_IN_USE,9292+ OID_GEN_MAXIMUM_FRAME_SIZE,9393+ OID_GEN_LINK_SPEED,9494+ OID_GEN_TRANSMIT_BLOCK_SIZE,9595+ OID_GEN_RECEIVE_BLOCK_SIZE,9696+ OID_GEN_VENDOR_ID,9797+ OID_GEN_VENDOR_DESCRIPTION,9898+ OID_GEN_VENDOR_DRIVER_VERSION,9999+ OID_GEN_CURRENT_PACKET_FILTER,100100+ OID_GEN_MAXIMUM_TOTAL_SIZE,101101+ OID_GEN_MEDIA_CONNECT_STATUS,102102+ OID_GEN_PHYSICAL_MEDIUM,103103+#if 0104104+ OID_GEN_RNDIS_CONFIG_PARAMETER,105105+#endif106106+107107+ /* the statistical stuff */108108+ OID_GEN_XMIT_OK,109109+ OID_GEN_RCV_OK,110110+ OID_GEN_XMIT_ERROR,111111+ OID_GEN_RCV_ERROR,112112+ OID_GEN_RCV_NO_BUFFER,113113+#ifdef RNDIS_OPTIONAL_STATS114114+ OID_GEN_DIRECTED_BYTES_XMIT,115115+ OID_GEN_DIRECTED_FRAMES_XMIT,116116+ OID_GEN_MULTICAST_BYTES_XMIT,117117+ OID_GEN_MULTICAST_FRAMES_XMIT,118118+ OID_GEN_BROADCAST_BYTES_XMIT,119119+ OID_GEN_BROADCAST_FRAMES_XMIT,120120+ OID_GEN_DIRECTED_BYTES_RCV,121121+ OID_GEN_DIRECTED_FRAMES_RCV,122122+ OID_GEN_MULTICAST_BYTES_RCV,123123+ OID_GEN_MULTICAST_FRAMES_RCV,124124+ OID_GEN_BROADCAST_BYTES_RCV,125125+ OID_GEN_BROADCAST_FRAMES_RCV,126126+ OID_GEN_RCV_CRC_ERROR,127127+ OID_GEN_TRANSMIT_QUEUE_LENGTH,128128+#endif /* RNDIS_OPTIONAL_STATS */129129+130130+ /* mandatory 802.3 */131131+ /* the general stuff */132132+ OID_802_3_PERMANENT_ADDRESS,133133+ OID_802_3_CURRENT_ADDRESS,134134+ OID_802_3_MULTICAST_LIST,135135+ OID_802_3_MAC_OPTIONS,136136+ OID_802_3_MAXIMUM_LIST_SIZE,137137+138138+ /* the statistical stuff */139139+ OID_802_3_RCV_ERROR_ALIGNMENT,140140+ OID_802_3_XMIT_ONE_COLLISION,141141+ OID_802_3_XMIT_MORE_COLLISIONS,142142+#ifdef RNDIS_OPTIONAL_STATS143143+ OID_802_3_XMIT_DEFERRED,144144+ OID_802_3_XMIT_MAX_COLLISIONS,145145+ OID_802_3_RCV_OVERRUN,146146+ OID_802_3_XMIT_UNDERRUN,147147+ OID_802_3_XMIT_HEARTBEAT_FAILURE,148148+ OID_802_3_XMIT_TIMES_CRS_LOST,149149+ OID_802_3_XMIT_LATE_COLLISIONS,150150+#endif /* RNDIS_OPTIONAL_STATS */151151+152152+#ifdef RNDIS_PM153153+ /* PM and wakeup are mandatory for USB: */154154+155155+ /* power management */156156+ OID_PNP_CAPABILITIES,157157+ OID_PNP_QUERY_POWER,158158+ OID_PNP_SET_POWER,159159+160160+#ifdef RNDIS_WAKEUP161161+ /* wake up host */162162+ OID_PNP_ENABLE_WAKE_UP,163163+ OID_PNP_ADD_WAKE_UP_PATTERN,164164+ OID_PNP_REMOVE_WAKE_UP_PATTERN,165165+#endif /* RNDIS_WAKEUP */166166+#endif /* RNDIS_PM */167167+};168168+169169+92170/* NDIS Functions */9393-static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)171171+static int172172+gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,173173+ rndis_resp_t *r)94174{95175 int retval = -ENOTSUPP;9696- u32 length = 0;9797- __le32 *tmp;176176+ u32 length = 4; /* usually */177177+ __le32 *outbuf;98178 int i, count;99179 rndis_query_cmplt_type *resp;100180···183101 resp = (rndis_query_cmplt_type *) r->buf;184102185103 if (!resp) return -ENOMEM;186186-104104+105105+ if (buf_len && rndis_debug > 1) {106106+ DEBUG("query OID %08x value, len %d:\n", OID, buf_len);107107+ for (i = 0; i < buf_len; i += 16) {108108+ DEBUG ("%03d: %08x %08x %08x %08x\n", i,109109+ le32_to_cpup((__le32 *)&buf[i]),110110+ le32_to_cpup((__le32 *)&buf[i + 4]),111111+ le32_to_cpup((__le32 *)&buf[i + 8]),112112+ le32_to_cpup((__le32 *)&buf[i + 12]));113113+ }114114+ }115115+116116+ /* response goes here, right after the header */117117+ outbuf = (__le32 *) &resp[1];118118+ resp->InformationBufferOffset = __constant_cpu_to_le32 (16);119119+187120 switch (OID) {188121189122 /* general oids (table 4-1) */···208111 DEBUG ("%s: OID_GEN_SUPPORTED_LIST\n", __FUNCTION__);209112 length = sizeof (oid_supported_list);210113 count = length / sizeof (u32);211211- tmp = (__le32 *) ((u8 *)resp + 24);212114 for (i = 0; i < count; i++)213213- tmp[i] = cpu_to_le32 (oid_supported_list[i]);115115+ outbuf[i] = cpu_to_le32 (oid_supported_list[i]);214116 retval = 0;215117 break;216118217119 /* mandatory */218120 case OID_GEN_HARDWARE_STATUS:219121 DEBUG("%s: OID_GEN_HARDWARE_STATUS\n", __FUNCTION__);220220- length = 4;221122 /* Bogus question! 222123 * Hardware must be ready to receive high level protocols.223124 * BTW: 224125 * reddite ergo quae sunt Caesaris Caesari225126 * et quae sunt Dei Deo!226127 */227227- *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);128128+ *outbuf = __constant_cpu_to_le32 (0);228129 retval = 0;229130 break;230131231132 /* mandatory */232133 case OID_GEN_MEDIA_SUPPORTED:233134 DEBUG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__);234234- length = 4;235235- *((__le32 *) resp + 6) = cpu_to_le32 (236236- rndis_per_dev_params [configNr].medium);135135+ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium);237136 retval = 0;238137 break;239138240139 /* mandatory */241140 case OID_GEN_MEDIA_IN_USE:242141 DEBUG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__);243243- length = 4;244142 /* one medium, one transport... (maybe you do it better) */245245- *((__le32 *) resp + 6) = cpu_to_le32 (246246- rndis_per_dev_params [configNr].medium);143143+ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium);247144 retval = 0;248145 break;249146···245154 case OID_GEN_MAXIMUM_FRAME_SIZE:246155 DEBUG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__);247156 if (rndis_per_dev_params [configNr].dev) {248248- length = 4;249249- *((__le32 *) resp + 6) = cpu_to_le32 (157157+ *outbuf = cpu_to_le32 (250158 rndis_per_dev_params [configNr].dev->mtu);251251- retval = 0;252252- } else {253253- *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);254159 retval = 0;255160 }256161 break;257162258163 /* mandatory */259164 case OID_GEN_LINK_SPEED:260260-// DEBUG("%s: OID_GEN_LINK_SPEED\n", __FUNCTION__);261261- length = 4;165165+ if (rndis_debug > 1)166166+ DEBUG("%s: OID_GEN_LINK_SPEED\n", __FUNCTION__);262167 if (rndis_per_dev_params [configNr].media_state263263- == NDIS_MEDIA_STATE_DISCONNECTED)264264- *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);168168+ == NDIS_MEDIA_STATE_DISCONNECTED)169169+ *outbuf = __constant_cpu_to_le32 (0);265170 else266266- *((__le32 *) resp + 6) = cpu_to_le32 (171171+ *outbuf = cpu_to_le32 (267172 rndis_per_dev_params [configNr].speed);268173 retval = 0;269174 break;···268181 case OID_GEN_TRANSMIT_BLOCK_SIZE:269182 DEBUG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __FUNCTION__);270183 if (rndis_per_dev_params [configNr].dev) {271271- length = 4;272272- *((__le32 *) resp + 6) = cpu_to_le32 (184184+ *outbuf = cpu_to_le32 (273185 rndis_per_dev_params [configNr].dev->mtu);274186 retval = 0;275187 }···278192 case OID_GEN_RECEIVE_BLOCK_SIZE:279193 DEBUG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__);280194 if (rndis_per_dev_params [configNr].dev) {281281- length = 4;282282- *((__le32 *) resp + 6) = cpu_to_le32 (195195+ *outbuf = cpu_to_le32 (283196 rndis_per_dev_params [configNr].dev->mtu);284197 retval = 0;285198 }···287202 /* mandatory */288203 case OID_GEN_VENDOR_ID:289204 DEBUG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__);290290- length = 4;291291- *((__le32 *) resp + 6) = cpu_to_le32 (205205+ *outbuf = cpu_to_le32 (292206 rndis_per_dev_params [configNr].vendorID);293207 retval = 0;294208 break;···296212 case OID_GEN_VENDOR_DESCRIPTION:297213 DEBUG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __FUNCTION__);298214 length = strlen (rndis_per_dev_params [configNr].vendorDescr);299299- memcpy ((u8 *) resp + 24, 215215+ memcpy (outbuf,300216 rndis_per_dev_params [configNr].vendorDescr, length);301217 retval = 0;302218 break;303219304220 case OID_GEN_VENDOR_DRIVER_VERSION:305221 DEBUG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__);306306- length = 4;307222 /* Created as LE */308308- *((__le32 *) resp + 6) = rndis_driver_version;223223+ *outbuf = rndis_driver_version;309224 retval = 0;310225 break;311226312227 /* mandatory */313228 case OID_GEN_CURRENT_PACKET_FILTER:314229 DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__);315315- length = 4;316316- *((__le32 *) resp + 6) = cpu_to_le32 (317317- rndis_per_dev_params[configNr].filter);230230+ *outbuf = cpu_to_le32 (*rndis_per_dev_params[configNr].filter);318231 retval = 0;319232 break;320233321234 /* mandatory */322235 case OID_GEN_MAXIMUM_TOTAL_SIZE:323236 DEBUG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __FUNCTION__);324324- length = 4;325325- *((__le32 *) resp + 6) = __constant_cpu_to_le32(326326- RNDIS_MAX_TOTAL_SIZE);237237+ *outbuf = __constant_cpu_to_le32(RNDIS_MAX_TOTAL_SIZE);327238 retval = 0;328239 break;329240330241 /* mandatory */331242 case OID_GEN_MEDIA_CONNECT_STATUS:332332- DEBUG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__);333333- length = 4;334334- *((__le32 *) resp + 6) = cpu_to_le32 (335335- rndis_per_dev_params [configNr]243243+ if (rndis_debug > 1)244244+ DEBUG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__);245245+ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]336246 .media_state);337247 retval = 0;338248 break;339249340250 case OID_GEN_PHYSICAL_MEDIUM:341251 DEBUG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__);342342- length = 4;343343- *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);252252+ *outbuf = __constant_cpu_to_le32 (0);344253 retval = 0;345254 break;346255···343266 */344267 case OID_GEN_MAC_OPTIONS: /* from WinME */345268 DEBUG("%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__);346346- length = 4;347347- *((__le32 *) resp + 6) = __constant_cpu_to_le32(269269+ *outbuf = __constant_cpu_to_le32(348270 NDIS_MAC_OPTION_RECEIVE_SERIALIZED349271 | NDIS_MAC_OPTION_FULL_DUPLEX);350272 retval = 0;···353277354278 /* mandatory */355279 case OID_GEN_XMIT_OK:356356- DEBUG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__);280280+ if (rndis_debug > 1)281281+ DEBUG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__);357282 if (rndis_per_dev_params [configNr].stats) {358358- length = 4;359359- *((__le32 *) resp + 6) = cpu_to_le32 (283283+ *outbuf = cpu_to_le32 (360284 rndis_per_dev_params [configNr].stats->tx_packets - 361285 rndis_per_dev_params [configNr].stats->tx_errors -362286 rndis_per_dev_params [configNr].stats->tx_dropped);363363- retval = 0;364364- } else {365365- *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);366287 retval = 0;367288 }368289 break;369290370291 /* mandatory */371292 case OID_GEN_RCV_OK:372372- DEBUG("%s: OID_GEN_RCV_OK\n", __FUNCTION__);293293+ if (rndis_debug > 1)294294+ DEBUG("%s: OID_GEN_RCV_OK\n", __FUNCTION__);373295 if (rndis_per_dev_params [configNr].stats) {374374- length = 4;375375- *((__le32 *) resp + 6) = cpu_to_le32 (296296+ *outbuf = cpu_to_le32 (376297 rndis_per_dev_params [configNr].stats->rx_packets - 377298 rndis_per_dev_params [configNr].stats->rx_errors -378299 rndis_per_dev_params [configNr].stats->rx_dropped);379379- retval = 0;380380- } else {381381- *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);382300 retval = 0;383301 }384302 break;385303386304 /* mandatory */387305 case OID_GEN_XMIT_ERROR:388388- DEBUG("%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__);306306+ if (rndis_debug > 1)307307+ DEBUG("%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__);389308 if (rndis_per_dev_params [configNr].stats) {390390- length = 4;391391- *((__le32 *) resp + 6) = cpu_to_le32 (392392- rndis_per_dev_params [configNr]309309+ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]393310 .stats->tx_errors);394394- retval = 0;395395- } else {396396- *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);397311 retval = 0;398312 }399313 break;400314401315 /* mandatory */402316 case OID_GEN_RCV_ERROR:403403- DEBUG("%s: OID_GEN_RCV_ERROR\n", __FUNCTION__);317317+ if (rndis_debug > 1)318318+ DEBUG("%s: OID_GEN_RCV_ERROR\n", __FUNCTION__);404319 if (rndis_per_dev_params [configNr].stats) {405405- *((__le32 *) resp + 6) = cpu_to_le32 (406406- rndis_per_dev_params [configNr]320320+ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]407321 .stats->rx_errors);408408- retval = 0;409409- } else {410410- *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);411322 retval = 0;412323 }413324 break;···403340 case OID_GEN_RCV_NO_BUFFER:404341 DEBUG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__);405342 if (rndis_per_dev_params [configNr].stats) {406406- *((__le32 *) resp + 6) = cpu_to_le32 (407407- rndis_per_dev_params [configNr]343343+ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]408344 .stats->rx_dropped);409409- retval = 0;410410- } else {411411- *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);412345 retval = 0;413346 }414347 break;···418359 * divided by weight of Alpha Centauri419360 */420361 if (rndis_per_dev_params [configNr].stats) {421421- length = 4;422422- *((__le32 *) resp + 6) = cpu_to_le32 (362362+ *outbuf = cpu_to_le32 (423363 (rndis_per_dev_params [configNr]424364 .stats->tx_packets - 425365 rndis_per_dev_params [configNr]···427369 .stats->tx_dropped)428370 * 123);429371 retval = 0;430430- } else {431431- *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);432432- retval = 0;433372 }434373 break;435374···434379 DEBUG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __FUNCTION__);435380 /* dito */436381 if (rndis_per_dev_params [configNr].stats) {437437- length = 4;438438- *((__le32 *) resp + 6) = cpu_to_le32 (382382+ *outbuf = cpu_to_le32 (439383 (rndis_per_dev_params [configNr]440384 .stats->tx_packets - 441385 rndis_per_dev_params [configNr]···443389 .stats->tx_dropped)444390 / 123);445391 retval = 0;446446- } else {447447- *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);448448- retval = 0;449392 }450393 break;451394452395 case OID_GEN_MULTICAST_BYTES_XMIT:453396 DEBUG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__);454397 if (rndis_per_dev_params [configNr].stats) {455455- *((__le32 *) resp + 6) = cpu_to_le32 (456456- rndis_per_dev_params [configNr]398398+ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]457399 .stats->multicast*1234);458458- retval = 0;459459- } else {460460- *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);461400 retval = 0;462401 }463402 break;···458411 case OID_GEN_MULTICAST_FRAMES_XMIT:459412 DEBUG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__);460413 if (rndis_per_dev_params [configNr].stats) {461461- *((__le32 *) resp + 6) = cpu_to_le32 (462462- rndis_per_dev_params [configNr]414414+ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]463415 .stats->multicast);464464- retval = 0;465465- } else {466466- *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);467416 retval = 0;468417 }469418 break;···467424 case OID_GEN_BROADCAST_BYTES_XMIT:468425 DEBUG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__);469426 if (rndis_per_dev_params [configNr].stats) {470470- *((__le32 *) resp + 6) = cpu_to_le32 (471471- rndis_per_dev_params [configNr]427427+ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]472428 .stats->tx_packets/42*255);473473- retval = 0;474474- } else {475475- *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);476429 retval = 0;477430 }478431 break;···476437 case OID_GEN_BROADCAST_FRAMES_XMIT:477438 DEBUG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__);478439 if (rndis_per_dev_params [configNr].stats) {479479- *((__le32 *) resp + 6) = cpu_to_le32 (480480- rndis_per_dev_params [configNr]440440+ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]481441 .stats->tx_packets/42);482482- retval = 0;483483- } else {484484- *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);485442 retval = 0;486443 }487444 break;488445489446 case OID_GEN_DIRECTED_BYTES_RCV:490447 DEBUG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__);491491- *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);448448+ *outbuf = __constant_cpu_to_le32 (0);492449 retval = 0;493450 break;494451495452 case OID_GEN_DIRECTED_FRAMES_RCV:496453 DEBUG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__);497497- *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);454454+ *outbuf = __constant_cpu_to_le32 (0);498455 retval = 0;499456 break;500457501458 case OID_GEN_MULTICAST_BYTES_RCV:502459 DEBUG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__);503460 if (rndis_per_dev_params [configNr].stats) {504504- *((__le32 *) resp + 6) = cpu_to_le32 (505505- rndis_per_dev_params [configNr]461461+ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]506462 .stats->multicast * 1111);507507- retval = 0;508508- } else {509509- *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);510463 retval = 0;511464 }512465 break;···506475 case OID_GEN_MULTICAST_FRAMES_RCV:507476 DEBUG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__);508477 if (rndis_per_dev_params [configNr].stats) {509509- *((__le32 *) resp + 6) = cpu_to_le32 (510510- rndis_per_dev_params [configNr]478478+ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]511479 .stats->multicast);512512- retval = 0;513513- } else {514514- *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);515480 retval = 0;516481 }517482 break;···515488 case OID_GEN_BROADCAST_BYTES_RCV:516489 DEBUG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__);517490 if (rndis_per_dev_params [configNr].stats) {518518- *((__le32 *) resp + 6) = cpu_to_le32 (519519- rndis_per_dev_params [configNr]491491+ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]520492 .stats->rx_packets/42*255);521521- retval = 0;522522- } else {523523- *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);524493 retval = 0;525494 }526495 break;···524501 case OID_GEN_BROADCAST_FRAMES_RCV:525502 DEBUG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__);526503 if (rndis_per_dev_params [configNr].stats) {527527- *((__le32 *) resp + 6) = cpu_to_le32 (528528- rndis_per_dev_params [configNr]504504+ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]529505 .stats->rx_packets/42);530530- retval = 0;531531- } else {532532- *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);533506 retval = 0;534507 }535508 break;···533514 case OID_GEN_RCV_CRC_ERROR:534515 DEBUG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__);535516 if (rndis_per_dev_params [configNr].stats) {536536- *((__le32 *) resp + 6) = cpu_to_le32 (537537- rndis_per_dev_params [configNr]517517+ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]538518 .stats->rx_crc_errors);539539- retval = 0;540540- } else {541541- *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);542519 retval = 0;543520 }544521 break;545522546523 case OID_GEN_TRANSMIT_QUEUE_LENGTH:547524 DEBUG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__);548548- *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);525525+ *outbuf = __constant_cpu_to_le32 (0);549526 retval = 0;550527 break;551528#endif /* RNDIS_OPTIONAL_STATS */···553538 DEBUG("%s: OID_802_3_PERMANENT_ADDRESS\n", __FUNCTION__);554539 if (rndis_per_dev_params [configNr].dev) {555540 length = ETH_ALEN;556556- memcpy ((u8 *) resp + 24,541541+ memcpy (outbuf,557542 rndis_per_dev_params [configNr].host_mac,558543 length);559559- retval = 0;560560- } else {561561- *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);562544 retval = 0;563545 }564546 break;···565553 DEBUG("%s: OID_802_3_CURRENT_ADDRESS\n", __FUNCTION__);566554 if (rndis_per_dev_params [configNr].dev) {567555 length = ETH_ALEN;568568- memcpy ((u8 *) resp + 24,556556+ memcpy (outbuf,569557 rndis_per_dev_params [configNr].host_mac,570558 length);571559 retval = 0;···575563 /* mandatory */576564 case OID_802_3_MULTICAST_LIST:577565 DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);578578- length = 4;579566 /* Multicast base address only */580580- *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0xE0000000);567567+ *outbuf = __constant_cpu_to_le32 (0xE0000000);581568 retval = 0;582569 break;583570584571 /* mandatory */585572 case OID_802_3_MAXIMUM_LIST_SIZE:586573 DEBUG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__);587587- length = 4;588574 /* Multicast base address only */589589- *((__le32 *) resp + 6) = __constant_cpu_to_le32 (1);575575+ *outbuf = __constant_cpu_to_le32 (1);590576 retval = 0;591577 break;592578···597587 /* mandatory */598588 case OID_802_3_RCV_ERROR_ALIGNMENT:599589 DEBUG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __FUNCTION__);600600- if (rndis_per_dev_params [configNr].stats)601601- {602602- length = 4;603603- *((__le32 *) resp + 6) = cpu_to_le32 (604604- rndis_per_dev_params [configNr]590590+ if (rndis_per_dev_params [configNr].stats) {591591+ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]605592 .stats->rx_frame_errors);606593 retval = 0;607594 }···607600 /* mandatory */608601 case OID_802_3_XMIT_ONE_COLLISION:609602 DEBUG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__);610610- length = 4;611611- *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);603603+ *outbuf = __constant_cpu_to_le32 (0);612604 retval = 0;613605 break;614606615607 /* mandatory */616608 case OID_802_3_XMIT_MORE_COLLISIONS:617609 DEBUG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__);618618- length = 4;619619- *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);610610+ *outbuf = __constant_cpu_to_le32 (0);620611 retval = 0;621612 break;622613···660655 case OID_PNP_CAPABILITIES:661656 DEBUG("%s: OID_PNP_CAPABILITIES\n", __FUNCTION__);662657663663- /* just PM, and remote wakeup on link status change664664- * (not magic packet or pattern match)665665- */658658+ /* for now, no wakeup capabilities */666659 length = sizeof (struct NDIS_PNP_CAPABILITIES);667667- memset (resp, 0, length);668668- {669669- struct NDIS_PNP_CAPABILITIES *caps = (void *) resp;670670-671671- caps->Flags = NDIS_DEVICE_WAKE_UP_ENABLE;672672- caps->WakeUpCapabilities.MinLinkChangeWakeUp 673673- = NdisDeviceStateD3;674674-675675- /* FIXME then use usb_gadget_wakeup(), and676676- * set USB_CONFIG_ATT_WAKEUP in config desc677677- */678678- }660660+ memset(outbuf, 0, length);679661 retval = 0;680662 break;681663 case OID_PNP_QUERY_POWER:682682- DEBUG("%s: OID_PNP_QUERY_POWER\n", __FUNCTION__);683683- /* sure, handle any power state that maps to USB suspend */664664+ DEBUG("%s: OID_PNP_QUERY_POWER D%d\n", __FUNCTION__,665665+ le32_to_cpup((__le32 *) buf) - 1);666666+ /* only suspend is a real power state, and667667+ * it can't be entered by OID_PNP_SET_POWER...668668+ */669669+ length = 0;684670 retval = 0;685671 break;686672#endif···680684 printk (KERN_WARNING "%s: query unknown OID 0x%08X\n", 681685 __FUNCTION__, OID);682686 }687687+ if (retval < 0)688688+ length = 0;683689684684- resp->InformationBufferOffset = __constant_cpu_to_le32 (16);685690 resp->InformationBufferLength = cpu_to_le32 (length);686686- resp->MessageLength = cpu_to_le32 (24 + length);687687- r->length = 24 + length;691691+ r->length = length + sizeof *resp;692692+ resp->MessageLength = cpu_to_le32 (r->length);688693 return retval;689694}690695···702705 if (!resp)703706 return -ENOMEM;704707705705- DEBUG("set OID %08x value, len %d:\n", OID, buf_len);706706- for (i = 0; i < buf_len; i += 16) {707707- DEBUG ("%03d: "708708- " %02x %02x %02x %02x"709709- " %02x %02x %02x %02x"710710- " %02x %02x %02x %02x"711711- " %02x %02x %02x %02x"712712- "\n",713713- i,714714- buf[i], buf [i+1],715715- buf[i+2], buf[i+3],716716- buf[i+4], buf [i+5],717717- buf[i+6], buf[i+7],718718- buf[i+8], buf [i+9],719719- buf[i+10], buf[i+11],720720- buf[i+12], buf [i+13],721721- buf[i+14], buf[i+15]);708708+ if (buf_len && rndis_debug > 1) {709709+ DEBUG("set OID %08x value, len %d:\n", OID, buf_len);710710+ for (i = 0; i < buf_len; i += 16) {711711+ DEBUG ("%03d: %08x %08x %08x %08x\n", i,712712+ le32_to_cpup((__le32 *)&buf[i]),713713+ le32_to_cpup((__le32 *)&buf[i + 4]),714714+ le32_to_cpup((__le32 *)&buf[i + 8]),715715+ le32_to_cpup((__le32 *)&buf[i + 12]));716716+ }722717 }723718719719+ params = &rndis_per_dev_params [configNr];724720 switch (OID) {725721 case OID_GEN_CURRENT_PACKET_FILTER:726726- params = &rndis_per_dev_params [configNr];727727- retval = 0;728722729729- /* FIXME use these NDIS_PACKET_TYPE_* bitflags to730730- * set the cdc_filter; it's not RNDIS-specific723723+ /* these NDIS_PACKET_TYPE_* bitflags are shared with724724+ * cdc_filter; it's not RNDIS-specific731725 * NDIS_PACKET_TYPE_x == USB_CDC_PACKET_TYPE_x for x in:732726 * PROMISCUOUS, DIRECTED,733727 * MULTICAST, ALL_MULTICAST, BROADCAST734728 */735735- params->filter = le32_to_cpup((__le32 *)buf);729729+ *params->filter = (u16) le32_to_cpup((__le32 *)buf);736730 DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",737737- __FUNCTION__, params->filter);731731+ __FUNCTION__, *params->filter);738732739733 /* this call has a significant side effect: it's740734 * what makes the packet flow start and stop, like741735 * activating the CDC Ethernet altsetting.742736 */743743- if (params->filter) {737737+#ifdef RNDIS_PM738738+update_linkstate:739739+#endif740740+ retval = 0;741741+ if (*params->filter) {744742 params->state = RNDIS_DATA_INITIALIZED;745743 netif_carrier_on(params->dev);746744 if (netif_running(params->dev))···768776769777#ifdef RNDIS_PM770778 case OID_PNP_SET_POWER:771771- DEBUG ("OID_PNP_SET_POWER\n");772772- /* sure, handle any power state that maps to USB suspend */773773- retval = 0;779779+ /* The only real power state is USB suspend, and RNDIS requests780780+ * can't enter it; this one isn't really about power. After781781+ * resuming, Windows forces a reset, and then SET_POWER D0.782782+ * FIXME ... then things go batty; Windows wedges itself.783783+ */784784+ i = le32_to_cpup((__force __le32 *)buf);785785+ DEBUG("%s: OID_PNP_SET_POWER D%d\n", __FUNCTION__, i - 1);786786+ switch (i) {787787+ case NdisDeviceStateD0:788788+ *params->filter = params->saved_filter;789789+ goto update_linkstate;790790+ case NdisDeviceStateD3:791791+ case NdisDeviceStateD2:792792+ case NdisDeviceStateD1:793793+ params->saved_filter = *params->filter;794794+ retval = 0;795795+ break;796796+ }774797 break;775798776776- case OID_PNP_ENABLE_WAKE_UP:777777- /* always-connected ... */778778- DEBUG ("OID_PNP_ENABLE_WAKE_UP\n");779779- retval = 0;780780- break;781781-782782- // no PM resume patterns supported (specified where?)783783- // so OID_PNP_{ADD,REMOVE}_WAKE_UP_PATTERN always fails799799+#ifdef RNDIS_WAKEUP800800+ // no wakeup support advertised, so wakeup OIDs always fail:801801+ // - OID_PNP_ENABLE_WAKE_UP802802+ // - OID_PNP_{ADD,REMOVE}_WAKE_UP_PATTERN784803#endif804804+805805+#endif /* RNDIS_PM */785806786807 default:787808 printk (KERN_WARNING "%s: set unknown OID 0x%08X, size %d\n", ···816811 if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP;817812818813 r = rndis_add_response (configNr, sizeof (rndis_init_cmplt_type));819819-820820- if (!r) return -ENOMEM;821821-814814+ if (!r)815815+ return -ENOMEM;822816 resp = (rndis_init_cmplt_type *) r->buf;823823-824824- if (!resp) return -ENOMEM;825817826818 resp->MessageType = __constant_cpu_to_le32 (827819 REMOTE_NDIS_INITIALIZE_CMPLT);···859857 * oid_supported_list is the largest answer 860858 */861859 r = rndis_add_response (configNr, sizeof (oid_supported_list));862862-863863- if (!r) return -ENOMEM;860860+ if (!r)861861+ return -ENOMEM;864862 resp = (rndis_query_cmplt_type *) r->buf;865863866866- if (!resp) return -ENOMEM;867867-868864 resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_QUERY_CMPLT);869869- resp->MessageLength = __constant_cpu_to_le32 (24);870865 resp->RequestID = buf->RequestID; /* Still LE in msg buffer */871871-872872- if (gen_ndis_query_resp (configNr, le32_to_cpu (buf->OID), r)) {866866+867867+ if (gen_ndis_query_resp (configNr, le32_to_cpu (buf->OID),868868+ le32_to_cpu(buf->InformationBufferOffset)869869+ + 8 + (u8 *) buf,870870+ le32_to_cpu(buf->InformationBufferLength),871871+ r)) {873872 /* OID not supported */874873 resp->Status = __constant_cpu_to_le32 (875874 RNDIS_STATUS_NOT_SUPPORTED);875875+ resp->MessageLength = __constant_cpu_to_le32 (sizeof *resp);876876 resp->InformationBufferLength = __constant_cpu_to_le32 (0);877877 resp->InformationBufferOffset = __constant_cpu_to_le32 (0);878878 } else···893889 rndis_resp_t *r;894890895891 r = rndis_add_response (configNr, sizeof (rndis_set_cmplt_type));896896-897897- if (!r) return -ENOMEM;892892+ if (!r)893893+ return -ENOMEM;898894 resp = (rndis_set_cmplt_type *) r->buf;899899- if (!resp) return -ENOMEM;900895901896 BufLength = le32_to_cpu (buf->InformationBufferLength);902897 BufOffset = le32_to_cpu (buf->InformationBufferOffset);···933930 rndis_resp_t *r;934931935932 r = rndis_add_response (configNr, sizeof (rndis_reset_cmplt_type));936936-937937- if (!r) return -ENOMEM;933933+ if (!r)934934+ return -ENOMEM;938935 resp = (rndis_reset_cmplt_type *) r->buf;939939- if (!resp) return -ENOMEM;940936941937 resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_RESET_CMPLT);942938 resp->MessageLength = __constant_cpu_to_le32 (16);···959957 /* host "should" check only in RNDIS_DATA_INITIALIZED state */960958961959 r = rndis_add_response (configNr, sizeof (rndis_keepalive_cmplt_type));960960+ if (!r)961961+ return -ENOMEM;962962 resp = (rndis_keepalive_cmplt_type *) r->buf;963963- if (!resp) return -ENOMEM;964963965964 resp->MessageType = __constant_cpu_to_le32 (966965 REMOTE_NDIS_KEEPALIVE_CMPLT);···990987991988 r = rndis_add_response (configNr, 992989 sizeof (rndis_indicate_status_msg_type));993993- if (!r) return -ENOMEM;994994-990990+ if (!r)991991+ return -ENOMEM;995992 resp = (rndis_indicate_status_msg_type *) r->buf;996996- if (!resp) return -ENOMEM;997993998994 resp->MessageType = __constant_cpu_to_le32 (999995 REMOTE_NDIS_INDICATE_STATUS_MSG);···10231021 RNDIS_STATUS_MEDIA_DISCONNECT);10241022}1025102310241024+void rndis_uninit (int configNr)10251025+{10261026+ u8 *buf;10271027+ u32 length;10281028+10291029+ if (configNr >= RNDIS_MAX_CONFIGS)10301030+ return;10311031+ rndis_per_dev_params [configNr].used = 0;10321032+ rndis_per_dev_params [configNr].state = RNDIS_UNINITIALIZED;10331033+10341034+ /* drain the response queue */10351035+ while ((buf = rndis_get_next_response(configNr, &length)))10361036+ rndis_free_response(configNr, buf);10371037+}10381038+10261039void rndis_set_host_mac (int configNr, const u8 *addr)10271040{10281041 rndis_per_dev_params [configNr].host_mac = addr;···10631046 return -ENOTSUPP;10641047 params = &rndis_per_dev_params [configNr];1065104810491049+ /* NOTE: RNDIS is *EXTREMELY* chatty ... Windows constantly polls for10501050+ * rx/tx statistics and link status, in addition to KEEPALIVE traffic10511051+ * and normal HC level polling to see if there's any IN traffic.10521052+ */10531053+10661054 /* For USB: responses may take up to 10 seconds */10671067- switch (MsgType)10681068- {10551055+ switch (MsgType) {10691056 case REMOTE_NDIS_INITIALIZE_MSG:10701057 DEBUG("%s: REMOTE_NDIS_INITIALIZE_MSG\n", 10711058 __FUNCTION__ );···1103108211041083 case REMOTE_NDIS_KEEPALIVE_MSG:11051084 /* For USB: host does this every 5 seconds */11061106-#ifdef VERBOSE11071107- DEBUG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n", 11081108- __FUNCTION__ );11091109-#endif10851085+ if (rndis_debug > 1)10861086+ DEBUG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n", 10871087+ __FUNCTION__ );11101088 return rndis_keepalive_response (configNr,11111089 (rndis_keepalive_msg_type *) 11121090 buf);···11721152}1173115311741154int rndis_set_param_dev (u8 configNr, struct net_device *dev, 11751175- struct net_device_stats *stats)11551155+ struct net_device_stats *stats,11561156+ u16 *cdc_filter)11761157{11771158 DEBUG("%s:\n", __FUNCTION__ );11781159 if (!dev || !stats) return -1;···1181116011821161 rndis_per_dev_params [configNr].dev = dev;11831162 rndis_per_dev_params [configNr].stats = stats;11631163+ rndis_per_dev_params [configNr].filter = cdc_filter;1184116411851165 return 0;11861166}···1200117812011179int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed)12021180{12031203- DEBUG("%s:\n", __FUNCTION__ );11811181+ DEBUG("%s: %u %u\n", __FUNCTION__, medium, speed);12041182 if (configNr >= RNDIS_MAX_CONFIGS) return -1;1205118312061184 rndis_per_dev_params [configNr].medium = medium;···12641242{12651243 rndis_resp_t *r;1266124412451245+ /* NOTE: this gets copied into ether.c USB_BUFSIZ bytes ... */12671246 r = kmalloc (sizeof (rndis_resp_t) + length, GFP_ATOMIC);12681247 if (!r) return NULL;12691248
···300300 u8 type, unsigned int index, int is_otg);301301302302static struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned int len,303303- int kmalloc_flags);303303+ unsigned kmalloc_flags);304304static void gs_free_req(struct usb_ep *ep, struct usb_request *req);305305306306static struct gs_req_entry *gs_alloc_req_entry(struct usb_ep *ep, unsigned len,307307- int kmalloc_flags);307307+ unsigned kmalloc_flags);308308static void gs_free_req_entry(struct usb_ep *ep, struct gs_req_entry *req);309309310310-static int gs_alloc_ports(struct gs_dev *dev, int kmalloc_flags);310310+static int gs_alloc_ports(struct gs_dev *dev, unsigned kmalloc_flags);311311static void gs_free_ports(struct gs_dev *dev);312312313313/* circular buffer */314314-static struct gs_buf *gs_buf_alloc(unsigned int size, int kmalloc_flags);314314+static struct gs_buf *gs_buf_alloc(unsigned int size, unsigned kmalloc_flags);315315static void gs_buf_free(struct gs_buf *gb);316316static void gs_buf_clear(struct gs_buf *gb);317317static unsigned int gs_buf_data_avail(struct gs_buf *gb);···16071607 int ret = -EOPNOTSUPP;16081608 struct gs_dev *dev = get_gadget_data(gadget);16091609 struct usb_request *req = dev->dev_ctrl_req;16101610- u16 wIndex = ctrl->wIndex;16111611- u16 wValue = ctrl->wValue;16121612- u16 wLength = ctrl->wLength;16101610+ u16 wIndex = le16_to_cpu(ctrl->wIndex);16111611+ u16 wValue = le16_to_cpu(ctrl->wValue);16121612+ u16 wLength = le16_to_cpu(ctrl->wLength);1613161316141614 switch (ctrl->bRequestType & USB_TYPE_MASK) {16151615 case USB_TYPE_STANDARD:···16511651 int ret = -EOPNOTSUPP;16521652 struct gs_dev *dev = get_gadget_data(gadget);16531653 struct usb_request *req = dev->dev_ctrl_req;16541654- u16 wIndex = ctrl->wIndex;16551655- u16 wValue = ctrl->wValue;16561656- u16 wLength = ctrl->wLength;16541654+ u16 wIndex = le16_to_cpu(ctrl->wIndex);16551655+ u16 wValue = le16_to_cpu(ctrl->wValue);16561656+ u16 wLength = le16_to_cpu(ctrl->wLength);1657165716581658 switch (ctrl->bRequest) {16591659 case USB_REQ_GET_DESCRIPTOR:···17821782 struct gs_dev *dev = get_gadget_data(gadget);17831783 struct gs_port *port = dev->dev_port[0]; /* ACM only has one port */17841784 struct usb_request *req = dev->dev_ctrl_req;17851785- u16 wIndex = ctrl->wIndex;17861786- u16 wValue = ctrl->wValue;17871787- u16 wLength = ctrl->wLength;17851785+ u16 wIndex = le16_to_cpu(ctrl->wIndex);17861786+ u16 wValue = le16_to_cpu(ctrl->wValue);17871787+ u16 wLength = le16_to_cpu(ctrl->wLength);1788178817891789 switch (ctrl->bRequest) {17901790 case USB_CDC_REQ_SET_LINE_CODING:···21192119 * Allocate a usb_request and its buffer. Returns a pointer to the21202120 * usb_request or NULL if there is an error.21212121 */21222122-static struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned int len, int kmalloc_flags)21222122+static struct usb_request *21232123+gs_alloc_req(struct usb_ep *ep, unsigned int len, unsigned kmalloc_flags)21232124{21242125 struct usb_request *req;21252126···21602159 * Allocates a request and its buffer, using the given21612160 * endpoint, buffer len, and kmalloc flags.21622161 */21632163-static struct gs_req_entry *gs_alloc_req_entry(struct usb_ep *ep, unsigned len, int kmalloc_flags)21622162+static struct gs_req_entry *21632163+gs_alloc_req_entry(struct usb_ep *ep, unsigned len, unsigned kmalloc_flags)21642164{21652165 struct gs_req_entry *req;21662166···22022200 *22032201 * The device lock is normally held when calling this function.22042202 */22052205-static int gs_alloc_ports(struct gs_dev *dev, int kmalloc_flags)22032203+static int gs_alloc_ports(struct gs_dev *dev, unsigned kmalloc_flags)22062204{22072205 int i;22082206 struct gs_port *port;···22842282 *22852283 * Allocate a circular buffer and all associated memory.22862284 */22872287-static struct gs_buf *gs_buf_alloc(unsigned int size, int kmalloc_flags)22852285+static struct gs_buf *gs_buf_alloc(unsigned int size, unsigned kmalloc_flags)22882286{22892287 struct gs_buf *gb;22902288
+3-3
drivers/usb/gadget/zero.c
···919919 struct zero_dev *dev = get_gadget_data (gadget);920920 struct usb_request *req = dev->req;921921 int value = -EOPNOTSUPP;922922- u16 w_index = ctrl->wIndex;923923- u16 w_value = ctrl->wValue;924924- u16 w_length = ctrl->wLength;922922+ u16 w_index = le16_to_cpu(ctrl->wIndex);923923+ u16 w_value = le16_to_cpu(ctrl->wValue);924924+ u16 w_length = le16_to_cpu(ctrl->wLength);925925926926 /* usually this stores reply data in the pre-allocated ep0 buffer,927927 * but config change events will reconfigure hardware.
+13
drivers/usb/host/Kconfig
···49495050 This supports the EHCI implementation from TransDimension Inc.51515252+config USB_ISP116X_HCD5353+ tristate "ISP116X HCD support"5454+ depends on USB5555+ default N5656+ ---help---5757+ The ISP1160 and ISP1161 chips are USB host controllers. Enable this5858+ option if your board has this chip. If unsure, say N.5959+6060+ This driver does not support isochronous transfers.6161+6262+ To compile this driver as a module, choose M here: the6363+ module will be called isp116x-hcd.6464+5265config USB_OHCI_HCD5366 tristate "OHCI HCD support"5467 depends on USB && USB_ARCH_HAS_OHCI
···254254 }255255256256 return scnprintf (buf, len,257257- "%s%sport %d status %06x%s%s sig=%s %s%s%s%s%s%s%s%s%s",257257+ "%s%sport %d status %06x%s%s sig=%s%s%s%s%s%s%s%s%s%s",258258 label, label [0] ? " " : "", port, status,259259 (status & PORT_POWER) ? " POWER" : "",260260 (status & PORT_OWNER) ? " OWNER" : "",···644644 if (bus->controller->power.power_state) {645645 size = scnprintf (next, size,646646 "bus %s, device %s (driver " DRIVER_VERSION ")\n"647647+ "%s\n"647648 "SUSPENDED (no register access)\n",648649 hcd->self.controller->bus->name,649649- hcd->self.controller->bus_id);650650+ hcd->self.controller->bus_id,651651+ hcd->product_desc);650652 goto done;651653 }652654···656654 i = HC_VERSION(readl (&ehci->caps->hc_capbase));657655 temp = scnprintf (next, size,658656 "bus %s, device %s (driver " DRIVER_VERSION ")\n"657657+ "%s\n"659658 "EHCI %x.%02x, hcd state %d\n",660659 hcd->self.controller->bus->name,661660 hcd->self.controller->bus_id,661661+ hcd->product_desc,662662 i >> 8, i & 0x0ff, hcd->state);663663 size -= temp;664664 next += temp;665665+666666+#ifdef CONFIG_PCI667667+ /* EHCI 0.96 and later may have "extended capabilities" */668668+ if (hcd->self.controller->bus == &pci_bus_type) {669669+ struct pci_dev *pdev;670670+ u32 offset, cap, cap2;671671+ unsigned count = 256/4;672672+673673+ pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller);674674+ offset = HCC_EXT_CAPS (readl (&ehci->caps->hcc_params));675675+ while (offset && count--) {676676+ pci_read_config_dword (pdev, offset, &cap);677677+ switch (cap & 0xff) {678678+ case 1:679679+ temp = scnprintf (next, size,680680+ "ownership %08x%s%s\n", cap,681681+ (cap & (1 << 24)) ? " linux" : "",682682+ (cap & (1 << 16)) ? " firmware" : "");683683+ size -= temp;684684+ next += temp;685685+686686+ offset += 4;687687+ pci_read_config_dword (pdev, offset, &cap2);688688+ temp = scnprintf (next, size,689689+ "SMI sts/enable 0x%08x\n", cap2);690690+ size -= temp;691691+ next += temp;692692+ break;693693+ case 0: /* illegal reserved capability */694694+ cap = 0;695695+ /* FALLTHROUGH */696696+ default: /* unknown */697697+ break;698698+ }699699+ temp = (cap >> 8) & 0xff;700700+ }701701+ }702702+#endif665703666704 // FIXME interpret both types of params667705 i = readl (&ehci->caps->hcs_params);···738696 size -= temp;739697 next += temp;740698741741- for (i = 0; i < HCS_N_PORTS (ehci->hcs_params); i++) {742742- temp = dbg_port_buf (scratch, sizeof scratch, label, i + 1,743743- readl (&ehci->regs->port_status [i]));699699+ for (i = 1; i <= HCS_N_PORTS (ehci->hcs_params); i++) {700700+ temp = dbg_port_buf (scratch, sizeof scratch, label, i,701701+ readl (&ehci->regs->port_status [i - 1]));744702 temp = scnprintf (next, size, fmt, temp, scratch);745703 size -= temp;746704 next += temp;705705+ if (i == HCS_DEBUG_PORT(ehci->hcs_params) && ehci->debug) {706706+ temp = scnprintf (next, size,707707+ " debug control %08x\n",708708+ readl (&ehci->debug->control));709709+ size -= temp;710710+ next += temp;711711+ }747712 }748713749714 if (ehci->reclaim) {
+14-44
drivers/usb/host/ehci-hcd.c
···304304 */305305static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap)306306{307307+ struct pci_dev *pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller);308308+309309+ /* always say Linux will own the hardware */310310+ pci_write_config_byte(pdev, where + 3, 1);311311+312312+ /* maybe wait a while for BIOS to respond */307313 if (cap & (1 << 16)) {308314 int msec = 5000;309309- struct pci_dev *pdev =310310- to_pci_dev(ehci_to_hcd(ehci)->self.controller);311315312312- /* request handoff to OS */313313- cap |= 1 << 24;314314- pci_write_config_dword(pdev, where, cap);315315-316316- /* and wait a while for it to happen */317316 do {318317 msleep(10);319318 msec -= 10;320319 pci_read_config_dword(pdev, where, &cap);321320 } while ((cap & (1 << 16)) && msec);322321 if (cap & (1 << 16)) {323323- ehci_err (ehci, "BIOS handoff failed (%d, %04x)\n",322322+ ehci_err(ehci, "BIOS handoff failed (%d, %08x)\n",324323 where, cap);325324 // some BIOS versions seem buggy...326325 // return 1;327326 ehci_warn (ehci, "continuing after BIOS bug...\n");328328- return 0;329329- } 330330- ehci_dbg (ehci, "BIOS handoff succeeded\n");327327+ /* disable all SMIs, and clear "BIOS owns" flag */328328+ pci_write_config_dword(pdev, where + 4, 0);329329+ pci_write_config_byte(pdev, where + 2, 0);330330+ } else331331+ ehci_dbg(ehci, "BIOS handoff succeeded\n");331332 }332333 return 0;333334}···493492{494493 struct ehci_hcd *ehci = hcd_to_ehci (hcd);495494 u32 temp;496496- struct usb_device *udev;497497- struct usb_bus *bus;498495 int retval;499496 u32 hcc_params;500497 u8 sbrn = 0;···587588 writel (0, &ehci->regs->segment);588589#if 0589590// this is deeply broken on almost all architectures590590- if (!pci_set_dma_mask (to_pci_dev(hcd->self.controller), 0xffffffffffffffffULL))591591- ehci_info (ehci, "enabled 64bit PCI DMA\n");591591+ if (!dma_set_mask (hcd->self.controller, DMA_64BIT_MASK))592592+ ehci_info (ehci, "enabled 64bit DMA\n");592593#endif593594 }594595···630631631632 /* set async sleep time = 10 us ... ? */632633633633- /* wire up the root hub */634634- bus = hcd_to_bus (hcd);635635- udev = first ? usb_alloc_dev (NULL, bus, 0) : bus->root_hub;636636- if (!udev) {637637-done2:638638- ehci_mem_cleanup (ehci);639639- return -ENOMEM;640640- }641641- udev->speed = USB_SPEED_HIGH;642642- udev->state = first ? USB_STATE_ATTACHED : USB_STATE_CONFIGURED;643643-644634 /*645635 * Start, enabling full USB 2.0 functionality ... usb 1.1 devices646636 * are explicitly handed to companion controller(s), so no TT is···651663 ((sbrn & 0xf0)>>4), (sbrn & 0x0f),652664 first ? "initialized" : "restarted",653665 temp >> 8, temp & 0xff, DRIVER_VERSION);654654-655655- /*656656- * From here on, khubd concurrently accesses the root657657- * hub; drivers will be talking to enumerated devices.658658- * (On restart paths, khubd already knows about the root659659- * hub and could find work as soon as we wrote FLAG_CF.)660660- *661661- * Before this point the HC was idle/ready. After, khubd662662- * and device drivers may start it running.663663- */664664- if (first && usb_hcd_register_root_hub (udev, hcd) != 0) {665665- if (hcd->state == HC_STATE_RUNNING)666666- ehci_quiesce (ehci);667667- ehci_reset (ehci);668668- usb_put_dev (udev); 669669- retval = -ENODEV;670670- goto done2;671671- }672666673667 writel (INTR_MASK, &ehci->regs->intr_enable); /* Turn On Interrupts */674668
+1-1
drivers/usb/host/ehci-hub.c
···11/*22- * Copyright (c) 2001-2002 by David Brownell22+ * Copyright (C) 2001-2004 by David Brownell33 * 44 * This program is free software; you can redistribute it and/or modify it55 * under the terms of the GNU General Public License as published by the
+1-1
drivers/usb/host/ehci-q.c
···11/*22- * Copyright (c) 2001-2002 by David Brownell22+ * Copyright (C) 2001-2004 by David Brownell33 * 44 * This program is free software; you can redistribute it and/or modify it55 * under the terms of the GNU General Public License as published by the
+7-10
drivers/usb/host/ehci-sched.c
···637637{638638 struct ehci_iso_stream *stream;639639640640- stream = kmalloc(sizeof *stream, mem_flags);640640+ stream = kcalloc(1, sizeof *stream, mem_flags);641641 if (likely (stream != NULL)) {642642- memset (stream, 0, sizeof(*stream));643642 INIT_LIST_HEAD(&stream->td_list);644643 INIT_LIST_HEAD(&stream->free_list);645644 stream->next_uframe = -1;···893894 trans |= length << 16;894895 uframe->transaction = cpu_to_le32 (trans);895896896896- /* might need to cross a buffer page within a td */897897+ /* might need to cross a buffer page within a uframe */897898 uframe->bufp = (buf & ~(u64)0x0fff);898899 buf += length;899900 if (unlikely ((uframe->bufp != (buf & ~(u64)0x0fff))))···11931194{11941195 int i;1195119611971197+ /* it's been recently zeroed */11961198 itd->hw_next = EHCI_LIST_END;11971199 itd->hw_bufp [0] = stream->buf0;11981200 itd->hw_bufp [1] = stream->buf1;···12101210 struct ehci_itd *itd,12111211 struct ehci_iso_sched *iso_sched,12121212 unsigned index,12131213- u16 uframe,12141214- int first12131213+ u16 uframe12151214)12161215{12171216 struct ehci_iso_packet *uf = &iso_sched->packet [index];···12271228 itd->hw_bufp_hi [pg] |= cpu_to_le32 ((u32)(uf->bufp >> 32));1228122912291230 /* iso_frame_desc[].offset must be strictly increasing */12301230- if (unlikely (!first && uf->cross)) {12311231+ if (unlikely (uf->cross)) {12311232 u64 bufp = uf->bufp + 4096;12321233 itd->pg = ++pg;12331234 itd->hw_bufp [pg] |= cpu_to_le32 (bufp & ~(u32)0);···12561257 struct ehci_iso_stream *stream12571258)12581259{12591259- int packet, first = 1;12601260+ int packet;12601261 unsigned next_uframe, uframe, frame;12611262 struct ehci_iso_sched *iso_sched = urb->hcpriv;12621263 struct ehci_itd *itd;···12891290 list_move_tail (&itd->itd_list, &stream->td_list);12901291 itd->stream = iso_stream_get (stream);12911292 itd->urb = usb_get_urb (urb);12921292- first = 1;12931293 itd_init (stream, itd);12941294 }12951295···12961298 frame = next_uframe >> 3;1297129912981300 itd->usecs [uframe] = stream->usecs;12991299- itd_patch (itd, iso_sched, packet, uframe, first);13001300- first = 0;13011301+ itd_patch (itd, iso_sched, packet, uframe);1301130213021303 next_uframe += stream->interval;13031304 stream->depth += stream->interval;
+1875
drivers/usb/host/isp116x-hcd.c
···11+/*22+ * ISP116x HCD (Host Controller Driver) for USB.33+ *44+ * Derived from the SL811 HCD, rewritten for ISP116x.55+ * Copyright (C) 2005 Olav Kongas <ok@artecdesign.ee>66+ *77+ * Portions:88+ * Copyright (C) 2004 Psion Teklogix (for NetBook PRO)99+ * Copyright (C) 2004 David Brownell1010+ *1111+ * Periodic scheduling is based on Roman's OHCI code1212+ * Copyright (C) 1999 Roman Weissgaerber1313+ *1414+ */1515+1616+/*1717+ * The driver basically works. A number of people have used it with a range1818+ * of devices.1919+ *2020+ *The driver passes all usbtests 1-14.2121+ *2222+ * Suspending/resuming of root hub via sysfs works. Remote wakeup works too.2323+ * And suspending/resuming of platform device works too. Suspend/resume2424+ * via HCD operations vector is not implemented.2525+ *2626+ * Iso transfer support is not implemented. Adding this would include2727+ * implementing recovery from the failure to service the processed ITL2828+ * fifo ram in time, which will involve chip reset.2929+ *3030+ * TODO:3131+ + More testing of suspend/resume.3232+*/3333+3434+/*3535+ ISP116x chips require certain delays between accesses to its3636+ registers. The following timing options exist.3737+3838+ 1. Configure your memory controller (the best)3939+ 2. Implement platform-specific delay function possibly4040+ combined with configuring the memory controller; see4141+ include/linux/usb-isp116x.h for more info. Some broken4242+ memory controllers line LH7A400 SMC need this. Also,4343+ uncomment for that to work the following4444+ USE_PLATFORM_DELAY macro.4545+ 3. Use ndelay (easiest, poorest). For that, uncomment4646+ the following USE_NDELAY macro.4747+*/4848+#define USE_PLATFORM_DELAY4949+//#define USE_NDELAY5050+5151+//#define DEBUG5252+//#define VERBOSE5353+/* Transfer descriptors. See dump_ptd() for printout format */5454+//#define PTD_TRACE5555+/* enqueuing/finishing log of urbs */5656+//#define URB_TRACE5757+5858+#include <linux/config.h>5959+#include <linux/module.h>6060+#include <linux/moduleparam.h>6161+#include <linux/kernel.h>6262+#include <linux/delay.h>6363+#include <linux/ioport.h>6464+#include <linux/sched.h>6565+#include <linux/slab.h>6666+#include <linux/smp_lock.h>6767+#include <linux/errno.h>6868+#include <linux/init.h>6969+#include <linux/list.h>7070+#include <linux/interrupt.h>7171+#include <linux/usb.h>7272+#include <linux/usb_isp116x.h>7373+7474+#include <asm/io.h>7575+#include <asm/irq.h>7676+#include <asm/system.h>7777+#include <asm/byteorder.h>7878+7979+#ifndef DEBUG8080+# define STUB_DEBUG_FILE8181+#endif8282+8383+#include "../core/hcd.h"8484+#include "isp116x.h"8585+8686+#define DRIVER_VERSION "08 Apr 2005"8787+#define DRIVER_DESC "ISP116x USB Host Controller Driver"8888+8989+MODULE_DESCRIPTION(DRIVER_DESC);9090+MODULE_LICENSE("GPL");9191+9292+static const char hcd_name[] = "isp116x-hcd";9393+9494+/*-----------------------------------------------------------------*/9595+9696+/*9797+ Write len bytes to fifo, pad till 32-bit boundary9898+ */9999+static void write_ptddata_to_fifo(struct isp116x *isp116x, void *buf, int len)100100+{101101+ u8 *dp = (u8 *) buf;102102+ u16 *dp2 = (u16 *) buf;103103+ u16 w;104104+ int quot = len % 4;105105+106106+ if ((unsigned long)dp2 & 1) {107107+ /* not aligned */108108+ for (; len > 1; len -= 2) {109109+ w = *dp++;110110+ w |= *dp++ << 8;111111+ isp116x_raw_write_data16(isp116x, w);112112+ }113113+ if (len)114114+ isp116x_write_data16(isp116x, (u16) * dp);115115+ } else {116116+ /* aligned */117117+ for (; len > 1; len -= 2)118118+ isp116x_raw_write_data16(isp116x, *dp2++);119119+ if (len)120120+ isp116x_write_data16(isp116x, 0xff & *((u8 *) dp2));121121+ }122122+ if (quot == 1 || quot == 2)123123+ isp116x_raw_write_data16(isp116x, 0);124124+}125125+126126+/*127127+ Read len bytes from fifo and then read till 32-bit boundary.128128+ */129129+static void read_ptddata_from_fifo(struct isp116x *isp116x, void *buf, int len)130130+{131131+ u8 *dp = (u8 *) buf;132132+ u16 *dp2 = (u16 *) buf;133133+ u16 w;134134+ int quot = len % 4;135135+136136+ if ((unsigned long)dp2 & 1) {137137+ /* not aligned */138138+ for (; len > 1; len -= 2) {139139+ w = isp116x_raw_read_data16(isp116x);140140+ *dp++ = w & 0xff;141141+ *dp++ = (w >> 8) & 0xff;142142+ }143143+ if (len)144144+ *dp = 0xff & isp116x_read_data16(isp116x);145145+ } else {146146+ /* aligned */147147+ for (; len > 1; len -= 2)148148+ *dp2++ = isp116x_raw_read_data16(isp116x);149149+ if (len)150150+ *(u8 *) dp2 = 0xff & isp116x_read_data16(isp116x);151151+ }152152+ if (quot == 1 || quot == 2)153153+ isp116x_raw_read_data16(isp116x);154154+}155155+156156+/*157157+ Write ptd's and data for scheduled transfers into158158+ the fifo ram. Fifo must be empty and ready.159159+*/160160+static void pack_fifo(struct isp116x *isp116x)161161+{162162+ struct isp116x_ep *ep;163163+ struct ptd *ptd;164164+ int buflen = isp116x->atl_last_dir == PTD_DIR_IN165165+ ? isp116x->atl_bufshrt : isp116x->atl_buflen;166166+ int ptd_count = 0;167167+168168+ isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT);169169+ isp116x_write_reg16(isp116x, HCXFERCTR, buflen);170170+ isp116x_write_addr(isp116x, HCATLPORT | ISP116x_WRITE_OFFSET);171171+ for (ep = isp116x->atl_active; ep; ep = ep->active) {172172+ ++ptd_count;173173+ ptd = &ep->ptd;174174+ dump_ptd(ptd);175175+ dump_ptd_out_data(ptd, ep->data);176176+ isp116x_write_data16(isp116x, ptd->count);177177+ isp116x_write_data16(isp116x, ptd->mps);178178+ isp116x_write_data16(isp116x, ptd->len);179179+ isp116x_write_data16(isp116x, ptd->faddr);180180+ buflen -= sizeof(struct ptd);181181+ /* Skip writing data for last IN PTD */182182+ if (ep->active || (isp116x->atl_last_dir != PTD_DIR_IN)) {183183+ write_ptddata_to_fifo(isp116x, ep->data, ep->length);184184+ buflen -= ALIGN(ep->length, 4);185185+ }186186+ }187187+ BUG_ON(buflen);188188+}189189+190190+/*191191+ Read the processed ptd's and data from fifo ram back to192192+ URBs' buffers. Fifo must be full and done193193+*/194194+static void unpack_fifo(struct isp116x *isp116x)195195+{196196+ struct isp116x_ep *ep;197197+ struct ptd *ptd;198198+ int buflen = isp116x->atl_last_dir == PTD_DIR_IN199199+ ? isp116x->atl_buflen : isp116x->atl_bufshrt;200200+201201+ isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT);202202+ isp116x_write_reg16(isp116x, HCXFERCTR, buflen);203203+ isp116x_write_addr(isp116x, HCATLPORT);204204+ for (ep = isp116x->atl_active; ep; ep = ep->active) {205205+ ptd = &ep->ptd;206206+ ptd->count = isp116x_read_data16(isp116x);207207+ ptd->mps = isp116x_read_data16(isp116x);208208+ ptd->len = isp116x_read_data16(isp116x);209209+ ptd->faddr = isp116x_read_data16(isp116x);210210+ buflen -= sizeof(struct ptd);211211+ /* Skip reading data for last Setup or Out PTD */212212+ if (ep->active || (isp116x->atl_last_dir == PTD_DIR_IN)) {213213+ read_ptddata_from_fifo(isp116x, ep->data, ep->length);214214+ buflen -= ALIGN(ep->length, 4);215215+ }216216+ dump_ptd(ptd);217217+ dump_ptd_in_data(ptd, ep->data);218218+ }219219+ BUG_ON(buflen);220220+}221221+222222+/*---------------------------------------------------------------*/223223+224224+/*225225+ Set up PTD's.226226+*/227227+static void preproc_atl_queue(struct isp116x *isp116x)228228+{229229+ struct isp116x_ep *ep;230230+ struct urb *urb;231231+ struct ptd *ptd;232232+ u16 toggle, dir, len;233233+234234+ for (ep = isp116x->atl_active; ep; ep = ep->active) {235235+ BUG_ON(list_empty(&ep->hep->urb_list));236236+ urb = container_of(ep->hep->urb_list.next,237237+ struct urb, urb_list);238238+ ptd = &ep->ptd;239239+ len = ep->length;240240+ spin_lock(&urb->lock);241241+ ep->data = (unsigned char *)urb->transfer_buffer242242+ + urb->actual_length;243243+244244+ switch (ep->nextpid) {245245+ case USB_PID_IN:246246+ toggle = usb_gettoggle(urb->dev, ep->epnum, 0);247247+ dir = PTD_DIR_IN;248248+ break;249249+ case USB_PID_OUT:250250+ toggle = usb_gettoggle(urb->dev, ep->epnum, 1);251251+ dir = PTD_DIR_OUT;252252+ break;253253+ case USB_PID_SETUP:254254+ toggle = 0;255255+ dir = PTD_DIR_SETUP;256256+ len = sizeof(struct usb_ctrlrequest);257257+ ep->data = urb->setup_packet;258258+ break;259259+ case USB_PID_ACK:260260+ toggle = 1;261261+ len = 0;262262+ dir = (urb->transfer_buffer_length263263+ && usb_pipein(urb->pipe))264264+ ? PTD_DIR_OUT : PTD_DIR_IN;265265+ break;266266+ default:267267+ /* To please gcc */268268+ toggle = dir = 0;269269+ ERR("%s %d: ep->nextpid %d\n", __func__, __LINE__,270270+ ep->nextpid);271271+ BUG_ON(1);272272+ }273273+274274+ ptd->count = PTD_CC_MSK | PTD_ACTIVE_MSK | PTD_TOGGLE(toggle);275275+ ptd->mps = PTD_MPS(ep->maxpacket)276276+ | PTD_SPD(urb->dev->speed == USB_SPEED_LOW)277277+ | PTD_EP(ep->epnum);278278+ ptd->len = PTD_LEN(len) | PTD_DIR(dir);279279+ ptd->faddr = PTD_FA(usb_pipedevice(urb->pipe));280280+ spin_unlock(&urb->lock);281281+ if (!ep->active) {282282+ ptd->mps |= PTD_LAST_MSK;283283+ isp116x->atl_last_dir = dir;284284+ }285285+ isp116x->atl_bufshrt = sizeof(struct ptd) + isp116x->atl_buflen;286286+ isp116x->atl_buflen = isp116x->atl_bufshrt + ALIGN(len, 4);287287+ }288288+}289289+290290+/*291291+ Analyze transfer results, handle partial transfers and errors292292+*/293293+static void postproc_atl_queue(struct isp116x *isp116x)294294+{295295+ struct isp116x_ep *ep;296296+ struct urb *urb;297297+ struct usb_device *udev;298298+ struct ptd *ptd;299299+ int short_not_ok;300300+ u8 cc;301301+302302+ for (ep = isp116x->atl_active; ep; ep = ep->active) {303303+ BUG_ON(list_empty(&ep->hep->urb_list));304304+ urb =305305+ container_of(ep->hep->urb_list.next, struct urb, urb_list);306306+ udev = urb->dev;307307+ ptd = &ep->ptd;308308+ cc = PTD_GET_CC(ptd);309309+310310+ spin_lock(&urb->lock);311311+ short_not_ok = 1;312312+313313+ /* Data underrun is special. For allowed underrun314314+ we clear the error and continue as normal. For315315+ forbidden underrun we finish the DATA stage316316+ immediately while for control transfer,317317+ we do a STATUS stage. */318318+ if (cc == TD_DATAUNDERRUN) {319319+ if (!(urb->transfer_flags & URB_SHORT_NOT_OK)) {320320+ DBG("Allowed data underrun\n");321321+ cc = TD_CC_NOERROR;322322+ short_not_ok = 0;323323+ } else {324324+ ep->error_count = 1;325325+ if (usb_pipecontrol(urb->pipe))326326+ ep->nextpid = USB_PID_ACK;327327+ else328328+ usb_settoggle(udev, ep->epnum,329329+ ep->nextpid ==330330+ USB_PID_OUT,331331+ PTD_GET_TOGGLE(ptd) ^ 1);332332+ urb->status = cc_to_error[TD_DATAUNDERRUN];333333+ spin_unlock(&urb->lock);334334+ continue;335335+ }336336+ }337337+ /* Keep underrun error through the STATUS stage */338338+ if (urb->status == cc_to_error[TD_DATAUNDERRUN])339339+ cc = TD_DATAUNDERRUN;340340+341341+ if (cc != TD_CC_NOERROR && cc != TD_NOTACCESSED342342+ && (++ep->error_count >= 3 || cc == TD_CC_STALL343343+ || cc == TD_DATAOVERRUN)) {344344+ if (urb->status == -EINPROGRESS)345345+ urb->status = cc_to_error[cc];346346+ if (ep->nextpid == USB_PID_ACK)347347+ ep->nextpid = 0;348348+ spin_unlock(&urb->lock);349349+ continue;350350+ }351351+ /* According to usb spec, zero-length Int transfer signals352352+ finishing of the urb. Hey, does this apply only353353+ for IN endpoints? */354354+ if (usb_pipeint(urb->pipe) && !PTD_GET_LEN(ptd)) {355355+ if (urb->status == -EINPROGRESS)356356+ urb->status = 0;357357+ spin_unlock(&urb->lock);358358+ continue;359359+ }360360+361361+ /* Relax after previously failed, but later succeeded362362+ or correctly NAK'ed retransmission attempt */363363+ if (ep->error_count364364+ && (cc == TD_CC_NOERROR || cc == TD_NOTACCESSED))365365+ ep->error_count = 0;366366+367367+ /* Take into account idiosyncracies of the isp116x chip368368+ regarding toggle bit for failed transfers */369369+ if (ep->nextpid == USB_PID_OUT)370370+ usb_settoggle(udev, ep->epnum, 1, PTD_GET_TOGGLE(ptd)371371+ ^ (ep->error_count > 0));372372+ else if (ep->nextpid == USB_PID_IN)373373+ usb_settoggle(udev, ep->epnum, 0, PTD_GET_TOGGLE(ptd)374374+ ^ (ep->error_count > 0));375375+376376+ switch (ep->nextpid) {377377+ case USB_PID_IN:378378+ case USB_PID_OUT:379379+ urb->actual_length += PTD_GET_COUNT(ptd);380380+ if (PTD_GET_ACTIVE(ptd)381381+ || (cc != TD_CC_NOERROR && cc < 0x0E))382382+ break;383383+ if (urb->transfer_buffer_length != urb->actual_length) {384384+ if (short_not_ok)385385+ break;386386+ } else {387387+ if (urb->transfer_flags & URB_ZERO_PACKET388388+ && ep->nextpid == USB_PID_OUT389389+ && !(PTD_GET_COUNT(ptd) % ep->maxpacket)) {390390+ DBG("Zero packet requested\n");391391+ break;392392+ }393393+ }394394+ /* All data for this URB is transferred, let's finish */395395+ if (usb_pipecontrol(urb->pipe))396396+ ep->nextpid = USB_PID_ACK;397397+ else if (urb->status == -EINPROGRESS)398398+ urb->status = 0;399399+ break;400400+ case USB_PID_SETUP:401401+ if (PTD_GET_ACTIVE(ptd)402402+ || (cc != TD_CC_NOERROR && cc < 0x0E))403403+ break;404404+ if (urb->transfer_buffer_length == urb->actual_length)405405+ ep->nextpid = USB_PID_ACK;406406+ else if (usb_pipeout(urb->pipe)) {407407+ usb_settoggle(udev, 0, 1, 1);408408+ ep->nextpid = USB_PID_OUT;409409+ } else {410410+ usb_settoggle(udev, 0, 0, 1);411411+ ep->nextpid = USB_PID_IN;412412+ }413413+ break;414414+ case USB_PID_ACK:415415+ if (PTD_GET_ACTIVE(ptd)416416+ || (cc != TD_CC_NOERROR && cc < 0x0E))417417+ break;418418+ if (urb->status == -EINPROGRESS)419419+ urb->status = 0;420420+ ep->nextpid = 0;421421+ break;422422+ default:423423+ BUG_ON(1);424424+ }425425+ spin_unlock(&urb->lock);426426+ }427427+}428428+429429+/*430430+ Take done or failed requests out of schedule. Give back431431+ processed urbs.432432+*/433433+static void finish_request(struct isp116x *isp116x, struct isp116x_ep *ep,434434+ struct urb *urb, struct pt_regs *regs)435435+__releases(isp116x->lock) __acquires(isp116x->lock)436436+{437437+ unsigned i;438438+439439+ urb->hcpriv = NULL;440440+ ep->error_count = 0;441441+442442+ if (usb_pipecontrol(urb->pipe))443443+ ep->nextpid = USB_PID_SETUP;444444+445445+ urb_dbg(urb, "Finish");446446+447447+ spin_unlock(&isp116x->lock);448448+ usb_hcd_giveback_urb(isp116x_to_hcd(isp116x), urb, regs);449449+ spin_lock(&isp116x->lock);450450+451451+ /* take idle endpoints out of the schedule */452452+ if (!list_empty(&ep->hep->urb_list))453453+ return;454454+455455+ /* async deschedule */456456+ if (!list_empty(&ep->schedule)) {457457+ list_del_init(&ep->schedule);458458+ return;459459+ }460460+461461+ /* periodic deschedule */462462+ DBG("deschedule qh%d/%p branch %d\n", ep->period, ep, ep->branch);463463+ for (i = ep->branch; i < PERIODIC_SIZE; i += ep->period) {464464+ struct isp116x_ep *temp;465465+ struct isp116x_ep **prev = &isp116x->periodic[i];466466+467467+ while (*prev && ((temp = *prev) != ep))468468+ prev = &temp->next;469469+ if (*prev)470470+ *prev = ep->next;471471+ isp116x->load[i] -= ep->load;472472+ }473473+ ep->branch = PERIODIC_SIZE;474474+ isp116x_to_hcd(isp116x)->self.bandwidth_allocated -=475475+ ep->load / ep->period;476476+477477+ /* switch irq type? */478478+ if (!--isp116x->periodic_count) {479479+ isp116x->irqenb &= ~HCuPINT_SOF;480480+ isp116x->irqenb |= HCuPINT_ATL;481481+ }482482+}483483+484484+/*485485+ Scan transfer lists, schedule transfers, send data off486486+ to chip.487487+ */488488+static void start_atl_transfers(struct isp116x *isp116x)489489+{490490+ struct isp116x_ep *last_ep = NULL, *ep;491491+ struct urb *urb;492492+ u16 load = 0;493493+ int len, index, speed, byte_time;494494+495495+ if (atomic_read(&isp116x->atl_finishing))496496+ return;497497+498498+ if (!HC_IS_RUNNING(isp116x_to_hcd(isp116x)->state))499499+ return;500500+501501+ /* FIFO not empty? */502502+ if (isp116x_read_reg16(isp116x, HCBUFSTAT) & HCBUFSTAT_ATL_FULL)503503+ return;504504+505505+ isp116x->atl_active = NULL;506506+ isp116x->atl_buflen = isp116x->atl_bufshrt = 0;507507+508508+ /* Schedule int transfers */509509+ if (isp116x->periodic_count) {510510+ isp116x->fmindex = index =511511+ (isp116x->fmindex + 1) & (PERIODIC_SIZE - 1);512512+ if ((load = isp116x->load[index])) {513513+ /* Bring all int transfers for this frame514514+ into the active queue */515515+ isp116x->atl_active = last_ep =516516+ isp116x->periodic[index];517517+ while (last_ep->next)518518+ last_ep = (last_ep->active = last_ep->next);519519+ last_ep->active = NULL;520520+ }521521+ }522522+523523+ /* Schedule control/bulk transfers */524524+ list_for_each_entry(ep, &isp116x->async, schedule) {525525+ urb = container_of(ep->hep->urb_list.next,526526+ struct urb, urb_list);527527+ speed = urb->dev->speed;528528+ byte_time = speed == USB_SPEED_LOW529529+ ? BYTE_TIME_LOWSPEED : BYTE_TIME_FULLSPEED;530530+531531+ if (ep->nextpid == USB_PID_SETUP) {532532+ len = sizeof(struct usb_ctrlrequest);533533+ } else if (ep->nextpid == USB_PID_ACK) {534534+ len = 0;535535+ } else {536536+ /* Find current free length ... */537537+ len = (MAX_LOAD_LIMIT - load) / byte_time;538538+539539+ /* ... then limit it to configured max size ... */540540+ len = min(len, speed == USB_SPEED_LOW ?541541+ MAX_TRANSFER_SIZE_LOWSPEED :542542+ MAX_TRANSFER_SIZE_FULLSPEED);543543+544544+ /* ... and finally cut to the multiple of MaxPacketSize,545545+ or to the real length if there's enough room. */546546+ if (len <547547+ (urb->transfer_buffer_length -548548+ urb->actual_length)) {549549+ len -= len % ep->maxpacket;550550+ if (!len)551551+ continue;552552+ } else553553+ len = urb->transfer_buffer_length -554554+ urb->actual_length;555555+ BUG_ON(len < 0);556556+ }557557+558558+ load += len * byte_time;559559+ if (load > MAX_LOAD_LIMIT)560560+ break;561561+562562+ ep->active = NULL;563563+ ep->length = len;564564+ if (last_ep)565565+ last_ep->active = ep;566566+ else567567+ isp116x->atl_active = ep;568568+ last_ep = ep;569569+ }570570+571571+ /* Avoid starving of endpoints */572572+ if ((&isp116x->async)->next != (&isp116x->async)->prev)573573+ list_move(&isp116x->async, (&isp116x->async)->next);574574+575575+ if (isp116x->atl_active) {576576+ preproc_atl_queue(isp116x);577577+ pack_fifo(isp116x);578578+ }579579+}580580+581581+/*582582+ Finish the processed transfers583583+*/584584+static void finish_atl_transfers(struct isp116x *isp116x, struct pt_regs *regs)585585+{586586+ struct isp116x_ep *ep;587587+ struct urb *urb;588588+589589+ if (!isp116x->atl_active)590590+ return;591591+ /* Fifo not ready? */592592+ if (!(isp116x_read_reg16(isp116x, HCBUFSTAT) & HCBUFSTAT_ATL_DONE))593593+ return;594594+595595+ atomic_inc(&isp116x->atl_finishing);596596+ unpack_fifo(isp116x);597597+ postproc_atl_queue(isp116x);598598+ for (ep = isp116x->atl_active; ep; ep = ep->active) {599599+ urb =600600+ container_of(ep->hep->urb_list.next, struct urb, urb_list);601601+ /* USB_PID_ACK check here avoids finishing of602602+ control transfers, for which TD_DATAUNDERRUN603603+ occured, while URB_SHORT_NOT_OK was set */604604+ if (urb && urb->status != -EINPROGRESS605605+ && ep->nextpid != USB_PID_ACK)606606+ finish_request(isp116x, ep, urb, regs);607607+ }608608+ atomic_dec(&isp116x->atl_finishing);609609+}610610+611611+static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs)612612+{613613+ struct isp116x *isp116x = hcd_to_isp116x(hcd);614614+ u16 irqstat;615615+ irqreturn_t ret = IRQ_NONE;616616+617617+ spin_lock(&isp116x->lock);618618+ isp116x_write_reg16(isp116x, HCuPINTENB, 0);619619+ irqstat = isp116x_read_reg16(isp116x, HCuPINT);620620+ isp116x_write_reg16(isp116x, HCuPINT, irqstat);621621+622622+ if (irqstat & (HCuPINT_ATL | HCuPINT_SOF)) {623623+ ret = IRQ_HANDLED;624624+ finish_atl_transfers(isp116x, regs);625625+ }626626+627627+ if (irqstat & HCuPINT_OPR) {628628+ u32 intstat = isp116x_read_reg32(isp116x, HCINTSTAT);629629+ isp116x_write_reg32(isp116x, HCINTSTAT, intstat);630630+ if (intstat & HCINT_UE) {631631+ ERR("Unrecoverable error\n");632632+ /* What should we do here? Reset? */633633+ }634634+ if (intstat & HCINT_RHSC) {635635+ isp116x->rhstatus =636636+ isp116x_read_reg32(isp116x, HCRHSTATUS);637637+ isp116x->rhport[0] =638638+ isp116x_read_reg32(isp116x, HCRHPORT1);639639+ isp116x->rhport[1] =640640+ isp116x_read_reg32(isp116x, HCRHPORT2);641641+ }642642+ if (intstat & HCINT_RD) {643643+ DBG("---- remote wakeup\n");644644+ schedule_work(&isp116x->rh_resume);645645+ ret = IRQ_HANDLED;646646+ }647647+ irqstat &= ~HCuPINT_OPR;648648+ ret = IRQ_HANDLED;649649+ }650650+651651+ if (irqstat & (HCuPINT_ATL | HCuPINT_SOF)) {652652+ start_atl_transfers(isp116x);653653+ }654654+655655+ isp116x_write_reg16(isp116x, HCuPINTENB, isp116x->irqenb);656656+ spin_unlock(&isp116x->lock);657657+ return ret;658658+}659659+660660+/*-----------------------------------------------------------------*/661661+662662+/* usb 1.1 says max 90% of a frame is available for periodic transfers.663663+ * this driver doesn't promise that much since it's got to handle an664664+ * IRQ per packet; irq handling latencies also use up that time.665665+ */666666+667667+/* out of 1000 us */668668+#define MAX_PERIODIC_LOAD 600669669+static int balance(struct isp116x *isp116x, u16 period, u16 load)670670+{671671+ int i, branch = -ENOSPC;672672+673673+ /* search for the least loaded schedule branch of that period674674+ which has enough bandwidth left unreserved. */675675+ for (i = 0; i < period; i++) {676676+ if (branch < 0 || isp116x->load[branch] > isp116x->load[i]) {677677+ int j;678678+679679+ for (j = i; j < PERIODIC_SIZE; j += period) {680680+ if ((isp116x->load[j] + load)681681+ > MAX_PERIODIC_LOAD)682682+ break;683683+ }684684+ if (j < PERIODIC_SIZE)685685+ continue;686686+ branch = i;687687+ }688688+ }689689+ return branch;690690+}691691+692692+/* NB! ALL the code above this point runs with isp116x->lock693693+ held, irqs off694694+*/695695+696696+/*-----------------------------------------------------------------*/697697+698698+static int isp116x_urb_enqueue(struct usb_hcd *hcd,699699+ struct usb_host_endpoint *hep, struct urb *urb,700700+ int mem_flags)701701+{702702+ struct isp116x *isp116x = hcd_to_isp116x(hcd);703703+ struct usb_device *udev = urb->dev;704704+ unsigned int pipe = urb->pipe;705705+ int is_out = !usb_pipein(pipe);706706+ int type = usb_pipetype(pipe);707707+ int epnum = usb_pipeendpoint(pipe);708708+ struct isp116x_ep *ep = NULL;709709+ unsigned long flags;710710+ int i;711711+ int ret = 0;712712+713713+ urb_dbg(urb, "Enqueue");714714+715715+ if (type == PIPE_ISOCHRONOUS) {716716+ ERR("Isochronous transfers not supported\n");717717+ urb_dbg(urb, "Refused to enqueue");718718+ return -ENXIO;719719+ }720720+ /* avoid all allocations within spinlocks: request or endpoint */721721+ if (!hep->hcpriv) {722722+ ep = kcalloc(1, sizeof *ep, (__force unsigned)mem_flags);723723+ if (!ep)724724+ return -ENOMEM;725725+ }726726+727727+ spin_lock_irqsave(&isp116x->lock, flags);728728+ if (!HC_IS_RUNNING(hcd->state)) {729729+ ret = -ENODEV;730730+ goto fail;731731+ }732732+733733+ if (hep->hcpriv)734734+ ep = hep->hcpriv;735735+ else {736736+ INIT_LIST_HEAD(&ep->schedule);737737+ ep->udev = usb_get_dev(udev);738738+ ep->epnum = epnum;739739+ ep->maxpacket = usb_maxpacket(udev, urb->pipe, is_out);740740+ usb_settoggle(udev, epnum, is_out, 0);741741+742742+ if (type == PIPE_CONTROL) {743743+ ep->nextpid = USB_PID_SETUP;744744+ } else if (is_out) {745745+ ep->nextpid = USB_PID_OUT;746746+ } else {747747+ ep->nextpid = USB_PID_IN;748748+ }749749+750750+ if (urb->interval) {751751+ /*752752+ With INT URBs submitted, the driver works with SOF753753+ interrupt enabled and ATL interrupt disabled. After754754+ the PTDs are written to fifo ram, the chip starts755755+ fifo processing and usb transfers after the next756756+ SOF and continues until the transfers are finished757757+ (succeeded or failed) or the frame ends. Therefore,758758+ the transfers occur only in every second frame,759759+ while fifo reading/writing and data processing760760+ occur in every other second frame. */761761+ if (urb->interval < 2)762762+ urb->interval = 2;763763+ if (urb->interval > 2 * PERIODIC_SIZE)764764+ urb->interval = 2 * PERIODIC_SIZE;765765+ ep->period = urb->interval >> 1;766766+ ep->branch = PERIODIC_SIZE;767767+ ep->load = usb_calc_bus_time(udev->speed,768768+ !is_out,769769+ (type == PIPE_ISOCHRONOUS),770770+ usb_maxpacket(udev, pipe,771771+ is_out)) /772772+ 1000;773773+ }774774+ hep->hcpriv = ep;775775+ ep->hep = hep;776776+ }777777+778778+ /* maybe put endpoint into schedule */779779+ switch (type) {780780+ case PIPE_CONTROL:781781+ case PIPE_BULK:782782+ if (list_empty(&ep->schedule))783783+ list_add_tail(&ep->schedule, &isp116x->async);784784+ break;785785+ case PIPE_INTERRUPT:786786+ urb->interval = ep->period;787787+ ep->length = min((int)ep->maxpacket,788788+ urb->transfer_buffer_length);789789+790790+ /* urb submitted for already existing endpoint */791791+ if (ep->branch < PERIODIC_SIZE)792792+ break;793793+794794+ ret = ep->branch = balance(isp116x, ep->period, ep->load);795795+ if (ret < 0)796796+ goto fail;797797+ ret = 0;798798+799799+ urb->start_frame = (isp116x->fmindex & (PERIODIC_SIZE - 1))800800+ + ep->branch;801801+802802+ /* sort each schedule branch by period (slow before fast)803803+ to share the faster parts of the tree without needing804804+ dummy/placeholder nodes */805805+ DBG("schedule qh%d/%p branch %d\n", ep->period, ep, ep->branch);806806+ for (i = ep->branch; i < PERIODIC_SIZE; i += ep->period) {807807+ struct isp116x_ep **prev = &isp116x->periodic[i];808808+ struct isp116x_ep *here = *prev;809809+810810+ while (here && ep != here) {811811+ if (ep->period > here->period)812812+ break;813813+ prev = &here->next;814814+ here = *prev;815815+ }816816+ if (ep != here) {817817+ ep->next = here;818818+ *prev = ep;819819+ }820820+ isp116x->load[i] += ep->load;821821+ }822822+ hcd->self.bandwidth_allocated += ep->load / ep->period;823823+824824+ /* switch over to SOFint */825825+ if (!isp116x->periodic_count++) {826826+ isp116x->irqenb &= ~HCuPINT_ATL;827827+ isp116x->irqenb |= HCuPINT_SOF;828828+ isp116x_write_reg16(isp116x, HCuPINTENB,829829+ isp116x->irqenb);830830+ }831831+ }832832+833833+ /* in case of unlink-during-submit */834834+ spin_lock(&urb->lock);835835+ if (urb->status != -EINPROGRESS) {836836+ spin_unlock(&urb->lock);837837+ finish_request(isp116x, ep, urb, NULL);838838+ ret = 0;839839+ goto fail;840840+ }841841+ urb->hcpriv = hep;842842+ spin_unlock(&urb->lock);843843+ start_atl_transfers(isp116x);844844+845845+ fail:846846+ spin_unlock_irqrestore(&isp116x->lock, flags);847847+ return ret;848848+}849849+850850+/*851851+ Dequeue URBs.852852+*/853853+static int isp116x_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)854854+{855855+ struct isp116x *isp116x = hcd_to_isp116x(hcd);856856+ struct usb_host_endpoint *hep;857857+ struct isp116x_ep *ep, *ep_act;858858+ unsigned long flags;859859+860860+ spin_lock_irqsave(&isp116x->lock, flags);861861+ hep = urb->hcpriv;862862+ /* URB already unlinked (or never linked)? */863863+ if (!hep) {864864+ spin_unlock_irqrestore(&isp116x->lock, flags);865865+ return 0;866866+ }867867+ ep = hep->hcpriv;868868+ WARN_ON(hep != ep->hep);869869+870870+ /* In front of queue? */871871+ if (ep->hep->urb_list.next == &urb->urb_list)872872+ /* active? */873873+ for (ep_act = isp116x->atl_active; ep_act;874874+ ep_act = ep_act->active)875875+ if (ep_act == ep) {876876+ VDBG("dequeue, urb %p active; wait for irq\n",877877+ urb);878878+ urb = NULL;879879+ break;880880+ }881881+882882+ if (urb)883883+ finish_request(isp116x, ep, urb, NULL);884884+885885+ spin_unlock_irqrestore(&isp116x->lock, flags);886886+ return 0;887887+}888888+889889+static void isp116x_endpoint_disable(struct usb_hcd *hcd,890890+ struct usb_host_endpoint *hep)891891+{892892+ int i;893893+ struct isp116x_ep *ep = hep->hcpriv;;894894+895895+ if (!ep)896896+ return;897897+898898+ /* assume we'd just wait for the irq */899899+ for (i = 0; i < 100 && !list_empty(&hep->urb_list); i++)900900+ msleep(3);901901+ if (!list_empty(&hep->urb_list))902902+ WARN("ep %p not empty?\n", ep);903903+904904+ usb_put_dev(ep->udev);905905+ kfree(ep);906906+ hep->hcpriv = NULL;907907+}908908+909909+static int isp116x_get_frame(struct usb_hcd *hcd)910910+{911911+ struct isp116x *isp116x = hcd_to_isp116x(hcd);912912+ u32 fmnum;913913+ unsigned long flags;914914+915915+ spin_lock_irqsave(&isp116x->lock, flags);916916+ fmnum = isp116x_read_reg32(isp116x, HCFMNUM);917917+ spin_unlock_irqrestore(&isp116x->lock, flags);918918+ return (int)fmnum;919919+}920920+921921+/*----------------------------------------------------------------*/922922+923923+/*924924+ Adapted from ohci-hub.c. Currently we don't support autosuspend.925925+*/926926+static int isp116x_hub_status_data(struct usb_hcd *hcd, char *buf)927927+{928928+ struct isp116x *isp116x = hcd_to_isp116x(hcd);929929+ int ports, i, changed = 0;930930+931931+ if (!HC_IS_RUNNING(hcd->state))932932+ return -ESHUTDOWN;933933+934934+ ports = isp116x->rhdesca & RH_A_NDP;935935+936936+ /* init status */937937+ if (isp116x->rhstatus & (RH_HS_LPSC | RH_HS_OCIC))938938+ buf[0] = changed = 1;939939+ else940940+ buf[0] = 0;941941+942942+ for (i = 0; i < ports; i++) {943943+ u32 status = isp116x->rhport[i];944944+945945+ if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC946946+ | RH_PS_OCIC | RH_PS_PRSC)) {947947+ changed = 1;948948+ buf[0] |= 1 << (i + 1);949949+ continue;950950+ }951951+ }952952+ return changed;953953+}954954+955955+static void isp116x_hub_descriptor(struct isp116x *isp116x,956956+ struct usb_hub_descriptor *desc)957957+{958958+ u32 reg = isp116x->rhdesca;959959+960960+ desc->bDescriptorType = 0x29;961961+ desc->bDescLength = 9;962962+ desc->bHubContrCurrent = 0;963963+ desc->bNbrPorts = (u8) (reg & 0x3);964964+ /* Power switching, device type, overcurrent. */965965+ desc->wHubCharacteristics =966966+ (__force __u16) cpu_to_le16((u16) ((reg >> 8) & 0x1f));967967+ desc->bPwrOn2PwrGood = (u8) ((reg >> 24) & 0xff);968968+ /* two bitmaps: ports removable, and legacy PortPwrCtrlMask */969969+ desc->bitmap[0] = desc->bNbrPorts == 1 ? 1 << 1 : 3 << 1;970970+ desc->bitmap[1] = ~0;971971+}972972+973973+/* Perform reset of a given port.974974+ It would be great to just start the reset and let the975975+ USB core to clear the reset in due time. However,976976+ root hub ports should be reset for at least 50 ms, while977977+ our chip stays in reset for about 10 ms. I.e., we must978978+ repeatedly reset it ourself here.979979+*/980980+static inline void root_port_reset(struct isp116x *isp116x, unsigned port)981981+{982982+ u32 tmp;983983+ unsigned long flags, t;984984+985985+ /* Root hub reset should be 50 ms, but some devices986986+ want it even longer. */987987+ t = jiffies + msecs_to_jiffies(100);988988+989989+ while (time_before(jiffies, t)) {990990+ spin_lock_irqsave(&isp116x->lock, flags);991991+ /* spin until any current reset finishes */992992+ for (;;) {993993+ tmp = isp116x_read_reg32(isp116x, port ?994994+ HCRHPORT2 : HCRHPORT1);995995+ if (!(tmp & RH_PS_PRS))996996+ break;997997+ udelay(500);998998+ }999999+ /* Don't reset a disconnected port */10001000+ if (!(tmp & RH_PS_CCS)) {10011001+ spin_unlock_irqrestore(&isp116x->lock, flags);10021002+ break;10031003+ }10041004+ /* Reset lasts 10ms (claims datasheet) */10051005+ isp116x_write_reg32(isp116x, port ? HCRHPORT2 :10061006+ HCRHPORT1, (RH_PS_PRS));10071007+ spin_unlock_irqrestore(&isp116x->lock, flags);10081008+ msleep(10);10091009+ }10101010+}10111011+10121012+/* Adapted from ohci-hub.c */10131013+static int isp116x_hub_control(struct usb_hcd *hcd,10141014+ u16 typeReq,10151015+ u16 wValue, u16 wIndex, char *buf, u16 wLength)10161016+{10171017+ struct isp116x *isp116x = hcd_to_isp116x(hcd);10181018+ int ret = 0;10191019+ unsigned long flags;10201020+ int ports = isp116x->rhdesca & RH_A_NDP;10211021+ u32 tmp = 0;10221022+10231023+ switch (typeReq) {10241024+ case ClearHubFeature:10251025+ DBG("ClearHubFeature: ");10261026+ switch (wValue) {10271027+ case C_HUB_OVER_CURRENT:10281028+ DBG("C_HUB_OVER_CURRENT\n");10291029+ spin_lock_irqsave(&isp116x->lock, flags);10301030+ isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_OCIC);10311031+ spin_unlock_irqrestore(&isp116x->lock, flags);10321032+ case C_HUB_LOCAL_POWER:10331033+ DBG("C_HUB_LOCAL_POWER\n");10341034+ break;10351035+ default:10361036+ goto error;10371037+ }10381038+ break;10391039+ case SetHubFeature:10401040+ DBG("SetHubFeature: ");10411041+ switch (wValue) {10421042+ case C_HUB_OVER_CURRENT:10431043+ case C_HUB_LOCAL_POWER:10441044+ DBG("C_HUB_OVER_CURRENT or C_HUB_LOCAL_POWER\n");10451045+ break;10461046+ default:10471047+ goto error;10481048+ }10491049+ break;10501050+ case GetHubDescriptor:10511051+ DBG("GetHubDescriptor\n");10521052+ isp116x_hub_descriptor(isp116x,10531053+ (struct usb_hub_descriptor *)buf);10541054+ break;10551055+ case GetHubStatus:10561056+ DBG("GetHubStatus\n");10571057+ *(__le32 *) buf = cpu_to_le32(0);10581058+ break;10591059+ case GetPortStatus:10601060+ DBG("GetPortStatus\n");10611061+ if (!wIndex || wIndex > ports)10621062+ goto error;10631063+ tmp = isp116x->rhport[--wIndex];10641064+ *(__le32 *) buf = cpu_to_le32(tmp);10651065+ DBG("GetPortStatus: port[%d] %08x\n", wIndex + 1, tmp);10661066+ break;10671067+ case ClearPortFeature:10681068+ DBG("ClearPortFeature: ");10691069+ if (!wIndex || wIndex > ports)10701070+ goto error;10711071+ wIndex--;10721072+10731073+ switch (wValue) {10741074+ case USB_PORT_FEAT_ENABLE:10751075+ DBG("USB_PORT_FEAT_ENABLE\n");10761076+ tmp = RH_PS_CCS;10771077+ break;10781078+ case USB_PORT_FEAT_C_ENABLE:10791079+ DBG("USB_PORT_FEAT_C_ENABLE\n");10801080+ tmp = RH_PS_PESC;10811081+ break;10821082+ case USB_PORT_FEAT_SUSPEND:10831083+ DBG("USB_PORT_FEAT_SUSPEND\n");10841084+ tmp = RH_PS_POCI;10851085+ break;10861086+ case USB_PORT_FEAT_C_SUSPEND:10871087+ DBG("USB_PORT_FEAT_C_SUSPEND\n");10881088+ tmp = RH_PS_PSSC;10891089+ break;10901090+ case USB_PORT_FEAT_POWER:10911091+ DBG("USB_PORT_FEAT_POWER\n");10921092+ tmp = RH_PS_LSDA;10931093+ break;10941094+ case USB_PORT_FEAT_C_CONNECTION:10951095+ DBG("USB_PORT_FEAT_C_CONNECTION\n");10961096+ tmp = RH_PS_CSC;10971097+ break;10981098+ case USB_PORT_FEAT_C_OVER_CURRENT:10991099+ DBG("USB_PORT_FEAT_C_OVER_CURRENT\n");11001100+ tmp = RH_PS_OCIC;11011101+ break;11021102+ case USB_PORT_FEAT_C_RESET:11031103+ DBG("USB_PORT_FEAT_C_RESET\n");11041104+ tmp = RH_PS_PRSC;11051105+ break;11061106+ default:11071107+ goto error;11081108+ }11091109+ spin_lock_irqsave(&isp116x->lock, flags);11101110+ isp116x_write_reg32(isp116x, wIndex11111111+ ? HCRHPORT2 : HCRHPORT1, tmp);11121112+ isp116x->rhport[wIndex] =11131113+ isp116x_read_reg32(isp116x, wIndex ? HCRHPORT2 : HCRHPORT1);11141114+ spin_unlock_irqrestore(&isp116x->lock, flags);11151115+ break;11161116+ case SetPortFeature:11171117+ DBG("SetPortFeature: ");11181118+ if (!wIndex || wIndex > ports)11191119+ goto error;11201120+ wIndex--;11211121+ switch (wValue) {11221122+ case USB_PORT_FEAT_SUSPEND:11231123+ DBG("USB_PORT_FEAT_SUSPEND\n");11241124+ spin_lock_irqsave(&isp116x->lock, flags);11251125+ isp116x_write_reg32(isp116x, wIndex11261126+ ? HCRHPORT2 : HCRHPORT1, RH_PS_PSS);11271127+ break;11281128+ case USB_PORT_FEAT_POWER:11291129+ DBG("USB_PORT_FEAT_POWER\n");11301130+ spin_lock_irqsave(&isp116x->lock, flags);11311131+ isp116x_write_reg32(isp116x, wIndex11321132+ ? HCRHPORT2 : HCRHPORT1, RH_PS_PPS);11331133+ break;11341134+ case USB_PORT_FEAT_RESET:11351135+ DBG("USB_PORT_FEAT_RESET\n");11361136+ root_port_reset(isp116x, wIndex);11371137+ spin_lock_irqsave(&isp116x->lock, flags);11381138+ break;11391139+ default:11401140+ goto error;11411141+ }11421142+ isp116x->rhport[wIndex] =11431143+ isp116x_read_reg32(isp116x, wIndex ? HCRHPORT2 : HCRHPORT1);11441144+ spin_unlock_irqrestore(&isp116x->lock, flags);11451145+ break;11461146+11471147+ default:11481148+ error:11491149+ /* "protocol stall" on error */11501150+ DBG("PROTOCOL STALL\n");11511151+ ret = -EPIPE;11521152+ }11531153+ return ret;11541154+}11551155+11561156+#ifdef CONFIG_PM11571157+11581158+static int isp116x_hub_suspend(struct usb_hcd *hcd)11591159+{11601160+ struct isp116x *isp116x = hcd_to_isp116x(hcd);11611161+ unsigned long flags;11621162+ u32 val;11631163+ int ret = 0;11641164+11651165+ spin_lock_irqsave(&isp116x->lock, flags);11661166+11671167+ val = isp116x_read_reg32(isp116x, HCCONTROL);11681168+ switch (val & HCCONTROL_HCFS) {11691169+ case HCCONTROL_USB_OPER:11701170+ hcd->state = HC_STATE_QUIESCING;11711171+ val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE);11721172+ val |= HCCONTROL_USB_SUSPEND;11731173+ if (hcd->remote_wakeup)11741174+ val |= HCCONTROL_RWE;11751175+ /* Wait for usb transfers to finish */11761176+ mdelay(2);11771177+ isp116x_write_reg32(isp116x, HCCONTROL, val);11781178+ hcd->state = HC_STATE_SUSPENDED;11791179+ /* Wait for devices to suspend */11801180+ mdelay(5);11811181+ case HCCONTROL_USB_SUSPEND:11821182+ break;11831183+ case HCCONTROL_USB_RESUME:11841184+ isp116x_write_reg32(isp116x, HCCONTROL,11851185+ (val & ~HCCONTROL_HCFS) |11861186+ HCCONTROL_USB_RESET);11871187+ case HCCONTROL_USB_RESET:11881188+ ret = -EBUSY;11891189+ break;11901190+ default:11911191+ ret = -EINVAL;11921192+ }11931193+11941194+ spin_unlock_irqrestore(&isp116x->lock, flags);11951195+ return ret;11961196+}11971197+11981198+static int isp116x_hub_resume(struct usb_hcd *hcd)11991199+{12001200+ struct isp116x *isp116x = hcd_to_isp116x(hcd);12011201+ u32 val;12021202+ int ret = -EINPROGRESS;12031203+12041204+ msleep(5);12051205+ spin_lock_irq(&isp116x->lock);12061206+12071207+ val = isp116x_read_reg32(isp116x, HCCONTROL);12081208+ switch (val & HCCONTROL_HCFS) {12091209+ case HCCONTROL_USB_SUSPEND:12101210+ val &= ~HCCONTROL_HCFS;12111211+ val |= HCCONTROL_USB_RESUME;12121212+ isp116x_write_reg32(isp116x, HCCONTROL, val);12131213+ case HCCONTROL_USB_RESUME:12141214+ break;12151215+ case HCCONTROL_USB_OPER:12161216+ /* Without setting power_state here the12171217+ SUSPENDED state won't be removed from12181218+ sysfs/usbN/power.state as a response to remote12191219+ wakeup. Maybe in the future. */12201220+ hcd->self.root_hub->dev.power.power_state = PMSG_ON;12211221+ ret = 0;12221222+ break;12231223+ default:12241224+ ret = -EBUSY;12251225+ }12261226+12271227+ if (ret != -EINPROGRESS) {12281228+ spin_unlock_irq(&isp116x->lock);12291229+ return ret;12301230+ }12311231+12321232+ val = isp116x->rhdesca & RH_A_NDP;12331233+ while (val--) {12341234+ u32 stat =12351235+ isp116x_read_reg32(isp116x, val ? HCRHPORT2 : HCRHPORT1);12361236+ /* force global, not selective, resume */12371237+ if (!(stat & RH_PS_PSS))12381238+ continue;12391239+ DBG("%s: Resuming port %d\n", __func__, val);12401240+ isp116x_write_reg32(isp116x, RH_PS_POCI, val12411241+ ? HCRHPORT2 : HCRHPORT1);12421242+ }12431243+ spin_unlock_irq(&isp116x->lock);12441244+12451245+ hcd->state = HC_STATE_RESUMING;12461246+ mdelay(20);12471247+12481248+ /* Go operational */12491249+ spin_lock_irq(&isp116x->lock);12501250+ val = isp116x_read_reg32(isp116x, HCCONTROL);12511251+ isp116x_write_reg32(isp116x, HCCONTROL,12521252+ (val & ~HCCONTROL_HCFS) | HCCONTROL_USB_OPER);12531253+ spin_unlock_irq(&isp116x->lock);12541254+ /* see analogous comment above */12551255+ hcd->self.root_hub->dev.power.power_state = PMSG_ON;12561256+ hcd->state = HC_STATE_RUNNING;12571257+12581258+ return 0;12591259+}12601260+12611261+static void isp116x_rh_resume(void *_hcd)12621262+{12631263+ struct usb_hcd *hcd = _hcd;12641264+12651265+ usb_resume_device(hcd->self.root_hub);12661266+}12671267+12681268+#else12691269+12701270+#define isp116x_hub_suspend NULL12711271+#define isp116x_hub_resume NULL12721272+12731273+static void isp116x_rh_resume(void *_hcd)12741274+{12751275+}12761276+12771277+#endif12781278+12791279+/*-----------------------------------------------------------------*/12801280+12811281+#ifdef STUB_DEBUG_FILE12821282+12831283+static inline void create_debug_file(struct isp116x *isp116x)12841284+{12851285+}12861286+12871287+static inline void remove_debug_file(struct isp116x *isp116x)12881288+{12891289+}12901290+12911291+#else12921292+12931293+#include <linux/proc_fs.h>12941294+#include <linux/seq_file.h>12951295+12961296+static void dump_irq(struct seq_file *s, char *label, u16 mask)12971297+{12981298+ seq_printf(s, "%s %04x%s%s%s%s%s%s\n", label, mask,12991299+ mask & HCuPINT_CLKRDY ? " clkrdy" : "",13001300+ mask & HCuPINT_SUSP ? " susp" : "",13011301+ mask & HCuPINT_OPR ? " opr" : "",13021302+ mask & HCuPINT_AIIEOT ? " eot" : "",13031303+ mask & HCuPINT_ATL ? " atl" : "",13041304+ mask & HCuPINT_SOF ? " sof" : "");13051305+}13061306+13071307+static void dump_int(struct seq_file *s, char *label, u32 mask)13081308+{13091309+ seq_printf(s, "%s %08x%s%s%s%s%s%s%s\n", label, mask,13101310+ mask & HCINT_MIE ? " MIE" : "",13111311+ mask & HCINT_RHSC ? " rhsc" : "",13121312+ mask & HCINT_FNO ? " fno" : "",13131313+ mask & HCINT_UE ? " ue" : "",13141314+ mask & HCINT_RD ? " rd" : "",13151315+ mask & HCINT_SF ? " sof" : "", mask & HCINT_SO ? " so" : "");13161316+}13171317+13181318+static int proc_isp116x_show(struct seq_file *s, void *unused)13191319+{13201320+ struct isp116x *isp116x = s->private;13211321+ struct isp116x_ep *ep;13221322+ struct urb *urb;13231323+ unsigned i;13241324+ char *str;13251325+13261326+ seq_printf(s, "%s\n%s version %s\n",13271327+ isp116x_to_hcd(isp116x)->product_desc, hcd_name,13281328+ DRIVER_VERSION);13291329+13301330+ if (HC_IS_SUSPENDED(isp116x_to_hcd(isp116x)->state)) {13311331+ seq_printf(s, "HCD is suspended\n");13321332+ return 0;13331333+ }13341334+ if (!HC_IS_RUNNING(isp116x_to_hcd(isp116x)->state)) {13351335+ seq_printf(s, "HCD not running\n");13361336+ return 0;13371337+ }13381338+13391339+ spin_lock_irq(&isp116x->lock);13401340+13411341+ dump_irq(s, "hc_irq_enable", isp116x_read_reg16(isp116x, HCuPINTENB));13421342+ dump_irq(s, "hc_irq_status", isp116x_read_reg16(isp116x, HCuPINT));13431343+ dump_int(s, "hc_int_enable", isp116x_read_reg32(isp116x, HCINTENB));13441344+ dump_int(s, "hc_int_status", isp116x_read_reg32(isp116x, HCINTSTAT));13451345+13461346+ list_for_each_entry(ep, &isp116x->async, schedule) {13471347+13481348+ switch (ep->nextpid) {13491349+ case USB_PID_IN:13501350+ str = "in";13511351+ break;13521352+ case USB_PID_OUT:13531353+ str = "out";13541354+ break;13551355+ case USB_PID_SETUP:13561356+ str = "setup";13571357+ break;13581358+ case USB_PID_ACK:13591359+ str = "status";13601360+ break;13611361+ default:13621362+ str = "?";13631363+ break;13641364+ };13651365+ seq_printf(s, "%p, ep%d%s, maxpacket %d:\n", ep,13661366+ ep->epnum, str, ep->maxpacket);13671367+ list_for_each_entry(urb, &ep->hep->urb_list, urb_list) {13681368+ seq_printf(s, " urb%p, %d/%d\n", urb,13691369+ urb->actual_length,13701370+ urb->transfer_buffer_length);13711371+ }13721372+ }13731373+ if (!list_empty(&isp116x->async))13741374+ seq_printf(s, "\n");13751375+13761376+ seq_printf(s, "periodic size= %d\n", PERIODIC_SIZE);13771377+13781378+ for (i = 0; i < PERIODIC_SIZE; i++) {13791379+ ep = isp116x->periodic[i];13801380+ if (!ep)13811381+ continue;13821382+ seq_printf(s, "%2d [%3d]:\n", i, isp116x->load[i]);13831383+13841384+ /* DUMB: prints shared entries multiple times */13851385+ do {13861386+ seq_printf(s, " %d/%p (%sdev%d ep%d%s max %d)\n",13871387+ ep->period, ep,13881388+ (ep->udev->speed ==13891389+ USB_SPEED_FULL) ? "" : "ls ",13901390+ ep->udev->devnum, ep->epnum,13911391+ (ep->epnum ==13921392+ 0) ? "" : ((ep->nextpid ==13931393+ USB_PID_IN) ? "in" : "out"),13941394+ ep->maxpacket);13951395+ ep = ep->next;13961396+ } while (ep);13971397+ }13981398+ spin_unlock_irq(&isp116x->lock);13991399+ seq_printf(s, "\n");14001400+14011401+ return 0;14021402+}14031403+14041404+static int proc_isp116x_open(struct inode *inode, struct file *file)14051405+{14061406+ return single_open(file, proc_isp116x_show, PDE(inode)->data);14071407+}14081408+14091409+static struct file_operations proc_ops = {14101410+ .open = proc_isp116x_open,14111411+ .read = seq_read,14121412+ .llseek = seq_lseek,14131413+ .release = single_release,14141414+};14151415+14161416+/* expect just one isp116x per system */14171417+static const char proc_filename[] = "driver/isp116x";14181418+14191419+static void create_debug_file(struct isp116x *isp116x)14201420+{14211421+ struct proc_dir_entry *pde;14221422+14231423+ pde = create_proc_entry(proc_filename, 0, NULL);14241424+ if (pde == NULL)14251425+ return;14261426+14271427+ pde->proc_fops = &proc_ops;14281428+ pde->data = isp116x;14291429+ isp116x->pde = pde;14301430+}14311431+14321432+static void remove_debug_file(struct isp116x *isp116x)14331433+{14341434+ if (isp116x->pde)14351435+ remove_proc_entry(proc_filename, NULL);14361436+}14371437+14381438+#endif14391439+14401440+/*-----------------------------------------------------------------*/14411441+14421442+/*14431443+ Software reset - can be called from any contect.14441444+*/14451445+static int isp116x_sw_reset(struct isp116x *isp116x)14461446+{14471447+ int retries = 15;14481448+ unsigned long flags;14491449+ int ret = 0;14501450+14511451+ spin_lock_irqsave(&isp116x->lock, flags);14521452+ isp116x_write_reg16(isp116x, HCSWRES, HCSWRES_MAGIC);14531453+ isp116x_write_reg32(isp116x, HCCMDSTAT, HCCMDSTAT_HCR);14541454+ while (--retries) {14551455+ /* It usually resets within 1 ms */14561456+ mdelay(1);14571457+ if (!(isp116x_read_reg32(isp116x, HCCMDSTAT) & HCCMDSTAT_HCR))14581458+ break;14591459+ }14601460+ if (!retries) {14611461+ ERR("Software reset timeout\n");14621462+ ret = -ETIME;14631463+ }14641464+ spin_unlock_irqrestore(&isp116x->lock, flags);14651465+ return ret;14661466+}14671467+14681468+/*14691469+ Reset. Tries to perform platform-specific hardware14701470+ reset first; falls back to software reset.14711471+*/14721472+static int isp116x_reset(struct usb_hcd *hcd)14731473+{14741474+ struct isp116x *isp116x = hcd_to_isp116x(hcd);14751475+ unsigned long t;14761476+ u16 clkrdy = 0;14771477+ int ret = 0, timeout = 15 /* ms */ ;14781478+14791479+ if (isp116x->board && isp116x->board->reset) {14801480+ /* Hardware reset */14811481+ isp116x->board->reset(hcd->self.controller, 1);14821482+ msleep(10);14831483+ if (isp116x->board->clock)14841484+ isp116x->board->clock(hcd->self.controller, 1);14851485+ msleep(1);14861486+ isp116x->board->reset(hcd->self.controller, 0);14871487+ } else14881488+ ret = isp116x_sw_reset(isp116x);14891489+14901490+ if (ret)14911491+ return ret;14921492+14931493+ t = jiffies + msecs_to_jiffies(timeout);14941494+ while (time_before_eq(jiffies, t)) {14951495+ msleep(4);14961496+ spin_lock_irq(&isp116x->lock);14971497+ clkrdy = isp116x_read_reg16(isp116x, HCuPINT) & HCuPINT_CLKRDY;14981498+ spin_unlock_irq(&isp116x->lock);14991499+ if (clkrdy)15001500+ break;15011501+ }15021502+ if (!clkrdy) {15031503+ ERR("Clock not ready after 20ms\n");15041504+ /* After sw_reset the clock won't report to be ready, if15051505+ H_WAKEUP pin is high. */15061506+ if (!isp116x->board || !isp116x->board->reset)15071507+ ERR("The driver does not support hardware wakeup.\n");15081508+ ERR("Please make sure that the H_WAKEUP pin "15091509+ "is pulled low!\n");15101510+ ret = -ENODEV;15111511+ }15121512+ return ret;15131513+}15141514+15151515+static void isp116x_stop(struct usb_hcd *hcd)15161516+{15171517+ struct isp116x *isp116x = hcd_to_isp116x(hcd);15181518+ unsigned long flags;15191519+ u32 val;15201520+15211521+ spin_lock_irqsave(&isp116x->lock, flags);15221522+ isp116x_write_reg16(isp116x, HCuPINTENB, 0);15231523+15241524+ /* Switch off ports' power, some devices don't come up15251525+ after next 'insmod' without this */15261526+ val = isp116x_read_reg32(isp116x, HCRHDESCA);15271527+ val &= ~(RH_A_NPS | RH_A_PSM);15281528+ isp116x_write_reg32(isp116x, HCRHDESCA, val);15291529+ isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_LPS);15301530+ spin_unlock_irqrestore(&isp116x->lock, flags);15311531+15321532+ /* Put the chip into reset state */15331533+ if (isp116x->board && isp116x->board->reset)15341534+ isp116x->board->reset(hcd->self.controller, 0);15351535+ else15361536+ isp116x_sw_reset(isp116x);15371537+15381538+ /* Stop the clock */15391539+ if (isp116x->board && isp116x->board->clock)15401540+ isp116x->board->clock(hcd->self.controller, 0);15411541+}15421542+15431543+/*15441544+ Configure the chip. The chip must be successfully reset by now.15451545+*/15461546+static int isp116x_start(struct usb_hcd *hcd)15471547+{15481548+ struct isp116x *isp116x = hcd_to_isp116x(hcd);15491549+ struct isp116x_platform_data *board = isp116x->board;15501550+ u32 val;15511551+ unsigned long flags;15521552+15531553+ spin_lock_irqsave(&isp116x->lock, flags);15541554+15551555+ /* clear interrupt status and disable all interrupt sources */15561556+ isp116x_write_reg16(isp116x, HCuPINT, 0xff);15571557+ isp116x_write_reg16(isp116x, HCuPINTENB, 0);15581558+15591559+ val = isp116x_read_reg16(isp116x, HCCHIPID);15601560+ if ((val & HCCHIPID_MASK) != HCCHIPID_MAGIC) {15611561+ ERR("Invalid chip ID %04x\n", val);15621562+ spin_unlock_irqrestore(&isp116x->lock, flags);15631563+ return -ENODEV;15641564+ }15651565+15661566+ isp116x_write_reg16(isp116x, HCITLBUFLEN, ISP116x_ITL_BUFSIZE);15671567+ isp116x_write_reg16(isp116x, HCATLBUFLEN, ISP116x_ATL_BUFSIZE);15681568+15691569+ /* ----- HW conf */15701570+ val = HCHWCFG_INT_ENABLE | HCHWCFG_DBWIDTH(1);15711571+ if (board->sel15Kres)15721572+ val |= HCHWCFG_15KRSEL;15731573+ /* Remote wakeup won't work without working clock */15741574+ if (board->clknotstop || board->remote_wakeup_enable)15751575+ val |= HCHWCFG_CLKNOTSTOP;15761576+ if (board->oc_enable)15771577+ val |= HCHWCFG_ANALOG_OC;15781578+ if (board->int_act_high)15791579+ val |= HCHWCFG_INT_POL;15801580+ if (board->int_edge_triggered)15811581+ val |= HCHWCFG_INT_TRIGGER;15821582+ isp116x_write_reg16(isp116x, HCHWCFG, val);15831583+15841584+ /* ----- Root hub conf */15851585+ val = 0;15861586+ /* AN10003_1.pdf recommends NPS to be always 1 */15871587+ if (board->no_power_switching)15881588+ val |= RH_A_NPS;15891589+ if (board->power_switching_mode)15901590+ val |= RH_A_PSM;15911591+ if (board->potpg)15921592+ val |= (board->potpg << 24) & RH_A_POTPGT;15931593+ else15941594+ val |= (25 << 24) & RH_A_POTPGT;15951595+ isp116x_write_reg32(isp116x, HCRHDESCA, val);15961596+ isp116x->rhdesca = isp116x_read_reg32(isp116x, HCRHDESCA);15971597+15981598+ val = RH_B_PPCM;15991599+ isp116x_write_reg32(isp116x, HCRHDESCB, val);16001600+ isp116x->rhdescb = isp116x_read_reg32(isp116x, HCRHDESCB);16011601+16021602+ val = 0;16031603+ if (board->remote_wakeup_enable) {16041604+ hcd->can_wakeup = 1;16051605+ val |= RH_HS_DRWE;16061606+ }16071607+ isp116x_write_reg32(isp116x, HCRHSTATUS, val);16081608+ isp116x->rhstatus = isp116x_read_reg32(isp116x, HCRHSTATUS);16091609+16101610+ isp116x_write_reg32(isp116x, HCFMINTVL, 0x27782edf);16111611+16121612+ hcd->state = HC_STATE_RUNNING;16131613+16141614+ /* Set up interrupts */16151615+ isp116x->intenb = HCINT_MIE | HCINT_RHSC | HCINT_UE;16161616+ if (board->remote_wakeup_enable)16171617+ isp116x->intenb |= HCINT_RD;16181618+ isp116x->irqenb = HCuPINT_ATL | HCuPINT_OPR; /* | HCuPINT_SUSP; */16191619+ isp116x_write_reg32(isp116x, HCINTENB, isp116x->intenb);16201620+ isp116x_write_reg16(isp116x, HCuPINTENB, isp116x->irqenb);16211621+16221622+ /* Go operational */16231623+ val = HCCONTROL_USB_OPER;16241624+ /* Remote wakeup connected - NOT SUPPORTED */16251625+ /* if (board->remote_wakeup_connected)16261626+ val |= HCCONTROL_RWC; */16271627+ if (board->remote_wakeup_enable)16281628+ val |= HCCONTROL_RWE;16291629+ isp116x_write_reg32(isp116x, HCCONTROL, val);16301630+16311631+ /* Disable ports to avoid race in device enumeration */16321632+ isp116x_write_reg32(isp116x, HCRHPORT1, RH_PS_CCS);16331633+ isp116x_write_reg32(isp116x, HCRHPORT2, RH_PS_CCS);16341634+16351635+ isp116x_show_regs(isp116x);16361636+ spin_unlock_irqrestore(&isp116x->lock, flags);16371637+ return 0;16381638+}16391639+16401640+/*-----------------------------------------------------------------*/16411641+16421642+static struct hc_driver isp116x_hc_driver = {16431643+ .description = hcd_name,16441644+ .product_desc = "ISP116x Host Controller",16451645+ .hcd_priv_size = sizeof(struct isp116x),16461646+16471647+ .irq = isp116x_irq,16481648+ .flags = HCD_USB11,16491649+16501650+ .reset = isp116x_reset,16511651+ .start = isp116x_start,16521652+ .stop = isp116x_stop,16531653+16541654+ .urb_enqueue = isp116x_urb_enqueue,16551655+ .urb_dequeue = isp116x_urb_dequeue,16561656+ .endpoint_disable = isp116x_endpoint_disable,16571657+16581658+ .get_frame_number = isp116x_get_frame,16591659+16601660+ .hub_status_data = isp116x_hub_status_data,16611661+ .hub_control = isp116x_hub_control,16621662+ .hub_suspend = isp116x_hub_suspend,16631663+ .hub_resume = isp116x_hub_resume,16641664+};16651665+16661666+/*----------------------------------------------------------------*/16671667+16681668+static int __init_or_module isp116x_remove(struct device *dev)16691669+{16701670+ struct usb_hcd *hcd = dev_get_drvdata(dev);16711671+ struct isp116x *isp116x;16721672+ struct platform_device *pdev;16731673+ struct resource *res;16741674+16751675+ if(!hcd)16761676+ return 0;16771677+ isp116x = hcd_to_isp116x(hcd);16781678+ pdev = container_of(dev, struct platform_device, dev);16791679+ remove_debug_file(isp116x);16801680+ usb_remove_hcd(hcd);16811681+16821682+ iounmap(isp116x->data_reg);16831683+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);16841684+ release_mem_region(res->start, 2);16851685+ iounmap(isp116x->addr_reg);16861686+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);16871687+ release_mem_region(res->start, 2);16881688+16891689+ usb_put_hcd(hcd);16901690+ return 0;16911691+}16921692+16931693+#define resource_len(r) (((r)->end - (r)->start) + 1)16941694+16951695+static int __init isp116x_probe(struct device *dev)16961696+{16971697+ struct usb_hcd *hcd;16981698+ struct isp116x *isp116x;16991699+ struct platform_device *pdev;17001700+ struct resource *addr, *data;17011701+ void __iomem *addr_reg;17021702+ void __iomem *data_reg;17031703+ int irq;17041704+ int ret = 0;17051705+17061706+ pdev = container_of(dev, struct platform_device, dev);17071707+ if (pdev->num_resources < 3) {17081708+ ret = -ENODEV;17091709+ goto err1;17101710+ }17111711+17121712+ data = platform_get_resource(pdev, IORESOURCE_MEM, 0);17131713+ addr = platform_get_resource(pdev, IORESOURCE_MEM, 1);17141714+ irq = platform_get_irq(pdev, 0);17151715+ if (!addr || !data || irq < 0) {17161716+ ret = -ENODEV;17171717+ goto err1;17181718+ }17191719+17201720+ if (dev->dma_mask) {17211721+ DBG("DMA not supported\n");17221722+ ret = -EINVAL;17231723+ goto err1;17241724+ }17251725+17261726+ if (!request_mem_region(addr->start, 2, hcd_name)) {17271727+ ret = -EBUSY;17281728+ goto err1;17291729+ }17301730+ addr_reg = ioremap(addr->start, resource_len(addr));17311731+ if (addr_reg == NULL) {17321732+ ret = -ENOMEM;17331733+ goto err2;17341734+ }17351735+ if (!request_mem_region(data->start, 2, hcd_name)) {17361736+ ret = -EBUSY;17371737+ goto err3;17381738+ }17391739+ data_reg = ioremap(data->start, resource_len(data));17401740+ if (data_reg == NULL) {17411741+ ret = -ENOMEM;17421742+ goto err4;17431743+ }17441744+17451745+ /* allocate and initialize hcd */17461746+ hcd = usb_create_hcd(&isp116x_hc_driver, dev, dev->bus_id);17471747+ if (!hcd) {17481748+ ret = -ENOMEM;17491749+ goto err5;17501750+ }17511751+ /* this rsrc_start is bogus */17521752+ hcd->rsrc_start = addr->start;17531753+ isp116x = hcd_to_isp116x(hcd);17541754+ isp116x->data_reg = data_reg;17551755+ isp116x->addr_reg = addr_reg;17561756+ spin_lock_init(&isp116x->lock);17571757+ INIT_LIST_HEAD(&isp116x->async);17581758+ INIT_WORK(&isp116x->rh_resume, isp116x_rh_resume, hcd);17591759+ isp116x->board = dev->platform_data;17601760+17611761+ if (!isp116x->board) {17621762+ ERR("Platform data structure not initialized\n");17631763+ ret = -ENODEV;17641764+ goto err6;17651765+ }17661766+ if (isp116x_check_platform_delay(isp116x)) {17671767+ ERR("USE_PLATFORM_DELAY defined, but delay function not "17681768+ "implemented.\n");17691769+ ERR("See comments in drivers/usb/host/isp116x-hcd.c\n");17701770+ ret = -ENODEV;17711771+ goto err6;17721772+ }17731773+17741774+ ret = usb_add_hcd(hcd, irq, SA_INTERRUPT);17751775+ if (ret != 0)17761776+ goto err6;17771777+17781778+ create_debug_file(isp116x);17791779+ return 0;17801780+17811781+ err6:17821782+ usb_put_hcd(hcd);17831783+ err5:17841784+ iounmap(data_reg);17851785+ err4:17861786+ release_mem_region(data->start, 2);17871787+ err3:17881788+ iounmap(addr_reg);17891789+ err2:17901790+ release_mem_region(addr->start, 2);17911791+ err1:17921792+ ERR("init error, %d\n", ret);17931793+ return ret;17941794+}17951795+17961796+#ifdef CONFIG_PM17971797+/*17981798+ Suspend of platform device17991799+*/18001800+static int isp116x_suspend(struct device *dev, pm_message_t state, u32 phase)18011801+{18021802+ int ret = 0;18031803+ struct usb_hcd *hcd = dev_get_drvdata(dev);18041804+18051805+ VDBG("%s: state %x, phase %x\n", __func__, state, phase);18061806+18071807+ if (phase != SUSPEND_DISABLE && phase != SUSPEND_POWER_DOWN)18081808+ return 0;18091809+18101810+ ret = usb_suspend_device(hcd->self.root_hub, state);18111811+ if (!ret) {18121812+ dev->power.power_state = state;18131813+ INFO("%s suspended\n", (char *)hcd_name);18141814+ } else18151815+ ERR("%s suspend failed\n", (char *)hcd_name);18161816+18171817+ return ret;18181818+}18191819+18201820+/*18211821+ Resume platform device18221822+*/18231823+static int isp116x_resume(struct device *dev, u32 phase)18241824+{18251825+ int ret = 0;18261826+ struct usb_hcd *hcd = dev_get_drvdata(dev);18271827+18281828+ VDBG("%s: state %x, phase %x\n", __func__, dev->power.power_state,18291829+ phase);18301830+ if (phase != RESUME_POWER_ON)18311831+ return 0;18321832+18331833+ ret = usb_resume_device(hcd->self.root_hub);18341834+ if (!ret) {18351835+ dev->power.power_state = PMSG_ON;18361836+ VDBG("%s resumed\n", (char *)hcd_name);18371837+ }18381838+ return ret;18391839+}18401840+18411841+#else18421842+18431843+#define isp116x_suspend NULL18441844+#define isp116x_resume NULL18451845+18461846+#endif18471847+18481848+static struct device_driver isp116x_driver = {18491849+ .name = (char *)hcd_name,18501850+ .bus = &platform_bus_type,18511851+ .probe = isp116x_probe,18521852+ .remove = isp116x_remove,18531853+ .suspend = isp116x_suspend,18541854+ .resume = isp116x_resume,18551855+};18561856+18571857+/*-----------------------------------------------------------------*/18581858+18591859+static int __init isp116x_init(void)18601860+{18611861+ if (usb_disabled())18621862+ return -ENODEV;18631863+18641864+ INFO("driver %s, %s\n", hcd_name, DRIVER_VERSION);18651865+ return driver_register(&isp116x_driver);18661866+}18671867+18681868+module_init(isp116x_init);18691869+18701870+static void __exit isp116x_cleanup(void)18711871+{18721872+ driver_unregister(&isp116x_driver);18731873+}18741874+18751875+module_exit(isp116x_cleanup);
···181181 if (config->otg) {182182 ohci_to_hcd(ohci)->self.otg_port = config->otg;183183 /* default/minimum OTG power budget: 8 mA */184184- ohci->power_budget = 8;184184+ ohci_to_hcd(ohci)->power_budget = 8;185185 }186186187187 /* boards can use OTG transceivers in non-OTG modes */···230230231231 /* TPS2045 switch for internal transceiver (port 1) */232232 if (machine_is_omap_osk()) {233233- ohci->power_budget = 250;233233+ ohci_to_hcd(ohci)->power_budget = 250;234234235235 rh &= ~RH_A_NOCP;236236
+1-1
drivers/usb/host/ohci.h
···371371 * other external transceivers should be software-transparent 372372 */373373 struct otg_transceiver *transceiver;374374- unsigned power_budget;375374376375 /*377376 * memory management for queue data structures···389390 u32 fminterval; /* saved register */390391391392 struct work_struct rh_resume;393393+ struct notifier_block reboot_notifier;392394393395 unsigned long flags; /* for HC bugs */394396#define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */
+2-16
drivers/usb/host/sl811-hcd.c
···15631563sl811h_start(struct usb_hcd *hcd)15641564{15651565 struct sl811 *sl811 = hcd_to_sl811(hcd);15661566- struct usb_device *udev;1567156615681567 /* chip has been reset, VBUS power is off */15691569-15701570- udev = usb_alloc_dev(NULL, &hcd->self, 0);15711571- if (!udev)15721572- return -ENOMEM;15731573-15741574- udev->speed = USB_SPEED_FULL;15751568 hcd->state = HC_STATE_RUNNING;1576156915771577- if (sl811->board)15701570+ if (sl811->board) {15781571 hcd->can_wakeup = sl811->board->can_wakeup;15791579-15801580- if (usb_hcd_register_root_hub(udev, hcd) != 0) {15811581- usb_put_dev(udev);15821582- sl811h_stop(hcd);15831583- return -ENODEV;15721572+ hcd->power_budget = sl811->board->power * 2;15841573 }15851585-15861586- if (sl811->board && sl811->board->power)15871587- hub_set_power_budget(udev, sl811->board->power * 2);1588157415891575 /* enable power and interupts */15901576 port_power(sl811, 1);
+32
drivers/usb/host/uhci-debug.c
···237237 return out - buf;238238}239239240240+static int uhci_show_root_hub_state(struct uhci_hcd *uhci, char *buf, int len)241241+{242242+ char *out = buf;243243+ char *rh_state;244244+245245+ /* Try to make sure there's enough memory */246246+ if (len < 60)247247+ return 0;248248+249249+ switch (uhci->rh_state) {250250+ case UHCI_RH_RESET:251251+ rh_state = "reset"; break;252252+ case UHCI_RH_SUSPENDED:253253+ rh_state = "suspended"; break;254254+ case UHCI_RH_AUTO_STOPPED:255255+ rh_state = "auto-stopped"; break;256256+ case UHCI_RH_RESUMING:257257+ rh_state = "resuming"; break;258258+ case UHCI_RH_SUSPENDING:259259+ rh_state = "suspending"; break;260260+ case UHCI_RH_RUNNING:261261+ rh_state = "running"; break;262262+ case UHCI_RH_RUNNING_NODEVS:263263+ rh_state = "running, no devs"; break;264264+ default:265265+ rh_state = "?"; break;266266+ }267267+ out += sprintf(out, "Root-hub state: %s\n", rh_state);268268+ return out - buf;269269+}270270+240271static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len)241272{242273 char *out = buf;···439408440409 spin_lock_irqsave(&uhci->lock, flags);441410411411+ out += uhci_show_root_hub_state(uhci, out, len - (out - buf));442412 out += sprintf(out, "HC status\n");443413 out += uhci_show_status(uhci, out, len - (out - buf));444414
+452-367
drivers/usb/host/uhci-hcd.c
···1313 * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface1414 * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com).1515 * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)1616- * (C) Copyright 2004 Alan Stern, stern@rowland.harvard.edu1616+ * (C) Copyright 2004-2005 Alan Stern, stern@rowland.harvard.edu1717 *1818 * Intel documents this fairly well, and as far as I know there1919 * are no royalties or anything like that, but even so there are2020 * people who decided that they want to do the same thing in a2121 * completely different way.2222 *2323- * WARNING! The USB documentation is downright evil. Most of it2424- * is just crap, written by a committee. You're better off ignoring2525- * most of it, the important stuff is:2626- * - the low-level protocol (fairly simple but lots of small details)2727- * - working around the horridness of the rest2823 */29243025#include <linux/config.h>···5964/*6065 * Version Information6166 */6262-#define DRIVER_VERSION "v2.2"6767+#define DRIVER_VERSION "v2.3"6368#define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, \6469Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, \6570Alan Stern"···84898590static kmem_cache_t *uhci_up_cachep; /* urb_priv */86919292+static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state);9393+static void wakeup_rh(struct uhci_hcd *uhci);8794static void uhci_get_current_frame_number(struct uhci_hcd *uhci);8888-static void hc_state_transitions(struct uhci_hcd *uhci);89959096/* If a transfer is still active after this much time, turn off FSBR */9197#define IDLE_TIMEOUT msecs_to_jiffies(50)···97101/* to make sure it doesn't hog all of the bandwidth */98102#define DEPTH_INTERVAL 599103104104+static inline void restart_timer(struct uhci_hcd *uhci)105105+{106106+ mod_timer(&uhci->stall_timer, jiffies + msecs_to_jiffies(100));107107+}108108+100109#include "uhci-hub.c"101110#include "uhci-debug.c"102111#include "uhci-q.c"103112104104-static int init_stall_timer(struct usb_hcd *hcd);105105-106106-static void stall_callback(unsigned long ptr)113113+/*114114+ * Make sure the controller is completely inactive, unable to115115+ * generate interrupts or do DMA.116116+ */117117+static void reset_hc(struct uhci_hcd *uhci)107118{108108- struct usb_hcd *hcd = (struct usb_hcd *)ptr;109109- struct uhci_hcd *uhci = hcd_to_uhci(hcd);110110- struct urb_priv *up;119119+ int port;120120+121121+ /* Turn off PIRQ enable and SMI enable. (This also turns off the122122+ * BIOS's USB Legacy Support.) Turn off all the R/WC bits too.123123+ */124124+ pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,125125+ USBLEGSUP_RWC);126126+127127+ /* Reset the HC - this will force us to get a128128+ * new notification of any already connected129129+ * ports due to the virtual disconnect that it130130+ * implies.131131+ */132132+ outw(USBCMD_HCRESET, uhci->io_addr + USBCMD);133133+ mb();134134+ udelay(5);135135+ if (inw(uhci->io_addr + USBCMD) & USBCMD_HCRESET)136136+ dev_warn(uhci_dev(uhci), "HCRESET not completed yet!\n");137137+138138+ /* Just to be safe, disable interrupt requests and139139+ * make sure the controller is stopped.140140+ */141141+ outw(0, uhci->io_addr + USBINTR);142142+ outw(0, uhci->io_addr + USBCMD);143143+144144+ /* HCRESET doesn't affect the Suspend, Reset, and Resume Detect145145+ * bits in the port status and control registers.146146+ * We have to clear them by hand.147147+ */148148+ for (port = 0; port < uhci->rh_numports; ++port)149149+ outw(0, uhci->io_addr + USBPORTSC1 + (port * 2));150150+151151+ uhci->port_c_suspend = uhci->suspended_ports =152152+ uhci->resuming_ports = 0;153153+ uhci->rh_state = UHCI_RH_RESET;154154+ uhci->is_stopped = UHCI_IS_STOPPED;155155+ uhci_to_hcd(uhci)->state = HC_STATE_HALT;156156+ uhci_to_hcd(uhci)->poll_rh = 0;157157+}158158+159159+/*160160+ * Last rites for a defunct/nonfunctional controller161161+ * or one we don't want to use any more.162162+ */163163+static void hc_died(struct uhci_hcd *uhci)164164+{165165+ reset_hc(uhci);166166+ uhci->hc_inaccessible = 1;167167+ del_timer(&uhci->stall_timer);168168+}169169+170170+/*171171+ * Initialize a controller that was newly discovered or has just been172172+ * resumed. In either case we can't be sure of its previous state.173173+ */174174+static void check_and_reset_hc(struct uhci_hcd *uhci)175175+{176176+ u16 legsup;177177+ unsigned int cmd, intr;178178+179179+ /*180180+ * When restarting a suspended controller, we expect all the181181+ * settings to be the same as we left them:182182+ *183183+ * PIRQ and SMI disabled, no R/W bits set in USBLEGSUP;184184+ * Controller is stopped and configured with EGSM set;185185+ * No interrupts enabled except possibly Resume Detect.186186+ *187187+ * If any of these conditions are violated we do a complete reset.188188+ */189189+ pci_read_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, &legsup);190190+ if (legsup & ~(USBLEGSUP_RO | USBLEGSUP_RWC)) {191191+ dev_dbg(uhci_dev(uhci), "%s: legsup = 0x%04x\n",192192+ __FUNCTION__, legsup);193193+ goto reset_needed;194194+ }195195+196196+ cmd = inw(uhci->io_addr + USBCMD);197197+ if ((cmd & USBCMD_RS) || !(cmd & USBCMD_CF) || !(cmd & USBCMD_EGSM)) {198198+ dev_dbg(uhci_dev(uhci), "%s: cmd = 0x%04x\n",199199+ __FUNCTION__, cmd);200200+ goto reset_needed;201201+ }202202+203203+ intr = inw(uhci->io_addr + USBINTR);204204+ if (intr & (~USBINTR_RESUME)) {205205+ dev_dbg(uhci_dev(uhci), "%s: intr = 0x%04x\n",206206+ __FUNCTION__, intr);207207+ goto reset_needed;208208+ }209209+ return;210210+211211+reset_needed:212212+ dev_dbg(uhci_dev(uhci), "Performing full reset\n");213213+ reset_hc(uhci);214214+}215215+216216+/*217217+ * Store the basic register settings needed by the controller.218218+ */219219+static void configure_hc(struct uhci_hcd *uhci)220220+{221221+ /* Set the frame length to the default: 1 ms exactly */222222+ outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF);223223+224224+ /* Store the frame list base address */225225+ outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD);226226+227227+ /* Set the current frame number */228228+ outw(uhci->frame_number, uhci->io_addr + USBFRNUM);229229+230230+ /* Mark controller as running before we enable interrupts */231231+ uhci_to_hcd(uhci)->state = HC_STATE_RUNNING;232232+ mb();233233+234234+ /* Enable PIRQ */235235+ pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,236236+ USBLEGSUP_DEFAULT);237237+}238238+239239+240240+static int resume_detect_interrupts_are_broken(struct uhci_hcd *uhci)241241+{242242+ int port;243243+244244+ switch (to_pci_dev(uhci_dev(uhci))->vendor) {245245+ default:246246+ break;247247+248248+ case PCI_VENDOR_ID_GENESYS:249249+ /* Genesys Logic's GL880S controllers don't generate250250+ * resume-detect interrupts.251251+ */252252+ return 1;253253+254254+ case PCI_VENDOR_ID_INTEL:255255+ /* Some of Intel's USB controllers have a bug that causes256256+ * resume-detect interrupts if any port has an over-current257257+ * condition. To make matters worse, some motherboards258258+ * hardwire unused USB ports' over-current inputs active!259259+ * To prevent problems, we will not enable resume-detect260260+ * interrupts if any ports are OC.261261+ */262262+ for (port = 0; port < uhci->rh_numports; ++port) {263263+ if (inw(uhci->io_addr + USBPORTSC1 + port * 2) &264264+ USBPORTSC_OC)265265+ return 1;266266+ }267267+ break;268268+ }269269+ return 0;270270+}271271+272272+static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state)273273+__releases(uhci->lock)274274+__acquires(uhci->lock)275275+{276276+ int auto_stop;277277+ int int_enable;278278+279279+ auto_stop = (new_state == UHCI_RH_AUTO_STOPPED);280280+ dev_dbg(uhci_dev(uhci), "%s%s\n", __FUNCTION__,281281+ (auto_stop ? " (auto-stop)" : ""));282282+283283+ /* If we get a suspend request when we're already auto-stopped284284+ * then there's nothing to do.285285+ */286286+ if (uhci->rh_state == UHCI_RH_AUTO_STOPPED) {287287+ uhci->rh_state = new_state;288288+ return;289289+ }290290+291291+ /* Enable resume-detect interrupts if they work.292292+ * Then enter Global Suspend mode, still configured.293293+ */294294+ int_enable = (resume_detect_interrupts_are_broken(uhci) ?295295+ 0 : USBINTR_RESUME);296296+ outw(int_enable, uhci->io_addr + USBINTR);297297+ outw(USBCMD_EGSM | USBCMD_CF, uhci->io_addr + USBCMD);298298+ mb();299299+ udelay(5);300300+301301+ /* If we're auto-stopping then no devices have been attached302302+ * for a while, so there shouldn't be any active URBs and the303303+ * controller should stop after a few microseconds. Otherwise304304+ * we will give the controller one frame to stop.305305+ */306306+ if (!auto_stop && !(inw(uhci->io_addr + USBSTS) & USBSTS_HCH)) {307307+ uhci->rh_state = UHCI_RH_SUSPENDING;308308+ spin_unlock_irq(&uhci->lock);309309+ msleep(1);310310+ spin_lock_irq(&uhci->lock);311311+ if (uhci->hc_inaccessible) /* Died */312312+ return;313313+ }314314+ if (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH))315315+ dev_warn(uhci_dev(uhci), "Controller not stopped yet!\n");316316+317317+ uhci_get_current_frame_number(uhci);318318+ smp_wmb();319319+320320+ uhci->rh_state = new_state;321321+ uhci->is_stopped = UHCI_IS_STOPPED;322322+ del_timer(&uhci->stall_timer);323323+ uhci_to_hcd(uhci)->poll_rh = !int_enable;324324+325325+ uhci_scan_schedule(uhci, NULL);326326+}327327+328328+static void start_rh(struct uhci_hcd *uhci)329329+{330330+ uhci->is_stopped = 0;331331+ smp_wmb();332332+333333+ /* Mark it configured and running with a 64-byte max packet.334334+ * All interrupts are enabled, even though RESUME won't do anything.335335+ */336336+ outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, uhci->io_addr + USBCMD);337337+ outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP,338338+ uhci->io_addr + USBINTR);339339+ mb();340340+ uhci->rh_state = UHCI_RH_RUNNING;341341+ uhci_to_hcd(uhci)->poll_rh = 1;342342+ restart_timer(uhci);343343+}344344+345345+static void wakeup_rh(struct uhci_hcd *uhci)346346+__releases(uhci->lock)347347+__acquires(uhci->lock)348348+{349349+ dev_dbg(uhci_dev(uhci), "%s%s\n", __FUNCTION__,350350+ uhci->rh_state == UHCI_RH_AUTO_STOPPED ?351351+ " (auto-start)" : "");352352+353353+ /* If we are auto-stopped then no devices are attached so there's354354+ * no need for wakeup signals. Otherwise we send Global Resume355355+ * for 20 ms.356356+ */357357+ if (uhci->rh_state == UHCI_RH_SUSPENDED) {358358+ uhci->rh_state = UHCI_RH_RESUMING;359359+ outw(USBCMD_FGR | USBCMD_EGSM | USBCMD_CF,360360+ uhci->io_addr + USBCMD);361361+ spin_unlock_irq(&uhci->lock);362362+ msleep(20);363363+ spin_lock_irq(&uhci->lock);364364+ if (uhci->hc_inaccessible) /* Died */365365+ return;366366+367367+ /* End Global Resume and wait for EOP to be sent */368368+ outw(USBCMD_CF, uhci->io_addr + USBCMD);369369+ mb();370370+ udelay(4);371371+ if (inw(uhci->io_addr + USBCMD) & USBCMD_FGR)372372+ dev_warn(uhci_dev(uhci), "FGR not stopped yet!\n");373373+ }374374+375375+ start_rh(uhci);376376+377377+ /* Restart root hub polling */378378+ mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies);379379+}380380+381381+static void stall_callback(unsigned long _uhci)382382+{383383+ struct uhci_hcd *uhci = (struct uhci_hcd *) _uhci;111384 unsigned long flags;112385113386 spin_lock_irqsave(&uhci->lock, flags);114387 uhci_scan_schedule(uhci, NULL);388388+ check_fsbr(uhci);115389116116- list_for_each_entry(up, &uhci->urb_list, urb_list) {117117- struct urb *u = up->urb;118118-119119- spin_lock(&u->lock);120120-121121- /* Check if the FSBR timed out */122122- if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies, up->fsbrtime + IDLE_TIMEOUT))123123- uhci_fsbr_timeout(uhci, u);124124-125125- spin_unlock(&u->lock);126126- }127127-128128- /* Really disable FSBR */129129- if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) {130130- uhci->fsbrtimeout = 0;131131- uhci->skel_term_qh->link = UHCI_PTR_TERM;132132- }133133-134134- /* Poll for and perform state transitions */135135- hc_state_transitions(uhci);136136- if (unlikely(uhci->suspended_ports && uhci->state != UHCI_SUSPENDED))137137- uhci_check_ports(uhci);138138-139139- init_stall_timer(hcd);390390+ if (!uhci->is_stopped)391391+ restart_timer(uhci);140392 spin_unlock_irqrestore(&uhci->lock, flags);141141-}142142-143143-static int init_stall_timer(struct usb_hcd *hcd)144144-{145145- struct uhci_hcd *uhci = hcd_to_uhci(hcd);146146-147147- init_timer(&uhci->stall_timer);148148- uhci->stall_timer.function = stall_callback;149149- uhci->stall_timer.data = (unsigned long)hcd;150150- uhci->stall_timer.expires = jiffies + msecs_to_jiffies(100);151151- add_timer(&uhci->stall_timer);152152-153153- return 0;154393}155394156395static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)157396{158397 struct uhci_hcd *uhci = hcd_to_uhci(hcd);159159- unsigned long io_addr = uhci->io_addr;160398 unsigned short status;399399+ unsigned long flags;161400162401 /*163402 * Read the interrupt status, and write it back to clear the164403 * interrupt cause. Contrary to the UHCI specification, the165404 * "HC Halted" status bit is persistent: it is RO, not R/WC.166405 */167167- status = inw(io_addr + USBSTS);406406+ status = inw(uhci->io_addr + USBSTS);168407 if (!(status & ~USBSTS_HCH)) /* shared interrupt, not mine */169408 return IRQ_NONE;170170- outw(status, io_addr + USBSTS); /* Clear it */409409+ outw(status, uhci->io_addr + USBSTS); /* Clear it */171410172411 if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) {173412 if (status & USBSTS_HSE)···411180 if (status & USBSTS_HCPE)412181 dev_err(uhci_dev(uhci), "host controller process "413182 "error, something bad happened!\n");414414- if ((status & USBSTS_HCH) && uhci->state > 0) {415415- dev_err(uhci_dev(uhci), "host controller halted, "183183+ if (status & USBSTS_HCH) {184184+ spin_lock_irqsave(&uhci->lock, flags);185185+ if (uhci->rh_state >= UHCI_RH_RUNNING) {186186+ dev_err(uhci_dev(uhci),187187+ "host controller halted, "416188 "very bad!\n");417417- /* FIXME: Reset the controller, fix the offending TD */189189+ hc_died(uhci);190190+ spin_unlock_irqrestore(&uhci->lock, flags);191191+ return IRQ_HANDLED;192192+ }193193+ spin_unlock_irqrestore(&uhci->lock, flags);418194 }419195 }420196421197 if (status & USBSTS_RD)422422- uhci->resume_detect = 1;198198+ usb_hcd_poll_rh_status(hcd);423199424424- spin_lock(&uhci->lock);200200+ spin_lock_irqsave(&uhci->lock, flags);425201 uhci_scan_schedule(uhci, regs);426426- spin_unlock(&uhci->lock);202202+ spin_unlock_irqrestore(&uhci->lock, flags);427203428204 return IRQ_HANDLED;429429-}430430-431431-static void reset_hc(struct uhci_hcd *uhci)432432-{433433- unsigned long io_addr = uhci->io_addr;434434-435435- /* Turn off PIRQ, SMI, and all interrupts. This also turns off436436- * the BIOS's USB Legacy Support.437437- */438438- pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0);439439- outw(0, uhci->io_addr + USBINTR);440440-441441- /* Global reset for 50ms */442442- uhci->state = UHCI_RESET;443443- outw(USBCMD_GRESET, io_addr + USBCMD);444444- msleep(50);445445- outw(0, io_addr + USBCMD);446446-447447- /* Another 10ms delay */448448- msleep(10);449449- uhci->resume_detect = 0;450450- uhci->is_stopped = UHCI_IS_STOPPED;451451-}452452-453453-static void suspend_hc(struct uhci_hcd *uhci)454454-{455455- unsigned long io_addr = uhci->io_addr;456456-457457- dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);458458- uhci->state = UHCI_SUSPENDED;459459- uhci->resume_detect = 0;460460- outw(USBCMD_EGSM, io_addr + USBCMD);461461-462462- /* FIXME: Wait for the controller to actually stop */463463- uhci_get_current_frame_number(uhci);464464- uhci->is_stopped = UHCI_IS_STOPPED;465465-466466- uhci_scan_schedule(uhci, NULL);467467-}468468-469469-static void wakeup_hc(struct uhci_hcd *uhci)470470-{471471- unsigned long io_addr = uhci->io_addr;472472-473473- switch (uhci->state) {474474- case UHCI_SUSPENDED: /* Start the resume */475475- dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);476476-477477- /* Global resume for >= 20ms */478478- outw(USBCMD_FGR | USBCMD_EGSM, io_addr + USBCMD);479479- uhci->state = UHCI_RESUMING_1;480480- uhci->state_end = jiffies + msecs_to_jiffies(20);481481- uhci->is_stopped = 0;482482- break;483483-484484- case UHCI_RESUMING_1: /* End global resume */485485- uhci->state = UHCI_RESUMING_2;486486- outw(0, io_addr + USBCMD);487487- /* Falls through */488488-489489- case UHCI_RESUMING_2: /* Wait for EOP to be sent */490490- if (inw(io_addr + USBCMD) & USBCMD_FGR)491491- break;492492-493493- /* Run for at least 1 second, and494494- * mark it configured with a 64-byte max packet */495495- uhci->state = UHCI_RUNNING_GRACE;496496- uhci->state_end = jiffies + HZ;497497- outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP,498498- io_addr + USBCMD);499499- break;500500-501501- case UHCI_RUNNING_GRACE: /* Now allowed to suspend */502502- uhci->state = UHCI_RUNNING;503503- break;504504-505505- default:506506- break;507507- }508508-}509509-510510-static int ports_active(struct uhci_hcd *uhci)511511-{512512- unsigned long io_addr = uhci->io_addr;513513- int connection = 0;514514- int i;515515-516516- for (i = 0; i < uhci->rh_numports; i++)517517- connection |= (inw(io_addr + USBPORTSC1 + i * 2) & USBPORTSC_CCS);518518-519519- return connection;520520-}521521-522522-static int suspend_allowed(struct uhci_hcd *uhci)523523-{524524- unsigned long io_addr = uhci->io_addr;525525- int i;526526-527527- if (to_pci_dev(uhci_dev(uhci))->vendor != PCI_VENDOR_ID_INTEL)528528- return 1;529529-530530- /* Some of Intel's USB controllers have a bug that causes false531531- * resume indications if any port has an over current condition.532532- * To prevent problems, we will not allow a global suspend if533533- * any ports are OC.534534- *535535- * Some motherboards using Intel's chipsets (but not using all536536- * the USB ports) appear to hardwire the over current inputs active537537- * to disable the USB ports.538538- */539539-540540- /* check for over current condition on any port */541541- for (i = 0; i < uhci->rh_numports; i++) {542542- if (inw(io_addr + USBPORTSC1 + i * 2) & USBPORTSC_OC)543543- return 0;544544- }545545-546546- return 1;547547-}548548-549549-static void hc_state_transitions(struct uhci_hcd *uhci)550550-{551551- switch (uhci->state) {552552- case UHCI_RUNNING:553553-554554- /* global suspend if nothing connected for 1 second */555555- if (!ports_active(uhci) && suspend_allowed(uhci)) {556556- uhci->state = UHCI_SUSPENDING_GRACE;557557- uhci->state_end = jiffies + HZ;558558- }559559- break;560560-561561- case UHCI_SUSPENDING_GRACE:562562- if (ports_active(uhci))563563- uhci->state = UHCI_RUNNING;564564- else if (time_after_eq(jiffies, uhci->state_end))565565- suspend_hc(uhci);566566- break;567567-568568- case UHCI_SUSPENDED:569569-570570- /* wakeup if requested by a device */571571- if (uhci->resume_detect)572572- wakeup_hc(uhci);573573- break;574574-575575- case UHCI_RESUMING_1:576576- case UHCI_RESUMING_2:577577- case UHCI_RUNNING_GRACE:578578- if (time_after_eq(jiffies, uhci->state_end))579579- wakeup_hc(uhci);580580- break;581581-582582- default:583583- break;584584- }585205}586206587207/*···443361{444362 if (!uhci->is_stopped)445363 uhci->frame_number = inw(uhci->io_addr + USBFRNUM);446446-}447447-448448-static int start_hc(struct uhci_hcd *uhci)449449-{450450- unsigned long io_addr = uhci->io_addr;451451- int timeout = 10;452452-453453- /*454454- * Reset the HC - this will force us to get a455455- * new notification of any already connected456456- * ports due to the virtual disconnect that it457457- * implies.458458- */459459- outw(USBCMD_HCRESET, io_addr + USBCMD);460460- while (inw(io_addr + USBCMD) & USBCMD_HCRESET) {461461- if (--timeout < 0) {462462- dev_err(uhci_dev(uhci), "USBCMD_HCRESET timed out!\n");463463- return -ETIMEDOUT;464464- }465465- msleep(1);466466- }467467-468468- /* Mark controller as running before we enable interrupts */469469- uhci_to_hcd(uhci)->state = HC_STATE_RUNNING;470470-471471- /* Turn on PIRQ and all interrupts */472472- pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,473473- USBLEGSUP_DEFAULT);474474- outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP,475475- io_addr + USBINTR);476476-477477- /* Start at frame 0 */478478- outw(0, io_addr + USBFRNUM);479479- outl(uhci->fl->dma_handle, io_addr + USBFLBASEADD);480480-481481- /* Run and mark it configured with a 64-byte max packet */482482- uhci->state = UHCI_RUNNING_GRACE;483483- uhci->state_end = jiffies + HZ;484484- outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD);485485- uhci->is_stopped = 0;486486-487487- return 0;488364}489365490366/*···488448static int uhci_reset(struct usb_hcd *hcd)489449{490450 struct uhci_hcd *uhci = hcd_to_uhci(hcd);451451+ unsigned io_size = (unsigned) hcd->rsrc_len;452452+ int port;491453492454 uhci->io_addr = (unsigned long) hcd->rsrc_start;493455494494- /* Kick BIOS off this hardware and reset, so we won't get495495- * interrupts from any previous setup.456456+ /* The UHCI spec says devices must have 2 ports, and goes on to say457457+ * they may have more but gives no way to determine how many there458458+ * are. However according to the UHCI spec, Bit 7 of the port459459+ * status and control register is always set to 1. So we try to460460+ * use this to our advantage. Another common failure mode when461461+ * a nonexistent register is addressed is to return all ones, so462462+ * we test for that also.496463 */497497- reset_hc(uhci);464464+ for (port = 0; port < (io_size - USBPORTSC1) / 2; port++) {465465+ unsigned int portstatus;466466+467467+ portstatus = inw(uhci->io_addr + USBPORTSC1 + (port * 2));468468+ if (!(portstatus & 0x0080) || portstatus == 0xffff)469469+ break;470470+ }471471+ if (debug)472472+ dev_info(uhci_dev(uhci), "detected %d ports\n", port);473473+474474+ /* Anything greater than 7 is weird so we'll ignore it. */475475+ if (port > UHCI_RH_MAXCHILD) {476476+ dev_info(uhci_dev(uhci), "port count misdetected? "477477+ "forcing to 2 ports\n");478478+ port = 2;479479+ }480480+ uhci->rh_numports = port;481481+482482+ /* Kick BIOS off this hardware and reset if the controller483483+ * isn't already safely quiescent.484484+ */485485+ check_and_reset_hc(uhci);498486 return 0;487487+}488488+489489+/* Make sure the controller is quiescent and that we're not using it490490+ * any more. This is mainly for the benefit of programs which, like kexec,491491+ * expect the hardware to be idle: not doing DMA or generating IRQs.492492+ *493493+ * This routine may be called in a damaged or failing kernel. Hence we494494+ * do not acquire the spinlock before shutting down the controller.495495+ */496496+static void uhci_shutdown(struct pci_dev *pdev)497497+{498498+ struct usb_hcd *hcd = (struct usb_hcd *) pci_get_drvdata(pdev);499499+500500+ hc_died(hcd_to_uhci(hcd));499501}500502501503/*···560478{561479 struct uhci_hcd *uhci = hcd_to_uhci(hcd);562480 int retval = -EBUSY;563563- int i, port;564564- unsigned io_size;481481+ int i;565482 dma_addr_t dma_handle;566566- struct usb_device *udev;567483 struct dentry *dentry;568484569569- io_size = (unsigned) hcd->rsrc_len;485485+ hcd->uses_new_polling = 1;486486+ if (pci_find_capability(to_pci_dev(uhci_dev(uhci)), PCI_CAP_ID_PM))487487+ hcd->can_wakeup = 1; /* Assume it supports PME# */570488571571- dentry = debugfs_create_file(hcd->self.bus_name, S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root, uhci, &uhci_debug_operations);489489+ dentry = debugfs_create_file(hcd->self.bus_name,490490+ S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root, uhci,491491+ &uhci_debug_operations);572492 if (!dentry) {573573- dev_err(uhci_dev(uhci), "couldn't create uhci debugfs entry\n");493493+ dev_err(uhci_dev(uhci),494494+ "couldn't create uhci debugfs entry\n");574495 retval = -ENOMEM;575496 goto err_create_debug_entry;576497 }···594509 INIT_LIST_HEAD(&uhci->complete_list);595510596511 init_waitqueue_head(&uhci->waitqh);512512+513513+ init_timer(&uhci->stall_timer);514514+ uhci->stall_timer.function = stall_callback;515515+ uhci->stall_timer.data = (unsigned long) uhci;597516598517 uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl),599518 &dma_handle, 0);···625536 goto err_create_qh_pool;626537 }627538628628- /* Initialize the root hub */629629-630630- /* UHCI specs says devices must have 2 ports, but goes on to say */631631- /* they may have more but give no way to determine how many they */632632- /* have. However, according to the UHCI spec, Bit 7 is always set */633633- /* to 1. So we try to use this to our advantage */634634- for (port = 0; port < (io_size - 0x10) / 2; port++) {635635- unsigned int portstatus;636636-637637- portstatus = inw(uhci->io_addr + 0x10 + (port * 2));638638- if (!(portstatus & 0x0080))639639- break;640640- }641641- if (debug)642642- dev_info(uhci_dev(uhci), "detected %d ports\n", port);643643-644644- /* This is experimental so anything less than 2 or greater than 8 is */645645- /* something weird and we'll ignore it */646646- if (port < 2 || port > UHCI_RH_MAXCHILD) {647647- dev_info(uhci_dev(uhci), "port count misdetected? "648648- "forcing to 2 ports\n");649649- port = 2;650650- }651651-652652- uhci->rh_numports = port;653653-654654- udev = usb_alloc_dev(NULL, &hcd->self, 0);655655- if (!udev) {656656- dev_err(uhci_dev(uhci), "unable to allocate root hub\n");657657- goto err_alloc_root_hub;658658- }659659-660660- uhci->term_td = uhci_alloc_td(uhci, udev);539539+ uhci->term_td = uhci_alloc_td(uhci);661540 if (!uhci->term_td) {662541 dev_err(uhci_dev(uhci), "unable to allocate terminating TD\n");663542 goto err_alloc_term_td;664543 }665544666545 for (i = 0; i < UHCI_NUM_SKELQH; i++) {667667- uhci->skelqh[i] = uhci_alloc_qh(uhci, udev);546546+ uhci->skelqh[i] = uhci_alloc_qh(uhci);668547 if (!uhci->skelqh[i]) {669548 dev_err(uhci_dev(uhci), "unable to allocate QH\n");670549 goto err_alloc_skelqh;···698641699642 /*700643 * Some architectures require a full mb() to enforce completion of701701- * the memory writes above before the I/O transfers in start_hc().644644+ * the memory writes above before the I/O transfers in configure_hc().702645 */703646 mb();704704- if ((retval = start_hc(uhci)) != 0)705705- goto err_alloc_skelqh;706647707707- init_stall_timer(hcd);708708-709709- udev->speed = USB_SPEED_FULL;710710-711711- if (usb_hcd_register_root_hub(udev, hcd) != 0) {712712- dev_err(uhci_dev(uhci), "unable to start root hub\n");713713- retval = -ENOMEM;714714- goto err_start_root_hub;715715- }716716-648648+ configure_hc(uhci);649649+ start_rh(uhci);717650 return 0;718651719652/*720653 * error exits:721654 */722722-err_start_root_hub:723723- reset_hc(uhci);724724-725725- del_timer_sync(&uhci->stall_timer);726726-727655err_alloc_skelqh:728656 for (i = 0; i < UHCI_NUM_SKELQH; i++)729657 if (uhci->skelqh[i]) {···720678 uhci->term_td = NULL;721679722680err_alloc_term_td:723723- usb_put_dev(udev);724724-725725-err_alloc_root_hub:726681 dma_pool_destroy(uhci->qh_pool);727682 uhci->qh_pool = NULL;728683···744705{745706 struct uhci_hcd *uhci = hcd_to_uhci(hcd);746707747747- del_timer_sync(&uhci->stall_timer);748748- reset_hc(uhci);749749-750708 spin_lock_irq(&uhci->lock);709709+ reset_hc(uhci);751710 uhci_scan_schedule(uhci, NULL);752711 spin_unlock_irq(&uhci->lock);753753-712712+713713+ del_timer_sync(&uhci->stall_timer);754714 release_uhci(uhci);755715}756716757717#ifdef CONFIG_PM758758-static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)718718+static int uhci_rh_suspend(struct usb_hcd *hcd)759719{760720 struct uhci_hcd *uhci = hcd_to_uhci(hcd);761721762722 spin_lock_irq(&uhci->lock);763763-764764- /* Don't try to suspend broken motherboards, reset instead */765765- if (suspend_allowed(uhci))766766- suspend_hc(uhci);767767- else {768768- spin_unlock_irq(&uhci->lock);769769- reset_hc(uhci);770770- spin_lock_irq(&uhci->lock);771771- uhci_scan_schedule(uhci, NULL);772772- }773773-723723+ if (!uhci->hc_inaccessible) /* Not dead */724724+ suspend_rh(uhci, UHCI_RH_SUSPENDED);774725 spin_unlock_irq(&uhci->lock);775726 return 0;727727+}728728+729729+static int uhci_rh_resume(struct usb_hcd *hcd)730730+{731731+ struct uhci_hcd *uhci = hcd_to_uhci(hcd);732732+ int rc = 0;733733+734734+ spin_lock_irq(&uhci->lock);735735+ if (uhci->hc_inaccessible) {736736+ if (uhci->rh_state == UHCI_RH_SUSPENDED) {737737+ dev_warn(uhci_dev(uhci), "HC isn't running!\n");738738+ rc = -ENODEV;739739+ }740740+ /* Otherwise the HC is dead */741741+ } else742742+ wakeup_rh(uhci);743743+ spin_unlock_irq(&uhci->lock);744744+ return rc;745745+}746746+747747+static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)748748+{749749+ struct uhci_hcd *uhci = hcd_to_uhci(hcd);750750+ int rc = 0;751751+752752+ dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);753753+754754+ spin_lock_irq(&uhci->lock);755755+ if (uhci->hc_inaccessible) /* Dead or already suspended */756756+ goto done;757757+758758+#ifndef CONFIG_USB_SUSPEND759759+ /* Otherwise this would never happen */760760+ suspend_rh(uhci, UHCI_RH_SUSPENDED);761761+#endif762762+763763+ if (uhci->rh_state > UHCI_RH_SUSPENDED) {764764+ dev_warn(uhci_dev(uhci), "Root hub isn't suspended!\n");765765+ hcd->state = HC_STATE_RUNNING;766766+ rc = -EBUSY;767767+ goto done;768768+ };769769+770770+ /* All PCI host controllers are required to disable IRQ generation771771+ * at the source, so we must turn off PIRQ.772772+ */773773+ pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0);774774+ uhci->hc_inaccessible = 1;775775+776776+ /* FIXME: Enable non-PME# remote wakeup? */777777+778778+done:779779+ spin_unlock_irq(&uhci->lock);780780+ if (rc == 0)781781+ del_timer_sync(&hcd->rh_timer);782782+ return rc;776783}777784778785static int uhci_resume(struct usb_hcd *hcd)779786{780787 struct uhci_hcd *uhci = hcd_to_uhci(hcd);781781- int rc;782788783783- pci_set_master(to_pci_dev(uhci_dev(uhci)));789789+ dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);784790791791+ if (uhci->rh_state == UHCI_RH_RESET) /* Dead */792792+ return 0;785793 spin_lock_irq(&uhci->lock);786794787787- if (uhci->state == UHCI_SUSPENDED) {795795+ /* FIXME: Disable non-PME# remote wakeup? */788796789789- /*790790- * Some systems don't maintain the UHCI register values791791- * during a PM suspend/resume cycle, so reinitialize792792- * the Frame Number, Framelist Base Address, Interrupt793793- * Enable, and Legacy Support registers.794794- */795795- pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,796796- 0);797797- outw(uhci->frame_number, uhci->io_addr + USBFRNUM);798798- outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD);799799- outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC |800800- USBINTR_SP, uhci->io_addr + USBINTR);801801- uhci->resume_detect = 1;802802- pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,803803- USBLEGSUP_DEFAULT);804804- } else {805805- spin_unlock_irq(&uhci->lock);806806- reset_hc(uhci);807807- if ((rc = start_hc(uhci)) != 0)808808- return rc;809809- spin_lock_irq(&uhci->lock);810810- }811811- hcd->state = HC_STATE_RUNNING;797797+ uhci->hc_inaccessible = 0;798798+799799+ /* The BIOS may have changed the controller settings during a800800+ * system wakeup. Check it and reconfigure to avoid problems.801801+ */802802+ check_and_reset_hc(uhci);803803+ configure_hc(uhci);804804+805805+#ifndef CONFIG_USB_SUSPEND806806+ /* Otherwise this would never happen */807807+ wakeup_rh(uhci);808808+#endif809809+ if (uhci->rh_state == UHCI_RH_RESET)810810+ suspend_rh(uhci, UHCI_RH_SUSPENDED);812811813812 spin_unlock_irq(&uhci->lock);813813+814814+ if (hcd->poll_rh)815815+ usb_hcd_poll_rh_status(hcd);814816 return 0;815817}816818#endif···868788static int uhci_hcd_get_frame_number(struct usb_hcd *hcd)869789{870790 struct uhci_hcd *uhci = hcd_to_uhci(hcd);871871- int frame_number;872791 unsigned long flags;792792+ int is_stopped;793793+ int frame_number;873794874795 /* Minimize latency by avoiding the spinlock */875796 local_irq_save(flags);876876- rmb();877877- frame_number = (uhci->is_stopped ? uhci->frame_number :797797+ is_stopped = uhci->is_stopped;798798+ smp_rmb();799799+ frame_number = (is_stopped ? uhci->frame_number :878800 inw(uhci->io_addr + USBFRNUM));879801 local_irq_restore(flags);880802 return frame_number;···899817#ifdef CONFIG_PM900818 .suspend = uhci_suspend,901819 .resume = uhci_resume,820820+ .hub_suspend = uhci_rh_suspend,821821+ .hub_resume = uhci_rh_resume,902822#endif903823 .stop = uhci_stop,904824···929845930846 .probe = usb_hcd_pci_probe,931847 .remove = usb_hcd_pci_remove,848848+ .shutdown = uhci_shutdown,932849933850#ifdef CONFIG_PM934851 .suspend = usb_hcd_pci_suspend,
+37-22
drivers/usb/host/uhci-hcd.h
···4141#define USBFRNUM 64242#define USBFLBASEADD 84343#define USBSOF 124444+#define USBSOF_DEFAULT 64 /* Frame length is exactly 1 ms */44454546/* USB port status and control registers */4647#define USBPORTSC1 16···6766/* Legacy support register */6867#define USBLEGSUP 0xc06968#define USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */6969+#define USBLEGSUP_RWC 0x8f00 /* the R/WC bits */7070+#define USBLEGSUP_RO 0x5040 /* R/O and reserved bits */70717172#define UHCI_NULL_DATA_SIZE 0x7FF /* for UHCI controller TD */7273···114111 /* Software fields */115112 dma_addr_t dma_handle;116113117117- struct usb_device *dev;118114 struct urb_priv *urbp;119115120116 struct list_head list; /* P: uhci->frame_list_lock */···205203 /* Software fields */206204 dma_addr_t dma_handle;207205208208- struct usb_device *dev;209206 struct urb *urb;210207211208 struct list_head list; /* P: urb->lock */···315314}316315317316/*318318- * Device states for the host controller.317317+ * States for the root hub.319318 *320319 * To prevent "bouncing" in the presence of electrical noise,321321- * we insist on a 1-second "grace" period, before switching to322322- * the RUNNING or SUSPENDED states, during which the state is323323- * not allowed to change.324324- *325325- * The resume process is divided into substates in order to avoid326326- * potentially length delays during the timer handler.327327- *328328- * States in which the host controller is halted must have values <= 0.320320+ * when there are no devices attached we delay for 1 second in the321321+ * RUNNING_NODEVS state before switching to the AUTO_STOPPED state.322322+ * 323323+ * (Note that the AUTO_STOPPED state won't be necessary once the hub324324+ * driver learns to autosuspend.)329325 */330330-enum uhci_state {331331- UHCI_RESET,332332- UHCI_RUNNING_GRACE, /* Before RUNNING */333333- UHCI_RUNNING, /* The normal state */334334- UHCI_SUSPENDING_GRACE, /* Before SUSPENDED */335335- UHCI_SUSPENDED = -10, /* When no devices are attached */336336- UHCI_RESUMING_1,337337- UHCI_RESUMING_2326326+enum uhci_rh_state {327327+ /* In the following states the HC must be halted.328328+ * These two must come first */329329+ UHCI_RH_RESET,330330+ UHCI_RH_SUSPENDED,331331+332332+ UHCI_RH_AUTO_STOPPED,333333+ UHCI_RH_RESUMING,334334+335335+ /* In this state the HC changes from running to halted,336336+ * so it can legally appear either way. */337337+ UHCI_RH_SUSPENDING,338338+339339+ /* In the following states it's an error if the HC is halted.340340+ * These two must come last */341341+ UHCI_RH_RUNNING, /* The normal state */342342+ UHCI_RH_RUNNING_NODEVS, /* Running with no devices attached */338343};339344340345/*···370363 int fsbr; /* Full-speed bandwidth reclamation */371364 unsigned long fsbrtimeout; /* FSBR delay */372365373373- enum uhci_state state; /* FIXME: needs a spinlock */374374- unsigned long state_end; /* Time of next transition */366366+ enum uhci_rh_state rh_state;367367+ unsigned long auto_stop_time; /* When to AUTO_STOP */368368+375369 unsigned int frame_number; /* As of last check */376370 unsigned int is_stopped;377371#define UHCI_IS_STOPPED 9999 /* Larger than a frame # */378372379373 unsigned int scan_in_progress:1; /* Schedule scan is running */380374 unsigned int need_rescan:1; /* Redo the schedule scan */381381- unsigned int resume_detect:1; /* Need a Global Resume */375375+ unsigned int hc_inaccessible:1; /* HC is suspended or dead */382376383377 /* Support for port suspend/resume/reset */384378 unsigned long port_c_suspend; /* Bit-arrays of ports */···458450 * #1 uhci->lock459451 * #2 urb->lock460452 */453453+454454+455455+/* Some special IDs */456456+457457+#define PCI_VENDOR_ID_GENESYS 0x17a0458458+#define PCI_DEVICE_ID_GL880S_UHCI 0x8083459459+#define PCI_DEVICE_ID_GL880S_EHCI 0x8084461460462461#endif
+79-4
drivers/usb/host/uhci-hub.c
···3333/* status change bits: nonzero writes will clear */3434#define RWC_BITS (USBPORTSC_OCC | USBPORTSC_PEC | USBPORTSC_CSC)35353636-static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)3636+/* A port that either is connected or has a changed-bit set will prevent3737+ * us from AUTO_STOPPING.3838+ */3939+static int any_ports_active(struct uhci_hcd *uhci)3740{3838- struct uhci_hcd *uhci = hcd_to_uhci(hcd);4141+ int port;4242+4343+ for (port = 0; port < uhci->rh_numports; ++port) {4444+ if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) &4545+ (USBPORTSC_CCS | RWC_BITS)) ||4646+ test_bit(port, &uhci->port_c_suspend))4747+ return 1;4848+ }4949+ return 0;5050+}5151+5252+static inline int get_hub_status_data(struct uhci_hcd *uhci, char *buf)5353+{3954 int port;40554156 *buf = 0;···5944 test_bit(port, &uhci->port_c_suspend))6045 *buf |= (1 << (port + 1));6146 }6262- if (*buf && uhci->state == UHCI_SUSPENDED)6363- uhci->resume_detect = 1;6447 return !!*buf;6548}6649···128115 set_bit(port, &uhci->resuming_ports);129116 uhci->ports_timeout = jiffies +130117 msecs_to_jiffies(20);118118+119119+ /* Make sure we see the port again120120+ * after the resuming period is over. */121121+ mod_timer(&uhci_to_hcd(uhci)->rh_timer,122122+ uhci->ports_timeout);131123 } else if (time_after_eq(jiffies,132124 uhci->ports_timeout)) {133125 uhci_finish_suspend(uhci, port, port_addr);134126 }135127 }136128 }129129+}130130+131131+static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)132132+{133133+ struct uhci_hcd *uhci = hcd_to_uhci(hcd);134134+ unsigned long flags;135135+ int status;136136+137137+ spin_lock_irqsave(&uhci->lock, flags);138138+ if (uhci->hc_inaccessible) {139139+ status = 0;140140+ goto done;141141+ }142142+143143+ uhci_check_ports(uhci);144144+ status = get_hub_status_data(uhci, buf);145145+146146+ switch (uhci->rh_state) {147147+ case UHCI_RH_SUSPENDING:148148+ case UHCI_RH_SUSPENDED:149149+ /* if port change, ask to be resumed */150150+ if (status)151151+ usb_hcd_resume_root_hub(hcd);152152+ break;153153+154154+ case UHCI_RH_AUTO_STOPPED:155155+ /* if port change, auto start */156156+ if (status)157157+ wakeup_rh(uhci);158158+ break;159159+160160+ case UHCI_RH_RUNNING:161161+ /* are any devices attached? */162162+ if (!any_ports_active(uhci)) {163163+ uhci->rh_state = UHCI_RH_RUNNING_NODEVS;164164+ uhci->auto_stop_time = jiffies + HZ;165165+ }166166+ break;167167+168168+ case UHCI_RH_RUNNING_NODEVS:169169+ /* auto-stop if nothing connected for 1 second */170170+ if (any_ports_active(uhci))171171+ uhci->rh_state = UHCI_RH_RUNNING;172172+ else if (time_after_eq(jiffies, uhci->auto_stop_time))173173+ suspend_rh(uhci, UHCI_RH_AUTO_STOPPED);174174+ break;175175+176176+ default:177177+ break;178178+ }179179+180180+done:181181+ spin_unlock_irqrestore(&uhci->lock, flags);182182+ return status;137183}138184139185/* size of returned buffer is part of USB spec */···205133 unsigned long port_addr = uhci->io_addr + USBPORTSC1 + 2 * port;206134 u16 wPortChange, wPortStatus;207135 unsigned long flags;136136+137137+ if (uhci->hc_inaccessible)138138+ return -ETIMEDOUT;208139209140 spin_lock_irqsave(&uhci->lock, flags);210141 switch (typeReq) {
+36-22
drivers/usb/host/uhci-q.c
···3232 */3333static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci)3434{3535+ if (uhci->is_stopped)3636+ mod_timer(&uhci->stall_timer, jiffies);3537 uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC); 3638}3739···4846 list_move_tail(&urbp->urb_list, &uhci->complete_list);4947}50485151-static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci, struct usb_device *dev)4949+static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci)5250{5351 dma_addr_t dma_handle;5452 struct uhci_td *td;···6361 td->buffer = 0;64626563 td->frame = -1;6666- td->dev = dev;67646865 INIT_LIST_HEAD(&td->list);6966 INIT_LIST_HEAD(&td->remove_list);7067 INIT_LIST_HEAD(&td->fl_list);7171-7272- usb_get_dev(dev);73687469 return td;7570}···167168 if (!list_empty(&td->fl_list))168169 dev_warn(uhci_dev(uhci), "td %p still in fl_list!\n", td);169170170170- if (td->dev)171171- usb_put_dev(td->dev);172172-173171 dma_pool_free(uhci->td_pool, td, td->dma_handle);174172}175173176176-static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, struct usb_device *dev)174174+static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci)177175{178176 dma_addr_t dma_handle;179177 struct uhci_qh *qh;···184188 qh->element = UHCI_PTR_TERM;185189 qh->link = UHCI_PTR_TERM;186190187187- qh->dev = dev;188191 qh->urbp = NULL;189192190193 INIT_LIST_HEAD(&qh->list);191194 INIT_LIST_HEAD(&qh->remove_list);192192-193193- usb_get_dev(dev);194195195196 return qh;196197}···198205 dev_warn(uhci_dev(uhci), "qh %p list not empty!\n", qh);199206 if (!list_empty(&qh->remove_list))200207 dev_warn(uhci_dev(uhci), "qh %p still in remove_list!\n", qh);201201-202202- if (qh->dev)203203- usb_put_dev(qh->dev);204208205209 dma_pool_free(uhci->qh_pool, qh, qh->dma_handle);206210}···587597 /*588598 * Build the TD for the control request setup packet589599 */590590- td = uhci_alloc_td(uhci, urb->dev);600600+ td = uhci_alloc_td(uhci);591601 if (!td)592602 return -ENOMEM;593603···616626 if (pktsze > maxsze)617627 pktsze = maxsze;618628619619- td = uhci_alloc_td(uhci, urb->dev);629629+ td = uhci_alloc_td(uhci);620630 if (!td)621631 return -ENOMEM;622632···634644 /*635645 * Build the final TD for control status 636646 */637637- td = uhci_alloc_td(uhci, urb->dev);647647+ td = uhci_alloc_td(uhci);638648 if (!td)639649 return -ENOMEM;640650···656666 uhci_fill_td(td, status | TD_CTRL_IOC,657667 destination | uhci_explen(UHCI_NULL_DATA_SIZE), 0);658668659659- qh = uhci_alloc_qh(uhci, urb->dev);669669+ qh = uhci_alloc_qh(uhci);660670 if (!qh)661671 return -ENOMEM;662672···855865 status &= ~TD_CTRL_SPD;856866 }857867858858- td = uhci_alloc_td(uhci, urb->dev);868868+ td = uhci_alloc_td(uhci);859869 if (!td)860870 return -ENOMEM;861871···881891 */882892 if (usb_pipeout(urb->pipe) && (urb->transfer_flags & URB_ZERO_PACKET) &&883893 !len && urb->transfer_buffer_length) {884884- td = uhci_alloc_td(uhci, urb->dev);894894+ td = uhci_alloc_td(uhci);885895 if (!td)886896 return -ENOMEM;887897···903913 * flag setting. */904914 td->status |= cpu_to_le32(TD_CTRL_IOC);905915906906- qh = uhci_alloc_qh(uhci, urb->dev);916916+ qh = uhci_alloc_qh(uhci);907917 if (!qh)908918 return -ENOMEM;909919···10861096 if (!urb->iso_frame_desc[i].length)10871097 continue;1088109810891089- td = uhci_alloc_td(uhci, urb->dev);10991099+ td = uhci_alloc_td(uhci);10901100 if (!td)10911101 return -ENOMEM;10921102···14871497 rescan:14881498 uhci->need_rescan = 0;1489149915001500+ uhci_clear_next_interrupt(uhci);14901501 uhci_get_current_frame_number(uhci);1491150214921503 if (uhci->frame_number + uhci->is_stopped != uhci->qh_remove_age)···1527153615281537 /* Wake up anyone waiting for an URB to complete */15291538 wake_up_all(&uhci->waitqh);15391539+}15401540+15411541+static void check_fsbr(struct uhci_hcd *uhci)15421542+{15431543+ struct urb_priv *up;15441544+15451545+ list_for_each_entry(up, &uhci->urb_list, urb_list) {15461546+ struct urb *u = up->urb;15471547+15481548+ spin_lock(&u->lock);15491549+15501550+ /* Check if the FSBR timed out */15511551+ if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies, up->fsbrtime + IDLE_TIMEOUT))15521552+ uhci_fsbr_timeout(uhci, u);15531553+15541554+ spin_unlock(&u->lock);15551555+ }15561556+15571557+ /* Really disable FSBR */15581558+ if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) {15591559+ uhci->fsbrtimeout = 0;15601560+ uhci->skel_term_qh->link = UHCI_PTR_TERM;15611561+ }15301562}
···13751375 (le16_to_cpu(dev->descriptor.idProduct) == USB_PENCAM_PRODUCT_ID)) {13761376 camera_name = "STV0680";13771377 PDEBUG (0, "STV(i): STV0680 camera found.");13781378+ } else if ((le16_to_cpu(dev->descriptor.idVendor) == USB_CREATIVEGOMINI_VENDOR_ID) &&13791379+ (le16_to_cpu(dev->descriptor.idProduct) == USB_CREATIVEGOMINI_PRODUCT_ID)) {13801380+ camera_name = "Creative WebCam Go Mini";13811381+ PDEBUG (0, "STV(i): Creative WebCam Go Mini found.");13781382 } else {13791379- PDEBUG (0, "STV(e): Vendor/Product ID do not match STV0680 values.");13801380- PDEBUG (0, "STV(e): Check that the STV0680 camera is connected to the computer.");13831383+ PDEBUG (0, "STV(e): Vendor/Product ID do not match STV0680 or Creative WebCam Go Mini values.");13841384+ PDEBUG (0, "STV(e): Check that the STV0680 or Creative WebCam Go Mini camera is connected to the computer.");13811385 retval = -ENODEV;13821386 goto error;13831387 }
···11-/* Siemens ID Mouse driver v0.511+/* Siemens ID Mouse driver v0.62233 This program is free software; you can redistribute it and/or44 modify it under the terms of the GNU General Public License as···10101111 Derived from the USB Skeleton driver 1.1,1212 Copyright (C) 2003 Greg Kroah-Hartman (greg@kroah.com)1313+1414+ Additional information provided by Martin Reising1515+ <Martin.Reising@natural-computing.de>13161417*/1518···2825#include <asm/uaccess.h>2926#include <linux/usb.h>30272828+/* image constants */3129#define WIDTH 2253232-#define HEIGHT 2883333-#define HEADER "P5 225 288 255 "3030+#define HEIGHT 2893131+#define HEADER "P5 225 289 255 "3432#define IMGSIZE ((WIDTH * HEIGHT) + sizeof(HEADER)-1)35333636-/* Version Information */3737-#define DRIVER_VERSION "0.5"3434+/* version information */3535+#define DRIVER_VERSION "0.6"3836#define DRIVER_SHORT "idmouse"3937#define DRIVER_AUTHOR "Florian 'Floe' Echtler <echtler@fs.tum.de>"4038#define DRIVER_DESC "Siemens ID Mouse FingerTIP Sensor Driver"41394242-/* Siemens ID Mouse */4343-#define USB_IDMOUSE_VENDOR_ID 0x06814444-#define USB_IDMOUSE_PRODUCT_ID 0x00054545-4646-/* we still need a minor number */4040+/* minor number for misc USB devices */4741#define USB_IDMOUSE_MINOR_BASE 13248424343+/* vendor and device IDs */4444+#define ID_SIEMENS 0x06814545+#define ID_IDMOUSE 0x00054646+#define ID_CHERRY 0x00104747+4848+/* device ID table */4949static struct usb_device_id idmouse_table[] = {5050- {USB_DEVICE(USB_IDMOUSE_VENDOR_ID, USB_IDMOUSE_PRODUCT_ID)},5151- {} /* null entry at the end */5050+ {USB_DEVICE(ID_SIEMENS, ID_IDMOUSE)}, /* Siemens ID Mouse (Professional) */5151+ {USB_DEVICE(ID_SIEMENS, ID_CHERRY )}, /* Cherry FingerTIP ID Board */5252+ {} /* terminating null entry */5253};5454+5555+/* sensor commands */5656+#define FTIP_RESET 0x205757+#define FTIP_ACQUIRE 0x215858+#define FTIP_RELEASE 0x225959+#define FTIP_BLINK 0x23 /* LSB of value = blink pulse width */6060+#define FTIP_SCROLL 0x246161+6262+#define ftip_command(dev, command, value, index) \6363+ usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0), command, \6464+ USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, value, index, NULL, 0, 1000)53655466MODULE_DEVICE_TABLE(usb, idmouse_table);5567···7557 struct usb_interface *interface; /* the interface for this device */76587759 unsigned char *bulk_in_buffer; /* the buffer to receive data */7878- size_t bulk_in_size; /* the size of the receive buffer */6060+ size_t bulk_in_size; /* the maximum bulk packet size */6161+ size_t orig_bi_size; /* same as above, but reported by the device */7962 __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */80638164 int open; /* if the port is open or not */···122103 .id_table = idmouse_table,123104};124105125125-// prevent races between open() and disconnect()106106+/* prevent races between open() and disconnect() */126107static DECLARE_MUTEX(disconnect_sem);127108128109static int idmouse_create_image(struct usb_idmouse *dev)···131112 int bulk_read = 0;132113 int result = 0;133114134134- if (dev->bulk_in_size < sizeof(HEADER))135135- return -ENOMEM;136136-137137- memcpy(dev->bulk_in_buffer,HEADER,sizeof(HEADER)-1);115115+ memcpy(dev->bulk_in_buffer, HEADER, sizeof(HEADER)-1);138116 bytes_read += sizeof(HEADER)-1;139117140140- /* Dump the setup packets. Yes, they are uncommented, simply 141141- because they were sniffed under Windows using SnoopyPro.142142- I _guess_ that 0x22 is a kind of reset command and 0x21 143143- means init..144144- */145145- result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0),146146- 0x21, 0x42, 0x0001, 0x0002, NULL, 0, 1000);118118+ /* reset the device and set a fast blink rate */119119+ result = ftip_command(dev, FTIP_RELEASE, 0, 0);147120 if (result < 0)148148- return result;149149- result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0),150150- 0x20, 0x42, 0x0001, 0x0002, NULL, 0, 1000);121121+ goto reset;122122+ result = ftip_command(dev, FTIP_BLINK, 1, 0);151123 if (result < 0)152152- return result;153153- result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0),154154- 0x22, 0x42, 0x0000, 0x0002, NULL, 0, 1000);155155- if (result < 0)156156- return result;124124+ goto reset;157125158158- result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0),159159- 0x21, 0x42, 0x0001, 0x0002, NULL, 0, 1000);126126+ /* initialize the sensor - sending this command twice */127127+ /* significantly reduces the rate of failed reads */128128+ result = ftip_command(dev, FTIP_ACQUIRE, 0, 0);160129 if (result < 0)161161- return result;162162- result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0),163163- 0x20, 0x42, 0x0001, 0x0002, NULL, 0, 1000);130130+ goto reset;131131+ result = ftip_command(dev, FTIP_ACQUIRE, 0, 0);164132 if (result < 0)165165- return result;166166- result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0),167167- 0x20, 0x42, 0x0000, 0x0002, NULL, 0, 1000);133133+ goto reset;134134+135135+ /* start the readout - sending this command twice */136136+ /* presumably enables the high dynamic range mode */137137+ result = ftip_command(dev, FTIP_RESET, 0, 0);168138 if (result < 0)169169- return result;139139+ goto reset;140140+ result = ftip_command(dev, FTIP_RESET, 0, 0);141141+ if (result < 0)142142+ goto reset;170143171144 /* loop over a blocking bulk read to get data from the device */172145 while (bytes_read < IMGSIZE) {···166155 usb_rcvbulkpipe (dev->udev, dev->bulk_in_endpointAddr),167156 dev->bulk_in_buffer + bytes_read,168157 dev->bulk_in_size, &bulk_read, 5000);169169- if (result < 0)170170- return result;171171- if (signal_pending(current))172172- return -EINTR;158158+ if (result < 0) {159159+ /* Maybe this error was caused by the increased packet size? */160160+ /* Reset to the original value and tell userspace to retry. */161161+ if (dev->bulk_in_size != dev->orig_bi_size) {162162+ dev->bulk_in_size = dev->orig_bi_size;163163+ result = -EAGAIN;164164+ }165165+ break;166166+ }167167+ if (signal_pending(current)) {168168+ result = -EINTR;169169+ break;170170+ }173171 bytes_read += bulk_read;174172 }175173176174 /* reset the device */177177- result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0),178178- 0x22, 0x42, 0x0000, 0x0002, NULL, 0, 1000);179179- if (result < 0)180180- return result;175175+reset:176176+ ftip_command(dev, FTIP_RELEASE, 0, 0);181177182182- /* should be IMGSIZE == 64815 */178178+ /* check for valid image */179179+ /* right border should be black (0x00) */180180+ for (bytes_read = sizeof(HEADER)-1 + WIDTH-1; bytes_read < IMGSIZE; bytes_read += WIDTH)181181+ if (dev->bulk_in_buffer[bytes_read] != 0x00)182182+ return -EAGAIN;183183+184184+ /* lower border should be white (0xFF) */185185+ for (bytes_read = IMGSIZE-WIDTH; bytes_read < IMGSIZE-1; bytes_read++)186186+ if (dev->bulk_in_buffer[bytes_read] != 0xFF)187187+ return -EAGAIN;188188+189189+ /* should be IMGSIZE == 65040 */183190 dbg("read %d bytes fingerprint data", bytes_read);184184- return 0;191191+ return result;185192}186193187194static inline void idmouse_delete(struct usb_idmouse *dev)···311282312283 dev = (struct usb_idmouse *) file->private_data;313284314314- // lock this object285285+ /* lock this object */315286 down (&dev->sem);316287317317- // verify that the device wasn't unplugged288288+ /* verify that the device wasn't unplugged */318289 if (!dev->present) {319290 up (&dev->sem);320291 return -ENODEV;···325296 return 0;326297 }327298328328- if (count > IMGSIZE - *ppos)329329- count = IMGSIZE - *ppos;299299+ count = min ((loff_t)count, IMGSIZE - (*ppos));330300331301 if (copy_to_user (buffer, dev->bulk_in_buffer + *ppos, count)) {332302 result = -EFAULT;···334306 *ppos += count;335307 }336308337337- // unlock the device 309309+ /* unlock the device */338310 up(&dev->sem);339311 return result;340312}···346318 struct usb_idmouse *dev = NULL;347319 struct usb_host_interface *iface_desc;348320 struct usb_endpoint_descriptor *endpoint;349349- size_t buffer_size;350321 int result;351322352323 /* check if we have gotten the data or the hid interface */···371344 USB_ENDPOINT_XFER_BULK)) {372345373346 /* we found a bulk in endpoint */374374- buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);375375- dev->bulk_in_size = buffer_size;347347+ dev->orig_bi_size = le16_to_cpu(endpoint->wMaxPacketSize);348348+ dev->bulk_in_size = 0x200; /* works _much_ faster */376349 dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;377350 dev->bulk_in_buffer =378378- kmalloc(IMGSIZE + buffer_size, GFP_KERNEL);351351+ kmalloc(IMGSIZE + dev->bulk_in_size, GFP_KERNEL);379352380353 if (!dev->bulk_in_buffer) {381354 err("Unable to allocate input buffer.");
+52-8
drivers/usb/misc/usbtest.c
···461461462462static unsigned realworld = 1;463463module_param (realworld, uint, 0);464464-MODULE_PARM_DESC (realworld, "clear to demand stricter ch9 compliance");464464+MODULE_PARM_DESC (realworld, "clear to demand stricter spec compliance");465465466466static int get_altsetting (struct usbtest_dev *dev)467467{···604604 USB_DIR_IN | USB_RECIP_DEVICE,605605 0, 0, dev->buf, 1, USB_CTRL_GET_TIMEOUT);606606 if (retval != 1 || dev->buf [0] != expected) {607607- dev_dbg (&iface->dev,608608- "get config --> %d (%d)\n", retval,609609- expected);607607+ dev_dbg (&iface->dev, "get config --> %d %d (1 %d)\n",608608+ retval, dev->buf[0], expected);610609 return (retval < 0) ? retval : -EDOM;611610 }612611 }···12421243 char *what = "?";12431244 struct usb_device *udev;1244124512451245- if (length > 0xffff || vary >= length)12461246+ if (length < 1 || length > 0xffff || vary >= length)12461247 return -EINVAL;1247124812481249 buf = kmalloc(length, SLAB_KERNEL);···12651266 0, 0, buf, len, USB_CTRL_SET_TIMEOUT);12661267 if (retval != len) {12671268 what = "write";12691269+ if (retval >= 0) {12701270+ INFO(dev, "ctrl_out, wlen %d (expected %d)\n",12711271+ retval, len);12721272+ retval = -EBADMSG;12731273+ }12681274 break;12691275 }12701276···12791275 0, 0, buf, len, USB_CTRL_GET_TIMEOUT);12801276 if (retval != len) {12811277 what = "read";12781278+ if (retval >= 0) {12791279+ INFO(dev, "ctrl_out, rlen %d (expected %d)\n",12801280+ retval, len);12811281+ retval = -EBADMSG;12821282+ }12821283 break;12831284 }12841285···13021293 }1303129413041295 len += vary;12961296+12971297+ /* [real world] the "zero bytes IN" case isn't really used.12981298+ * hardware can easily trip up in this wierd case, since its12991299+ * status stage is IN, not OUT like other ep0in transfers.13001300+ */13051301 if (len > length)13061306- len = 0;13021302+ len = realworld ? 1 : 0;13071303 }1308130413091305 if (retval < 0)···1532151815331519 if (down_interruptible (&dev->sem))15341520 return -ERESTARTSYS;15211521+15221522+ if (intf->dev.power.power_state != PMSG_ON) {15231523+ up (&dev->sem);15241524+ return -EHOSTUNREACH;15251525+ }1535152615361527 /* some devices, like ez-usb default devices, need a non-default15371528 * altsetting to have any active endpoints. some tests change···17811762 case 14:17821763 if (!dev->info->ctrl_out)17831764 break;17841784- dev_dbg (&intf->dev, "TEST 14: %d ep0out, 0..%d vary %d\n",17851785- param->iterations, param->length, param->vary);17651765+ dev_dbg (&intf->dev, "TEST 14: %d ep0out, %d..%d vary %d\n",17661766+ param->iterations,17671767+ realworld ? 1 : 0, param->length,17681768+ param->vary);17861769 retval = ctrl_out (dev, param->iterations, 17871770 param->length, param->vary);17881771 break;···19471926 info->alt >= 0 ? " (+alt)" : "");19481927 return 0;19491928}19291929+19301930+static int usbtest_suspend (struct usb_interface *intf, pm_message_t message)19311931+{19321932+ struct usbtest_dev *dev = usb_get_intfdata (intf);19331933+19341934+ down (&dev->sem);19351935+ intf->dev.power.power_state = PMSG_SUSPEND;19361936+ up (&dev->sem);19371937+ return 0;19381938+}19391939+19401940+static int usbtest_resume (struct usb_interface *intf)19411941+{19421942+ struct usbtest_dev *dev = usb_get_intfdata (intf);19431943+19441944+ down (&dev->sem);19451945+ intf->dev.power.power_state = PMSG_ON;19461946+ up (&dev->sem);19471947+ return 0;19481948+}19491949+1950195019511951static void usbtest_disconnect (struct usb_interface *intf)19521952{···21572115 .probe = usbtest_probe,21582116 .ioctl = usbtest_ioctl,21592117 .disconnect = usbtest_disconnect,21182118+ .suspend = usbtest_suspend,21192119+ .resume = usbtest_resume,21602120};2161212121622122/*-------------------------------------------------------------------------*/
···4646 char essid[IW_ESSID_MAX_SIZE+1];4747 int essidlen;4848 int mac_enabled;4949+ int was_enabled;4950 int monitor;5051 int encode_enabled;5152 int encode_restricted;
+10-9
drivers/usb/serial/cyberjack.c
···213213 return (0);214214 }215215216216- if (port->write_urb->status == -EINPROGRESS) {216216+ spin_lock(&port->lock);217217+ if (port->write_urb_busy) {218218+ spin_unlock(&port->lock);217219 dbg("%s - already writing", __FUNCTION__);218218- return (0);220220+ return 0;219221 }222222+ port->write_urb_busy = 1;223223+ spin_unlock(&port->lock);220224221225 spin_lock_irqsave(&priv->lock, flags);222226···228224 /* To much data for buffer. Reset buffer. */229225 priv->wrfilled=0;230226 spin_unlock_irqrestore(&priv->lock, flags);227227+ port->write_urb_busy = 0;231228 return (0);232229 }233230···273268 priv->wrfilled=0;274269 priv->wrsent=0;275270 spin_unlock_irqrestore(&priv->lock, flags);271271+ port->write_urb_busy = 0;276272 return 0;277273 }278274···418412 struct cyberjack_private *priv = usb_get_serial_port_data(port);419413420414 dbg("%s - port %d", __FUNCTION__, port->number);421421-415415+416416+ port->write_urb_busy = 0;422417 if (urb->status) {423418 dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);424419 return;···430423 /* only do something if we have more data to send */431424 if( priv->wrfilled ) {432425 int length, blksize, result;433433-434434- if (port->write_urb->status == -EINPROGRESS) {435435- dbg("%s - already writing", __FUNCTION__);436436- spin_unlock(&priv->lock);437437- return;438438- }439426440427 dbg("%s - transmitting data (frame n)", __FUNCTION__);441428
+16-8
drivers/usb/serial/generic.c
···174174175175 /* only do something if we have a bulk out endpoint */176176 if (serial->num_bulk_out) {177177- if (port->write_urb->status == -EINPROGRESS) {177177+ spin_lock(&port->lock);178178+ if (port->write_urb_busy) {179179+ spin_unlock(&port->lock);178180 dbg("%s - already writing", __FUNCTION__);179179- return (0);181181+ return 0;180182 }183183+ port->write_urb_busy = 1;184184+ spin_unlock(&port->lock);181185182186 count = (count > port->bulk_out_size) ? port->bulk_out_size : count;183187···199195 usb_serial_generic_write_bulk_callback), port);200196201197 /* send the data out the bulk port */198198+ port->write_urb_busy = 1;202199 result = usb_submit_urb(port->write_urb, GFP_ATOMIC);203203- if (result)200200+ if (result) {204201 dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);205205- else202202+ /* don't have to grab the lock here, as we will retry if != 0 */203203+ port->write_urb_busy = 0;204204+ } else206205 result = count;207206208207 return result;209208 }210209211210 /* no bulk out, so return 0 bytes written */212212- return (0);211211+ return 0;213212}214213215214int usb_serial_generic_write_room (struct usb_serial_port *port)···221214 int room = 0;222215223216 dbg("%s - port %d", __FUNCTION__, port->number);224224-217217+225218 if (serial->num_bulk_out) {226226- if (port->write_urb->status != -EINPROGRESS)219219+ if (port->write_urb_busy)227220 room = port->bulk_out_size;228221 }229222···239232 dbg("%s - port %d", __FUNCTION__, port->number);240233241234 if (serial->num_bulk_out) {242242- if (port->write_urb->status == -EINPROGRESS)235235+ if (port->write_urb_busy)243236 chars = port->write_urb->transfer_buffer_length;244237 }245238···298291299292 dbg("%s - port %d", __FUNCTION__, port->number);300293294294+ port->write_urb_busy = 0;301295 if (urb->status) {302296 dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);303297 return;
-5
drivers/usb/serial/ipaq.c
···818818 struct ipaq_packet *pkt, *tmp;819819 struct urb *urb = port->write_urb;820820821821- if (urb->status == -EINPROGRESS) {822822- /* Should never happen */823823- err("%s - flushing while urb is active !", __FUNCTION__);824824- return;825825- }826821 room = URBDATA_SIZE;827822 list_for_each_entry_safe(pkt, tmp, &priv->queue, list) {828823 count = min(room, (int)(pkt->len - pkt->written));
···520520 the TX urb is in-flight (wait until it completes)521521 the device is full (wait until it says there is room)522522 */523523- if (port->write_urb->status == -EINPROGRESS || priv->tx_throttled ) {524524- return( 0 );523523+ spin_lock(&port->lock);524524+ if (port->write_urb_busy || priv->tx_throttled) {525525+ spin_unlock(&port->lock);526526+ return 0;525527 }528528+ port->write_urb_busy = 1;529529+ spin_unlock(&port->lock);526530527531 /* At this point the URB is in our control, nobody else can submit it528532 again (the only sudden transition was the one from EINPROGRESS to···574570 memcpy (port->write_urb->transfer_buffer, buf, count);575571 /* send the data out the bulk port */576572 port->write_urb->transfer_buffer_length = count;577577-573573+578574 priv->tx_room -= count;579575580576 port->write_urb->dev = port->serial->dev;···597593598594 rc = count;599595exit:596596+ if (rc < 0)597597+ port->write_urb_busy = 0;600598 return rc;601599}602600···608602 struct usb_serial_port *port = (struct usb_serial_port *)urb->context;609603 struct keyspan_pda_private *priv;610604605605+ port->write_urb_busy = 0;611606 priv = usb_get_serial_port_data(port);612607613608 /* queue up a wakeup at scheduler time */···633626static int keyspan_pda_chars_in_buffer (struct usb_serial_port *port)634627{635628 struct keyspan_pda_private *priv;636636-629629+637630 priv = usb_get_serial_port_data(port);638638-631631+639632 /* when throttled, return at least WAKEUP_CHARS to tell select() (via640633 n_tty.c:normal_poll() ) that we're not writeable. */641641- if( port->write_urb->status == -EINPROGRESS || priv->tx_throttled )634634+ if (port->write_urb_busy || priv->tx_throttled)642635 return 256;643636 return 0;644637}
+12-5
drivers/usb/serial/omninet.c
···254254 dbg("%s - write request of 0 bytes", __FUNCTION__);255255 return (0);256256 }257257- if (wport->write_urb->status == -EINPROGRESS) {257257+258258+ spin_lock(&port->lock);259259+ if (port->write_urb_busy) {260260+ spin_unlock(&port->lock);258261 dbg("%s - already writing", __FUNCTION__);259259- return (0);262262+ return 0;260263 }264264+ port->write_urb_busy = 1;265265+ spin_unlock(&port->lock);261266262267 count = (count > OMNINET_BULKOUTSIZE) ? OMNINET_BULKOUTSIZE : count;263268···280275281276 wport->write_urb->dev = serial->dev;282277 result = usb_submit_urb(wport->write_urb, GFP_ATOMIC);283283- if (result)278278+ if (result) {279279+ port->write_urb_busy = 0;284280 err("%s - failed submitting write urb, error %d", __FUNCTION__, result);285285- else281281+ } else286282 result = count;287283288284 return result;···297291298292 int room = 0; // Default: no room299293300300- if (wport->write_urb->status != -EINPROGRESS)294294+ if (wport->write_urb_busy)301295 room = wport->bulk_out_size - OMNINET_HEADERLEN;302296303297// dbg("omninet_write_room returns %d", room);···312306313307// dbg("omninet_write_bulk_callback, port %0x\n", port);314308309309+ port->write_urb_busy = 0;315310 if (urb->status) {316311 dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);317312 return;
···6969 * usb_serial_port: structure for the specific ports of a device.7070 * @serial: pointer back to the struct usb_serial owner of this port.7171 * @tty: pointer to the corresponding tty for this port.7272+ * @lock: spinlock to grab when updating portions of this structure.7273 * @number: the number of the port (the minor number).7374 * @interrupt_in_buffer: pointer to the interrupt in buffer for this port.7475 * @interrupt_in_urb: pointer to the interrupt in struct urb for this port.···9998struct usb_serial_port {10099 struct usb_serial * serial;101100 struct tty_struct * tty;101101+ spinlock_t lock;102102 unsigned char number;103103104104 unsigned char * interrupt_in_buffer;···119117 unsigned char * bulk_out_buffer;120118 int bulk_out_size;121119 struct urb * write_urb;120120+ int write_urb_busy;122121 __u8 bulk_out_endpointAddress;123122124123 wait_queue_head_t write_wait;
+22-32
drivers/usb/storage/scsiglue.c
···155155 * If this device makes that mistake, tell the sd driver. */156156 if (us->flags & US_FL_FIX_CAPACITY)157157 sdev->fix_capacity = 1;158158+159159+ /* USB-IDE bridges tend to report SK = 0x04 (Non-recoverable160160+ * Hardware Error) when any low-level error occurs,161161+ * recoverable or not. Setting this flag tells the SCSI162162+ * midlayer to retry such commands, which frequently will163163+ * succeed and fix the error. The worst this can lead to164164+ * is an occasional series of retries that will all fail. */165165+ sdev->retry_hwerror = 1;166166+158167 } else {159168160169 /* Non-disk-type devices don't need to blacklist any pages···264255265256 /* lock the device pointers and do the reset */266257 down(&(us->dev_semaphore));267267- if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {268268- result = FAILED;269269- US_DEBUGP("No reset during disconnect\n");270270- } else271271- result = us->transport_reset(us);258258+ result = us->transport_reset(us);272259 up(&(us->dev_semaphore));273260274274- return result;261261+ return result < 0 ? FAILED : SUCCESS;275262}276263277277-/* This resets the device's USB port. */278278-/* It refuses to work if there's more than one interface in279279- * the device, so that other users are not affected. */264264+/* Simulate a SCSI bus reset by resetting the device's USB port. */280265/* This is always called with scsi_lock(host) held */281266static int bus_reset(struct scsi_cmnd *srb)282267{283268 struct us_data *us = host_to_us(srb->device->host);284284- int result, rc;269269+ int result;285270286271 US_DEBUGP("%s called\n", __FUNCTION__);287272288288- /* The USB subsystem doesn't handle synchronisation between289289- * a device's several drivers. Therefore we reset only devices290290- * with just one interface, which we of course own. */291291-292273 down(&(us->dev_semaphore));293293- if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {294294- result = -EIO;295295- US_DEBUGP("No reset during disconnect\n");296296- } else if (us->pusb_dev->actconfig->desc.bNumInterfaces != 1) {297297- result = -EBUSY;298298- US_DEBUGP("Refusing to reset a multi-interface device\n");299299- } else {300300- rc = usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf);301301- if (rc < 0) {302302- US_DEBUGP("unable to lock device for reset: %d\n", rc);303303- result = rc;304304- } else {305305- result = usb_reset_device(us->pusb_dev);306306- if (rc)307307- usb_unlock_device(us->pusb_dev);308308- US_DEBUGP("usb_reset_device returns %d\n", result);309309- }310310- }274274+ result = usb_stor_port_reset(us);311275 up(&(us->dev_semaphore));312276313277 /* lock the host for the return */···300318 for (i = 1; i < host->max_id; ++i)301319 scsi_report_device_reset(host, 0, i);302320 }321321+}322322+323323+/* Report a driver-initiated bus reset to the SCSI layer.324324+ * Calling this for a SCSI-initiated reset is unnecessary but harmless.325325+ * The caller must own the SCSI host lock. */326326+void usb_stor_report_bus_reset(struct us_data *us)327327+{328328+ scsi_report_bus_reset(us_to_host(us), 0);303329}304330305331/***********************************************************************
···266266 NULL, 0, 3*HZ);267267268268 /* reset the endpoint toggle */269269- usb_settoggle(us->pusb_dev, usb_pipeendpoint(pipe),270270- usb_pipeout(pipe), 0);269269+ if (result >= 0)270270+ usb_settoggle(us->pusb_dev, usb_pipeendpoint(pipe),271271+ usb_pipeout(pipe), 0);271272272273 US_DEBUGP("%s: result = %d\n", __FUNCTION__, result);273274 return result;···541540 */542541 if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {543542 US_DEBUGP("-- command was aborted\n");544544- goto Handle_Abort;543543+ srb->result = DID_ABORT << 16;544544+ goto Handle_Errors;545545 }546546547547 /* if there is a transport error, reset and don't auto-sense */548548 if (result == USB_STOR_TRANSPORT_ERROR) {549549 US_DEBUGP("-- transport indicates error, resetting\n");550550- us->transport_reset(us);551550 srb->result = DID_ERROR << 16;552552- return;551551+ goto Handle_Errors;553552 }554553555554 /* if the transport provided its own sense data, don't auto-sense */···669668670669 if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {671670 US_DEBUGP("-- auto-sense aborted\n");672672- goto Handle_Abort;671671+ srb->result = DID_ABORT << 16;672672+ goto Handle_Errors;673673 }674674 if (temp_result != USB_STOR_TRANSPORT_GOOD) {675675 US_DEBUGP("-- auto-sense failure\n");···679677 * multi-target device, since failure of an680678 * auto-sense is perfectly valid681679 */682682- if (!(us->flags & US_FL_SCM_MULT_TARG))683683- us->transport_reset(us);684680 srb->result = DID_ERROR << 16;681681+ if (!(us->flags & US_FL_SCM_MULT_TARG))682682+ goto Handle_Errors;685683 return;686684 }687685···722720723721 return;724722725725- /* abort processing: the bulk-only transport requires a reset726726- * following an abort */727727- Handle_Abort:728728- srb->result = DID_ABORT << 16;729729- if (us->protocol == US_PR_BULK)723723+ /* Error and abort processing: try to resynchronize with the device724724+ * by issuing a port reset. If that fails, try a class-specific725725+ * device reset. */726726+ Handle_Errors:727727+728728+ /* Let the SCSI layer know we are doing a reset, set the729729+ * RESETTING bit, and clear the ABORTING bit so that the reset730730+ * may proceed. */731731+ scsi_lock(us_to_host(us));732732+ usb_stor_report_bus_reset(us);733733+ set_bit(US_FLIDX_RESETTING, &us->flags);734734+ clear_bit(US_FLIDX_ABORTING, &us->flags);735735+ scsi_unlock(us_to_host(us));736736+737737+ result = usb_stor_port_reset(us);738738+ if (result < 0) {739739+ scsi_lock(us_to_host(us));740740+ usb_stor_report_device_reset(us);741741+ scsi_unlock(us_to_host(us));730742 us->transport_reset(us);743743+ }744744+ clear_bit(US_FLIDX_RESETTING, &us->flags);731745}732746733747/* Stop the current URB transfer */···11421124 * It's handy that every transport mechanism uses the control endpoint for11431125 * resets.11441126 *11451145- * Basically, we send a reset with a 20-second timeout, so we don't get11271127+ * Basically, we send a reset with a 5-second timeout, so we don't get11461128 * jammed attempting to do the reset.11471129 */11481130static int usb_stor_reset_common(struct us_data *us,···11511133{11521134 int result;11531135 int result2;11541154- int rc = FAILED;1155113611561156- /* Let the SCSI layer know we are doing a reset, set the11571157- * RESETTING bit, and clear the ABORTING bit so that the reset11581158- * may proceed.11591159- */11601160- scsi_lock(us_to_host(us));11611161- usb_stor_report_device_reset(us);11621162- set_bit(US_FLIDX_RESETTING, &us->flags);11631163- clear_bit(US_FLIDX_ABORTING, &us->flags);11641164- scsi_unlock(us_to_host(us));11371137+ if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {11381138+ US_DEBUGP("No reset during disconnect\n");11391139+ return -EIO;11401140+ }1165114111661166- /* A 20-second timeout may seem rather long, but a LaCie11671167- * StudioDrive USB2 device takes 16+ seconds to get going11681168- * following a powerup or USB attach event.11691169- */11701142 result = usb_stor_control_msg(us, us->send_ctrl_pipe,11711143 request, requesttype, value, index, data, size,11721172- 20*HZ);11441144+ 5*HZ);11731145 if (result < 0) {11741146 US_DEBUGP("Soft reset failed: %d\n", result);11751175- goto Done;11471147+ return result;11761148 }1177114911781150 /* Give the device some time to recover from the reset,···11721164 HZ*6);11731165 if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {11741166 US_DEBUGP("Reset interrupted by disconnect\n");11751175- goto Done;11671167+ return -EIO;11761168 }1177116911781170 US_DEBUGP("Soft reset: clearing bulk-in endpoint halt\n");···11811173 US_DEBUGP("Soft reset: clearing bulk-out endpoint halt\n");11821174 result2 = usb_stor_clear_halt(us, us->send_bulk_pipe);1183117511841184- /* return a result code based on the result of the control message */11851185- if (result < 0 || result2 < 0) {11761176+ /* return a result code based on the result of the clear-halts */11771177+ if (result >= 0)11781178+ result = result2;11791179+ if (result < 0)11861180 US_DEBUGP("Soft reset failed\n");11871187- goto Done;11881188- }11891189- US_DEBUGP("Soft reset done\n");11901190- rc = SUCCESS;11911191-11921192- Done:11931193- clear_bit(US_FLIDX_RESETTING, &us->flags);11941194- return rc;11811181+ else11821182+ US_DEBUGP("Soft reset done\n");11831183+ return result;11951184}1196118511971186/* This issues a CB[I] Reset to the device in question···12171212 return usb_stor_reset_common(us, US_BULK_RESET_REQUEST, 12181213 USB_TYPE_CLASS | USB_RECIP_INTERFACE,12191214 0, us->ifnum, NULL, 0);12151215+}12161216+12171217+/* Issue a USB port reset to the device. But don't do anything if12181218+ * there's more than one interface in the device, so that other users12191219+ * are not affected. */12201220+int usb_stor_port_reset(struct us_data *us)12211221+{12221222+ int result, rc;12231223+12241224+ if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {12251225+ result = -EIO;12261226+ US_DEBUGP("No reset during disconnect\n");12271227+ } else if (us->pusb_dev->actconfig->desc.bNumInterfaces != 1) {12281228+ result = -EBUSY;12291229+ US_DEBUGP("Refusing to reset a multi-interface device\n");12301230+ } else {12311231+ result = rc =12321232+ usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf);12331233+ if (result < 0) {12341234+ US_DEBUGP("unable to lock device for reset: %d\n",12351235+ result);12361236+ } else {12371237+ result = usb_reset_device(us->pusb_dev);12381238+ if (rc)12391239+ usb_unlock_device(us->pusb_dev);12401240+ US_DEBUGP("usb_reset_device returns %d\n", result);12411241+ }12421242+ }12431243+ return result;12201244}
+1
drivers/usb/storage/transport.h
···171171extern int usb_stor_bulk_transfer_sg(struct us_data *us, unsigned int pipe,172172 void *buf, unsigned int length, int use_sg, int *residual);173173174174+extern int usb_stor_port_reset(struct us_data *us);174175#endif
···66 *77 * - the master/host side Linux-USB kernel driver API;88 * - the "usbfs" user space API; and99- * - (eventually) a Linux "gadget" slave/device side driver API.99+ * - the Linux "gadget" slave/device/peripheral side driver API.1010 *1111 * USB 2.0 adds an additional "On The Go" (OTG) mode, which lets systems1212 * act either as a USB master/host or as a USB slave/device. That means1313- * the master and slave side APIs will benefit from working well together.1313+ * the master and slave side APIs benefit from working well together.1414+ *1515+ * There's also "Wireless USB", using low power short range radios for1616+ * peripheral interconnection but otherwise building on the USB framework.1417 */15181619#ifndef __LINUX_USB_CH9_H···7168#define USB_REQ_SET_INTERFACE 0x0B7269#define USB_REQ_SYNCH_FRAME 0x0C73707171+#define USB_REQ_SET_ENCRYPTION 0x0D /* Wireless USB */7272+#define USB_REQ_GET_ENCRYPTION 0x0E7373+#define USB_REQ_SET_HANDSHAKE 0x0F7474+#define USB_REQ_GET_HANDSHAKE 0x107575+#define USB_REQ_SET_CONNECTION 0x117676+#define USB_REQ_SET_SECURITY_DATA 0x127777+#define USB_REQ_GET_SECURITY_DATA 0x137878+#define USB_REQ_SET_WUSB_DATA 0x147979+#define USB_REQ_LOOPBACK_DATA_WRITE 0x158080+#define USB_REQ_LOOPBACK_DATA_READ 0x168181+#define USB_REQ_SET_INTERFACE_DS 0x178282+7483/*7584 * USB feature flags are written using USB_REQ_{CLEAR,SET}_FEATURE, and7685 * are read as a bit array returned by USB_REQ_GET_STATUS. (So there···9075 */9176#define USB_DEVICE_SELF_POWERED 0 /* (read only) */9277#define USB_DEVICE_REMOTE_WAKEUP 1 /* dev may initiate wakeup */9393-#define USB_DEVICE_TEST_MODE 2 /* (high speed only) */9494-#define USB_DEVICE_B_HNP_ENABLE 3 /* dev may initiate HNP */9595-#define USB_DEVICE_A_HNP_SUPPORT 4 /* RH port supports HNP */9696-#define USB_DEVICE_A_ALT_HNP_SUPPORT 5 /* other RH port does */7878+#define USB_DEVICE_TEST_MODE 2 /* (wired high speed only) */7979+#define USB_DEVICE_BATTERY 2 /* (wireless) */8080+#define USB_DEVICE_B_HNP_ENABLE 3 /* (otg) dev may initiate HNP */8181+#define USB_DEVICE_WUSB_DEVICE 3 /* (wireless)*/8282+#define USB_DEVICE_A_HNP_SUPPORT 4 /* (otg) RH port supports HNP */8383+#define USB_DEVICE_A_ALT_HNP_SUPPORT 5 /* (otg) other RH port does */9784#define USB_DEVICE_DEBUG_MODE 6 /* (special devices only) */98859986#define USB_ENDPOINT_HALT 0 /* IN/OUT will STALL */···152135#define USB_DT_OTG 0x09153136#define USB_DT_DEBUG 0x0a154137#define USB_DT_INTERFACE_ASSOCIATION 0x0b138138+/* these are from the Wireless USB spec */139139+#define USB_DT_SECURITY 0x0c140140+#define USB_DT_KEY 0x0d141141+#define USB_DT_ENCRYPTION_TYPE 0x0e142142+#define USB_DT_BOS 0x0f143143+#define USB_DT_DEVICE_CAPABILITY 0x10144144+#define USB_DT_WIRELESS_ENDPOINT_COMP 0x11155145156146/* conventional codes for class-specific descriptors */157147#define USB_DT_CS_DEVICE 0x21···216192#define USB_CLASS_CSCID 0x0b /* chip+ smart card */217193#define USB_CLASS_CONTENT_SEC 0x0d /* content security */218194#define USB_CLASS_VIDEO 0x0e195195+#define USB_CLASS_WIRELESS_CONTROLLER 0xe0219196#define USB_CLASS_APP_SPEC 0xfe220197#define USB_CLASS_VENDOR_SPEC 0xff221198···248223#define USB_CONFIG_ATT_ONE (1 << 7) /* must be set */249224#define USB_CONFIG_ATT_SELFPOWER (1 << 6) /* self powered */250225#define USB_CONFIG_ATT_WAKEUP (1 << 5) /* can wakeup */226226+#define USB_CONFIG_ATT_BATTERY (1 << 4) /* battery powered */251227252228/*-------------------------------------------------------------------------*/253229···315289#define USB_ENDPOINT_XFER_ISOC 1316290#define USB_ENDPOINT_XFER_BULK 2317291#define USB_ENDPOINT_XFER_INT 3292292+#define USB_ENDPOINT_MAX_ADJUSTABLE 0x80318293319294320295/*-------------------------------------------------------------------------*/···379352380353/*-------------------------------------------------------------------------*/381354355355+/* USB_DT_SECURITY: group of wireless security descriptors, including356356+ * encryption types available for setting up a CC/association.357357+ */358358+struct usb_security_descriptor {359359+ __u8 bLength;360360+ __u8 bDescriptorType;361361+362362+ __le16 wTotalLength;363363+ __u8 bNumEncryptionTypes;364364+};365365+366366+/*-------------------------------------------------------------------------*/367367+368368+/* USB_DT_KEY: used with {GET,SET}_SECURITY_DATA; only public keys369369+ * may be retrieved.370370+ */371371+struct usb_key_descriptor {372372+ __u8 bLength;373373+ __u8 bDescriptorType;374374+375375+ __u8 tTKID[3];376376+ __u8 bReserved;377377+ __u8 bKeyData[0];378378+};379379+380380+/*-------------------------------------------------------------------------*/381381+382382+/* USB_DT_ENCRYPTION_TYPE: bundled in DT_SECURITY groups */383383+struct usb_encryption_descriptor {384384+ __u8 bLength;385385+ __u8 bDescriptorType;386386+387387+ __u8 bEncryptionType;388388+#define USB_ENC_TYPE_UNSECURE 0389389+#define USB_ENC_TYPE_WIRED 1 /* non-wireless mode */390390+#define USB_ENC_TYPE_CCM_1 2 /* aes128/cbc session */391391+#define USB_ENC_TYPE_RSA_1 3 /* rsa3072/sha1 auth */392392+ __u8 bEncryptionValue; /* use in SET_ENCRYPTION */393393+ __u8 bAuthKeyIndex;394394+};395395+396396+397397+/*-------------------------------------------------------------------------*/398398+399399+/* USB_DT_BOS: group of wireless capabilities */400400+struct usb_bos_descriptor {401401+ __u8 bLength;402402+ __u8 bDescriptorType;403403+404404+ __le16 wTotalLength;405405+ __u8 bNumDeviceCaps;406406+};407407+408408+/*-------------------------------------------------------------------------*/409409+410410+/* USB_DT_DEVICE_CAPABILITY: grouped with BOS */411411+struct usb_dev_cap_header {412412+ __u8 bLength;413413+ __u8 bDescriptorType;414414+ __u8 bDevCapabilityType;415415+};416416+417417+#define USB_CAP_TYPE_WIRELESS_USB 1418418+419419+struct usb_wireless_cap_descriptor { /* Ultra Wide Band */420420+ __u8 bLength;421421+ __u8 bDescriptorType;422422+ __u8 bDevCapabilityType;423423+424424+ __u8 bmAttributes;425425+#define USB_WIRELESS_P2P_DRD (1 << 1)426426+#define USB_WIRELESS_BEACON_MASK (3 << 2)427427+#define USB_WIRELESS_BEACON_SELF (1 << 2)428428+#define USB_WIRELESS_BEACON_DIRECTED (2 << 2)429429+#define USB_WIRELESS_BEACON_NONE (3 << 2)430430+ __le16 wPHYRates; /* bit rates, Mbps */431431+#define USB_WIRELESS_PHY_53 (1 << 0) /* always set */432432+#define USB_WIRELESS_PHY_80 (1 << 1)433433+#define USB_WIRELESS_PHY_107 (1 << 2) /* always set */434434+#define USB_WIRELESS_PHY_160 (1 << 3)435435+#define USB_WIRELESS_PHY_200 (1 << 4) /* always set */436436+#define USB_WIRELESS_PHY_320 (1 << 5)437437+#define USB_WIRELESS_PHY_400 (1 << 6)438438+#define USB_WIRELESS_PHY_480 (1 << 7)439439+ __u8 bmTFITXPowerInfo; /* TFI power levels */440440+ __u8 bmFFITXPowerInfo; /* FFI power levels */441441+ __le16 bmBandGroup;442442+ __u8 bReserved;443443+};444444+445445+/*-------------------------------------------------------------------------*/446446+447447+/* USB_DT_WIRELESS_ENDPOINT_COMP: companion descriptor associated with448448+ * each endpoint descriptor for a wireless device449449+ */450450+struct usb_wireless_ep_comp_descriptor {451451+ __u8 bLength;452452+ __u8 bDescriptorType;453453+454454+ __u8 bMaxBurst;455455+ __u8 bMaxSequence;456456+ __le16 wMaxStreamDelay;457457+ __le16 wOverTheAirPacketSize;458458+ __u8 bOverTheAirInterval;459459+ __u8 bmCompAttributes;460460+#define USB_ENDPOINT_SWITCH_MASK 0x03 /* in bmCompAttributes */461461+#define USB_ENDPOINT_SWITCH_NO 0462462+#define USB_ENDPOINT_SWITCH_SWITCH 1463463+#define USB_ENDPOINT_SWITCH_SCALE 2464464+};465465+466466+/*-------------------------------------------------------------------------*/467467+468468+/* USB_REQ_SET_HANDSHAKE is a four-way handshake used between a wireless469469+ * host and a device for connection set up, mutual authentication, and470470+ * exchanging short lived session keys. The handshake depends on a CC.471471+ */472472+struct usb_handshake {473473+ __u8 bMessageNumber;474474+ __u8 bStatus;475475+ __u8 tTKID[3];476476+ __u8 bReserved;477477+ __u8 CDID[16];478478+ __u8 nonce[16];479479+ __u8 MIC[8];480480+};481481+482482+/*-------------------------------------------------------------------------*/483483+484484+/* USB_REQ_SET_CONNECTION modifies or revokes a connection context (CC).485485+ * A CC may also be set up using non-wireless secure channels (including486486+ * wired USB!), and some devices may support CCs with multiple hosts.487487+ */488488+struct usb_connection_context {489489+ __u8 CHID[16]; /* persistent host id */490490+ __u8 CDID[16]; /* device id (unique w/in host context) */491491+ __u8 CK[16]; /* connection key */492492+};493493+494494+/*-------------------------------------------------------------------------*/495495+382496/* USB 2.0 defines three speeds, here's how Linux identifies them */383497384498enum usb_device_speed {385499 USB_SPEED_UNKNOWN = 0, /* enumerating */386500 USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */387387- USB_SPEED_HIGH /* usb 2.0 */501501+ USB_SPEED_HIGH, /* usb 2.0 */502502+ USB_SPEED_VARIABLE, /* wireless (usb 2.5) */388503};389504390505enum usb_device_state {
+1-1
include/linux/usb_gadget.h
···711711 * the hardware level driver. Most calls must be handled by712712 * the gadget driver, including descriptor and configuration713713 * management. The 16 bit members of the setup data are in714714- * cpu order. Called in_interrupt; this may not sleep. Driver714714+ * USB byte order. Called in_interrupt; this may not sleep. Driver715715 * queues a response to ep0, or returns negative to stall.716716 * @disconnect: Invoked after all transfers have been stopped,717717 * when the host is disconnected. May be called in_interrupt; this
+47
include/linux/usb_isp116x.h
···11+22+/*33+ * Board initialization code should put one of these into dev->platform_data44+ * and place the isp116x onto platform_bus.55+ */66+77+struct isp116x_platform_data {88+ /* Enable internal resistors on downstream ports */99+ unsigned sel15Kres:1;1010+ /* Chip's internal clock won't be stopped in suspended state.1111+ Setting/unsetting this bit takes effect only if1212+ 'remote_wakeup_enable' below is not set. */1313+ unsigned clknotstop:1;1414+ /* On-chip overcurrent protection */1515+ unsigned oc_enable:1;1616+ /* INT output polarity */1717+ unsigned int_act_high:1;1818+ /* INT edge or level triggered */1919+ unsigned int_edge_triggered:1;2020+ /* WAKEUP pin connected - NOT SUPPORTED */2121+ /* unsigned remote_wakeup_connected:1; */2222+ /* Wakeup by devices on usb bus enabled */2323+ unsigned remote_wakeup_enable:1;2424+ /* Switch or not to switch (keep always powered) */2525+ unsigned no_power_switching:1;2626+ /* Ganged port power switching (0) or individual port2727+ power switching (1) */2828+ unsigned power_switching_mode:1;2929+ /* Given port_power, msec/2 after power on till power good */3030+ u8 potpg;3131+ /* Hardware reset set/clear. If implemented, this function must:3232+ if set == 0, deassert chip's HW reset pin3333+ otherwise, assert chip's HW reset pin */3434+ void (*reset) (struct device * dev, int set);3535+ /* Hardware clock start/stop. If implemented, this function must:3636+ if start == 0, stop the external clock3737+ otherwise, start the external clock3838+ */3939+ void (*clock) (struct device * dev, int start);4040+ /* Inter-io delay (ns). The chip is picky about access timings; it4141+ expects at least:4242+ 150ns delay between consecutive accesses to DATA_REG,4343+ 300ns delay between access to ADDR_REG and DATA_REG4444+ OE, WE MUST NOT be changed during these intervals4545+ */4646+ void (*delay) (struct device * dev, int delay);4747+};