Commit dd26bf6d authored by Linus Torvalds's avatar Linus Torvalds

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

* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (22 commits)
  WUSB: correct format of wusb_chid sysfs file
  WUSB: fix oops when completing URBs for disconnected devices
  WUSB: disconnect all devices when stopping a WUSB HCD
  USB: whci-hcd: check return value of usb_hcd_link_urb_to_ep()
  USB: whci-hcd: provide a endpoint_reset method
  USB: add reset endpoint operations
  USB device codes for Motorola phone.
  usb-storage: fix mistake in Makefile
  USB: usb-serial ch341: support for DTR/RTS/CTS
  Revert USB: usb-serial ch341: support for DTR/RTS/CTS
  USB: musb: fix possible panic while resuming
  USB: musb: fix isochronous TXDMA (take 2)
  USB: musb: sanitize clearing TXCSR DMA bits (take 2)
  USB: musb: bugfixes for multi-packet TXDMA support
  USB: musb_host, fix ep0 fifo flushing
  USB: usb-storage: augment unusual_devs entry for Simple Tech/Datafab
  USB: musb_host, minor enqueue locking fix (v2)
  USB: fix oops in cdc-wdm in case of malformed descriptors
  USB: qcserial: Add extra device IDs
  USB: option: Add ids for D-Link DWM-652 3.5G modem
  ...
parents 7217fa98 fca10c81
...@@ -1025,6 +1025,7 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) ...@@ -1025,6 +1025,7 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
{ {
struct urb *urb = &sc->work_urb; struct urb *urb = &sc->work_urb;
struct bulk_cs_wrap *bcs; struct bulk_cs_wrap *bcs;
int endp;
int len; int len;
int rc; int rc;
...@@ -1033,6 +1034,10 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) ...@@ -1033,6 +1034,10 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
return; return;
} }
endp = usb_pipeendpoint(sc->last_pipe);
if (usb_pipein(sc->last_pipe))
endp |= USB_DIR_IN;
if (cmd->state == UB_CMDST_CLEAR) { if (cmd->state == UB_CMDST_CLEAR) {
if (urb->status == -EPIPE) { if (urb->status == -EPIPE) {
/* /*
...@@ -1048,9 +1053,7 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) ...@@ -1048,9 +1053,7 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
* We ignore the result for the halt clear. * We ignore the result for the halt clear.
*/ */
/* reset the endpoint toggle */ usb_reset_endpoint(sc->dev, endp);
usb_settoggle(sc->dev, usb_pipeendpoint(sc->last_pipe),
usb_pipeout(sc->last_pipe), 0);
ub_state_sense(sc, cmd); ub_state_sense(sc, cmd);
...@@ -1065,9 +1068,7 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) ...@@ -1065,9 +1068,7 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
* We ignore the result for the halt clear. * We ignore the result for the halt clear.
*/ */
/* reset the endpoint toggle */ usb_reset_endpoint(sc->dev, endp);
usb_settoggle(sc->dev, usb_pipeendpoint(sc->last_pipe),
usb_pipeout(sc->last_pipe), 0);
ub_state_stat(sc, cmd); ub_state_stat(sc, cmd);
...@@ -1082,9 +1083,7 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) ...@@ -1082,9 +1083,7 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
* We ignore the result for the halt clear. * We ignore the result for the halt clear.
*/ */
/* reset the endpoint toggle */ usb_reset_endpoint(sc->dev, endp);
usb_settoggle(sc->dev, usb_pipeendpoint(sc->last_pipe),
usb_pipeout(sc->last_pipe), 0);
ub_state_stat_counted(sc, cmd); ub_state_stat_counted(sc, cmd);
...@@ -2119,8 +2118,7 @@ static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe) ...@@ -2119,8 +2118,7 @@ static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe)
del_timer_sync(&timer); del_timer_sync(&timer);
usb_kill_urb(&sc->work_urb); usb_kill_urb(&sc->work_urb);
/* reset the endpoint toggle */ usb_reset_endpoint(sc->dev, endp);
usb_settoggle(sc->dev, endp, usb_pipeout(sc->last_pipe), 0);
return 0; return 0;
} }
......
...@@ -149,14 +149,7 @@ static void usb_ctrl_complete(struct urb *urb) ...@@ -149,14 +149,7 @@ static void usb_ctrl_complete(struct urb *urb)
if (ctrl_msg->dr.bRequest == USB_REQ_CLEAR_FEATURE) { if (ctrl_msg->dr.bRequest == USB_REQ_CLEAR_FEATURE) {
/* Special case handling for pipe reset */ /* Special case handling for pipe reset */
le16_to_cpus(&ctrl_msg->dr.wIndex); le16_to_cpus(&ctrl_msg->dr.wIndex);
usb_reset_endpoint(adapter->usb_dev, ctrl_msg->dr.wIndex);
/* toggle is reset on clear */
usb_settoggle(adapter->usb_dev,
ctrl_msg->dr.wIndex & ~USB_DIR_IN,
(ctrl_msg->dr.wIndex & USB_DIR_IN) == 0,
0);
} }
if (ctrl_msg->complete) if (ctrl_msg->complete)
......
...@@ -1461,7 +1461,6 @@ static int pvr2_upload_firmware1(struct pvr2_hdw *hdw) ...@@ -1461,7 +1461,6 @@ static int pvr2_upload_firmware1(struct pvr2_hdw *hdw)
return ret; return ret;
} }
usb_settoggle(hdw->usb_dev, 0 & 0xf, !(0 & USB_DIR_IN), 0);
usb_clear_halt(hdw->usb_dev, usb_sndbulkpipe(hdw->usb_dev, 0 & 0x7f)); usb_clear_halt(hdw->usb_dev, usb_sndbulkpipe(hdw->usb_dev, 0 & 0x7f));
pipe = usb_sndctrlpipe(hdw->usb_dev, 0); pipe = usb_sndctrlpipe(hdw->usb_dev, 0);
......
...@@ -652,7 +652,7 @@ static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id) ...@@ -652,7 +652,7 @@ static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id)
iface = &intf->altsetting[0]; iface = &intf->altsetting[0];
ep = &iface->endpoint[0].desc; ep = &iface->endpoint[0].desc;
if (!usb_endpoint_is_int_in(ep)) { if (!ep || !usb_endpoint_is_int_in(ep)) {
rv = -EINVAL; rv = -EINVAL;
goto err; goto err;
} }
......
...@@ -841,7 +841,7 @@ static int proc_resetep(struct dev_state *ps, void __user *arg) ...@@ -841,7 +841,7 @@ static int proc_resetep(struct dev_state *ps, void __user *arg)
ret = checkintf(ps, ret); ret = checkintf(ps, ret);
if (ret) if (ret)
return ret; return ret;
usb_settoggle(ps->dev, ep & 0xf, !(ep & USB_DIR_IN), 0); usb_reset_endpoint(ps->dev, ep);
return 0; return 0;
} }
......
...@@ -1539,6 +1539,32 @@ void usb_hcd_disable_endpoint(struct usb_device *udev, ...@@ -1539,6 +1539,32 @@ void usb_hcd_disable_endpoint(struct usb_device *udev,
hcd->driver->endpoint_disable(hcd, ep); hcd->driver->endpoint_disable(hcd, ep);
} }
/**
* usb_hcd_reset_endpoint - reset host endpoint state
* @udev: USB device.
* @ep: the endpoint to reset.
*
* Resets any host endpoint state such as the toggle bit, sequence
* number and current window.
*/
void usb_hcd_reset_endpoint(struct usb_device *udev,
struct usb_host_endpoint *ep)
{
struct usb_hcd *hcd = bus_to_hcd(udev->bus);
if (hcd->driver->endpoint_reset)
hcd->driver->endpoint_reset(hcd, ep);
else {
int epnum = usb_endpoint_num(&ep->desc);
int is_out = usb_endpoint_dir_out(&ep->desc);
int is_control = usb_endpoint_xfer_control(&ep->desc);
usb_settoggle(udev, epnum, is_out, 0);
if (is_control)
usb_settoggle(udev, epnum, !is_out, 0);
}
}
/* Protect against drivers that try to unlink URBs after the device /* Protect against drivers that try to unlink URBs after the device
* is gone, by waiting until all unlinks for @udev are finished. * is gone, by waiting until all unlinks for @udev are finished.
* Since we don't currently track URBs by device, simply wait until * Since we don't currently track URBs by device, simply wait until
......
...@@ -206,6 +206,11 @@ struct hc_driver { ...@@ -206,6 +206,11 @@ struct hc_driver {
void (*endpoint_disable)(struct usb_hcd *hcd, void (*endpoint_disable)(struct usb_hcd *hcd,
struct usb_host_endpoint *ep); struct usb_host_endpoint *ep);
/* (optional) reset any endpoint state such as sequence number
and current window */
void (*endpoint_reset)(struct usb_hcd *hcd,
struct usb_host_endpoint *ep);
/* root hub support */ /* root hub support */
int (*hub_status_data) (struct usb_hcd *hcd, char *buf); int (*hub_status_data) (struct usb_hcd *hcd, char *buf);
int (*hub_control) (struct usb_hcd *hcd, int (*hub_control) (struct usb_hcd *hcd,
...@@ -234,6 +239,8 @@ extern void usb_hcd_flush_endpoint(struct usb_device *udev, ...@@ -234,6 +239,8 @@ extern void usb_hcd_flush_endpoint(struct usb_device *udev,
struct usb_host_endpoint *ep); struct usb_host_endpoint *ep);
extern void usb_hcd_disable_endpoint(struct usb_device *udev, extern void usb_hcd_disable_endpoint(struct usb_device *udev,
struct usb_host_endpoint *ep); struct usb_host_endpoint *ep);
extern void usb_hcd_reset_endpoint(struct usb_device *udev,
struct usb_host_endpoint *ep);
extern void usb_hcd_synchronize_unlinks(struct usb_device *udev); extern void usb_hcd_synchronize_unlinks(struct usb_device *udev);
extern int usb_hcd_get_frame_number(struct usb_device *udev); extern int usb_hcd_get_frame_number(struct usb_device *udev);
...@@ -279,6 +286,13 @@ extern irqreturn_t usb_hcd_irq(int irq, void *__hcd); ...@@ -279,6 +286,13 @@ extern irqreturn_t usb_hcd_irq(int irq, void *__hcd);
extern void usb_hc_died(struct usb_hcd *hcd); extern void usb_hc_died(struct usb_hcd *hcd);
extern void usb_hcd_poll_rh_status(struct usb_hcd *hcd); extern void usb_hcd_poll_rh_status(struct usb_hcd *hcd);
/* The D0/D1 toggle bits ... USE WITH CAUTION (they're almost hcd-internal) */
#define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> (ep)) & 1)
#define usb_dotoggle(dev, ep, out) ((dev)->toggle[out] ^= (1 << (ep)))
#define usb_settoggle(dev, ep, out, bit) \
((dev)->toggle[out] = ((dev)->toggle[out] & ~(1 << (ep))) | \
((bit) << (ep)))
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* Enumeration is only for the hub driver, or HCD virtual root hubs */ /* Enumeration is only for the hub driver, or HCD virtual root hubs */
......
...@@ -1002,8 +1002,7 @@ int usb_clear_halt(struct usb_device *dev, int pipe) ...@@ -1002,8 +1002,7 @@ int usb_clear_halt(struct usb_device *dev, int pipe)
* the copy in usb-storage, for as long as we need two copies. * the copy in usb-storage, for as long as we need two copies.
*/ */
/* toggle was reset by the clear */ usb_reset_endpoint(dev, endp);
usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0);
return 0; return 0;
} }
...@@ -1075,6 +1074,30 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr, ...@@ -1075,6 +1074,30 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr,
} }
} }
/**
* usb_reset_endpoint - Reset an endpoint's state.
* @dev: the device whose endpoint is to be reset
* @epaddr: the endpoint's address. Endpoint number for output,
* endpoint number + USB_DIR_IN for input
*
* Resets any host-side endpoint state such as the toggle bit,
* sequence number or current window.
*/
void usb_reset_endpoint(struct usb_device *dev, unsigned int epaddr)
{
unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK;
struct usb_host_endpoint *ep;
if (usb_endpoint_out(epaddr))
ep = dev->ep_out[epnum];
else
ep = dev->ep_in[epnum];
if (ep)
usb_hcd_reset_endpoint(dev, ep);
}
EXPORT_SYMBOL_GPL(usb_reset_endpoint);
/** /**
* usb_disable_interface -- Disable all endpoints for an interface * usb_disable_interface -- Disable all endpoints for an interface
* @dev: the device whose interface is being disabled * @dev: the device whose interface is being disabled
...@@ -1117,7 +1140,6 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) ...@@ -1117,7 +1140,6 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
usb_disable_endpoint(dev, i, true); usb_disable_endpoint(dev, i, true);
usb_disable_endpoint(dev, i + USB_DIR_IN, true); usb_disable_endpoint(dev, i + USB_DIR_IN, true);
} }
dev->toggle[0] = dev->toggle[1] = 0;
/* getting rid of interfaces will disconnect /* getting rid of interfaces will disconnect
* any drivers bound to them (a key side effect) * any drivers bound to them (a key side effect)
...@@ -1154,28 +1176,24 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) ...@@ -1154,28 +1176,24 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
* usb_enable_endpoint - Enable an endpoint for USB communications * usb_enable_endpoint - Enable an endpoint for USB communications
* @dev: the device whose interface is being enabled * @dev: the device whose interface is being enabled
* @ep: the endpoint * @ep: the endpoint
* @reset_toggle: flag to set the endpoint's toggle back to 0 * @reset_ep: flag to reset the endpoint state
* *
* Resets the endpoint toggle if asked, and sets dev->ep_{in,out} pointers. * Resets the endpoint state if asked, and sets dev->ep_{in,out} pointers.
* For control endpoints, both the input and output sides are handled. * For control endpoints, both the input and output sides are handled.
*/ */
void usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep, void usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep,
bool reset_toggle) bool reset_ep)
{ {
int epnum = usb_endpoint_num(&ep->desc); int epnum = usb_endpoint_num(&ep->desc);
int is_out = usb_endpoint_dir_out(&ep->desc); int is_out = usb_endpoint_dir_out(&ep->desc);
int is_control = usb_endpoint_xfer_control(&ep->desc); int is_control = usb_endpoint_xfer_control(&ep->desc);
if (is_out || is_control) { if (reset_ep)
if (reset_toggle) usb_hcd_reset_endpoint(dev, ep);
usb_settoggle(dev, epnum, 1, 0); if (is_out || is_control)
dev->ep_out[epnum] = ep; dev->ep_out[epnum] = ep;
} if (!is_out || is_control)
if (!is_out || is_control) {
if (reset_toggle)
usb_settoggle(dev, epnum, 0, 0);
dev->ep_in[epnum] = ep; dev->ep_in[epnum] = ep;
}
ep->enabled = 1; ep->enabled = 1;
} }
...@@ -1183,18 +1201,18 @@ void usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep, ...@@ -1183,18 +1201,18 @@ void usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep,
* usb_enable_interface - Enable all the endpoints for an interface * usb_enable_interface - Enable all the endpoints for an interface
* @dev: the device whose interface is being enabled * @dev: the device whose interface is being enabled
* @intf: pointer to the interface descriptor * @intf: pointer to the interface descriptor
* @reset_toggles: flag to set the endpoints' toggles back to 0 * @reset_eps: flag to reset the endpoints' state
* *
* Enables all the endpoints for the interface's current altsetting. * Enables all the endpoints for the interface's current altsetting.
*/ */
void usb_enable_interface(struct usb_device *dev, void usb_enable_interface(struct usb_device *dev,
struct usb_interface *intf, bool reset_toggles) struct usb_interface *intf, bool reset_eps)
{ {
struct usb_host_interface *alt = intf->cur_altsetting; struct usb_host_interface *alt = intf->cur_altsetting;
int i; int i;
for (i = 0; i < alt->desc.bNumEndpoints; ++i) for (i = 0; i < alt->desc.bNumEndpoints; ++i)
usb_enable_endpoint(dev, &alt->endpoint[i], reset_toggles); usb_enable_endpoint(dev, &alt->endpoint[i], reset_eps);
} }
/** /**
...@@ -1335,7 +1353,7 @@ EXPORT_SYMBOL_GPL(usb_set_interface); ...@@ -1335,7 +1353,7 @@ EXPORT_SYMBOL_GPL(usb_set_interface);
* This issues a standard SET_CONFIGURATION request to the device using * This issues a standard SET_CONFIGURATION request to the device using
* the current configuration. The effect is to reset most USB-related * the current configuration. The effect is to reset most USB-related
* state in the device, including interface altsettings (reset to zero), * state in the device, including interface altsettings (reset to zero),
* endpoint halts (cleared), and data toggle (only for bulk and interrupt * endpoint halts (cleared), and endpoint state (only for bulk and interrupt
* endpoints). Other usbcore state is unchanged, including bindings of * endpoints). Other usbcore state is unchanged, including bindings of
* usb device drivers to interfaces. * usb device drivers to interfaces.
* *
...@@ -1343,7 +1361,7 @@ EXPORT_SYMBOL_GPL(usb_set_interface); ...@@ -1343,7 +1361,7 @@ EXPORT_SYMBOL_GPL(usb_set_interface);
* (multi-interface) devices. Instead, the driver for each interface may * (multi-interface) devices. Instead, the driver for each interface may
* use usb_set_interface() on the interfaces it claims. Be careful though; * use usb_set_interface() on the interfaces it claims. Be careful though;
* some devices don't support the SET_INTERFACE request, and others won't * some devices don't support the SET_INTERFACE request, and others won't
* reset all the interface state (notably data toggles). Resetting the whole * reset all the interface state (notably endpoint state). Resetting the whole
* configuration would affect other drivers' interfaces. * configuration would affect other drivers' interfaces.
* *
* The caller must own the device lock. * The caller must own the device lock.
...@@ -1376,8 +1394,6 @@ int usb_reset_configuration(struct usb_device *dev) ...@@ -1376,8 +1394,6 @@ int usb_reset_configuration(struct usb_device *dev)
if (retval < 0) if (retval < 0)
return retval; return retval;
dev->toggle[0] = dev->toggle[1] = 0;
/* re-init hc/hcd interface/endpoint state */ /* re-init hc/hcd interface/endpoint state */
for (i = 0; i < config->desc.bNumInterfaces; i++) { for (i = 0; i < config->desc.bNumInterfaces; i++) {
struct usb_interface *intf = config->interface[i]; struct usb_interface *intf = config->interface[i];
......
...@@ -362,7 +362,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, ...@@ -362,7 +362,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE; dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE;
dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT; dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT;
/* ep0 maxpacket comes later, from device descriptor */ /* ep0 maxpacket comes later, from device descriptor */
usb_enable_endpoint(dev, &dev->ep0, true); usb_enable_endpoint(dev, &dev->ep0, false);
dev->can_submit = 1; dev->can_submit = 1;
/* Save readable and stable topology id, distinguishing devices /* Save readable and stable topology id, distinguishing devices
......
...@@ -175,12 +175,6 @@ static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p) ...@@ -175,12 +175,6 @@ static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p)
strlcpy(p->bus_info, dev_name(&dev->gadget->dev), sizeof p->bus_info); strlcpy(p->bus_info, dev_name(&dev->gadget->dev), sizeof p->bus_info);
} }
static u32 eth_get_link(struct net_device *net)
{
struct eth_dev *dev = netdev_priv(net);
return dev->gadget->speed != USB_SPEED_UNKNOWN;
}
/* REVISIT can also support: /* REVISIT can also support:
* - WOL (by tracking suspends and issuing remote wakeup) * - WOL (by tracking suspends and issuing remote wakeup)
* - msglevel (implies updated messaging) * - msglevel (implies updated messaging)
...@@ -189,7 +183,7 @@ static u32 eth_get_link(struct net_device *net) ...@@ -189,7 +183,7 @@ static u32 eth_get_link(struct net_device *net)
static struct ethtool_ops ops = { static struct ethtool_ops ops = {
.get_drvinfo = eth_get_drvinfo, .get_drvinfo = eth_get_drvinfo,
.get_link = eth_get_link .get_link = ethtool_op_get_link,
}; };
static void defer_kevent(struct eth_dev *dev, int flag) static void defer_kevent(struct eth_dev *dev, int flag)
......
...@@ -122,7 +122,8 @@ static uint32_t process_qset(struct whc *whc, struct whc_qset *qset) ...@@ -122,7 +122,8 @@ static uint32_t process_qset(struct whc *whc, struct whc_qset *qset)
process_inactive_qtd(whc, qset, td); process_inactive_qtd(whc, qset, td);
} }
update |= qset_add_qtds(whc, qset); if (!qset->remove)
update |= qset_add_qtds(whc, qset);
done: done:
/* /*
...@@ -254,23 +255,29 @@ int asl_urb_enqueue(struct whc *whc, struct urb *urb, gfp_t mem_flags) ...@@ -254,23 +255,29 @@ int asl_urb_enqueue(struct whc *whc, struct urb *urb, gfp_t mem_flags)
spin_lock_irqsave(&whc->lock, flags); spin_lock_irqsave(&whc->lock, flags);
err = usb_hcd_link_urb_to_ep(&whc->wusbhc.usb_hcd, urb);
if (err < 0) {
spin_unlock_irqrestore(&whc->lock, flags);
return err;
}
qset = get_qset(whc, urb, GFP_ATOMIC); qset = get_qset(whc, urb, GFP_ATOMIC);
if (qset == NULL) if (qset == NULL)
err = -ENOMEM; err = -ENOMEM;
else else
err = qset_add_urb(whc, qset, urb, GFP_ATOMIC); err = qset_add_urb(whc, qset, urb, GFP_ATOMIC);
if (!err) { if (!err) {
usb_hcd_link_urb_to_ep(&whc->wusbhc.usb_hcd, urb);
if (!qset->in_sw_list) if (!qset->in_sw_list)
asl_qset_insert_begin(whc, qset); asl_qset_insert_begin(whc, qset);
} } else
usb_hcd_unlink_urb_from_ep(&whc->wusbhc.usb_hcd, urb);
spin_unlock_irqrestore(&whc->lock, flags); spin_unlock_irqrestore(&whc->lock, flags);
if (!err) if (!err)
queue_work(whc->workqueue, &whc->async_work); queue_work(whc->workqueue, &whc->async_work);
return 0; return err;
} }
/** /**
......
...@@ -186,6 +186,28 @@ static void whc_endpoint_disable(struct usb_hcd *usb_hcd, ...@@ -186,6 +186,28 @@ static void whc_endpoint_disable(struct usb_hcd *usb_hcd,
} }
} }
static void whc_endpoint_reset(struct usb_hcd *usb_hcd,
struct usb_host_endpoint *ep)
{
struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd);
struct whc *whc = wusbhc_to_whc(wusbhc);
struct whc_qset *qset;
qset = ep->hcpriv;
if (qset) {
qset->remove = 1;
if (usb_endpoint_xfer_bulk(&ep->desc)
|| usb_endpoint_xfer_control(&ep->desc))
queue_work(whc->workqueue, &whc->async_work);
else
queue_work(whc->workqueue, &whc->periodic_work);
qset_reset(whc, qset);
}
}
static struct hc_driver whc_hc_driver = { static struct hc_driver whc_hc_driver = {
.description = "whci-hcd", .description = "whci-hcd",
.product_desc = "Wireless host controller", .product_desc = "Wireless host controller",
...@@ -200,6 +222,7 @@ static struct hc_driver whc_hc_driver = { ...@@ -200,6 +222,7 @@ static struct hc_driver whc_hc_driver = {
.urb_enqueue = whc_urb_enqueue, .urb_enqueue = whc_urb_enqueue,
.urb_dequeue = whc_urb_dequeue, .urb_dequeue = whc_urb_dequeue,
.endpoint_disable = whc_endpoint_disable, .endpoint_disable = whc_endpoint_disable,
.endpoint_reset = whc_endpoint_reset,
.hub_status_data = wusbhc_rh_status_data, .hub_status_data = wusbhc_rh_status_data,
.hub_control = wusbhc_rh_control, .hub_control = wusbhc_rh_control,
......
...@@ -128,7 +128,8 @@ static enum whc_update pzl_process_qset(struct whc *whc, struct whc_qset *qset) ...@@ -128,7 +128,8 @@ static enum whc_update pzl_process_qset(struct whc *whc, struct whc_qset *qset)
process_inactive_qtd(whc, qset, td); process_inactive_qtd(whc, qset, td);
} }
update |= qset_add_qtds(whc, qset); if (!qset->remove)
update |= qset_add_qtds(whc, qset);
done: done:
/* /*
...@@ -282,23 +283,29 @@ int pzl_urb_enqueue(struct whc *whc, struct urb *urb, gfp_t mem_flags) ...@@ -282,23 +283,29 @@ int pzl_urb_enqueue(struct whc *whc, struct urb *urb, gfp_t mem_flags)
spin_lock_irqsave(&whc->lock, flags); spin_lock_irqsave(&whc->lock, flags);
err = usb_hcd_link_urb_to_ep(&whc->wusbhc.usb_hcd, urb);
if (err < 0) {
spin_unlock_irqrestore(&whc->lock, flags);
return err;
}
qset = get_qset(whc, urb, GFP_ATOMIC); qset = get_qset(whc, urb, GFP_ATOMIC);
if (qset == NULL) if (qset == NULL)
err = -ENOMEM; err = -ENOMEM;
else else
err = qset_add_urb(whc, qset, urb, GFP_ATOMIC); err = qset_add_urb(whc, qset, urb, GFP_ATOMIC);
if (!err) { if (!err) {
usb_hcd_link_urb_to_ep(&whc->wusbhc.usb_hcd, urb);
if (!qset->in_sw_list) if (!qset->in_sw_list)
qset_insert_in_sw_list(whc, qset); qset_insert_in_sw_list(whc, qset);
} } else
usb_hcd_unlink_urb_from_ep(&whc->wusbhc.usb_hcd, urb);
spin_unlock_irqrestore(&whc->lock, flags); spin_unlock_irqrestore(&whc->lock, flags);
if (!err) if (!err)
queue_work(whc->workqueue, &whc->periodic_work); queue_work(whc->workqueue, &whc->periodic_work);
return 0; return err;
} }
/** /**
...@@ -353,7 +360,6 @@ void pzl_qset_delete(struct whc *whc, struct whc_qset *qset) ...@@ -353,7 +360,6 @@ void pzl_qset_delete(struct whc *whc, struct whc_qset *qset)
qset_delete(whc, qset); qset_delete(whc, qset);
} }
/** /**
* pzl_init - initialize the periodic zone list * pzl_init - initialize the periodic zone list
* @whc: the WHCI host controller * @whc: the WHCI host controller
......
...@@ -89,11 +89,16 @@ static void qset_fill_qh(struct whc_qset *qset, struct urb *urb) ...@@ -89,11 +89,16 @@ static void qset_fill_qh(struct whc_qset *qset, struct urb *urb)
QH_INFO3_TX_RATE_53_3 QH_INFO3_TX_RATE_53_3
| QH_INFO3_TX_PWR(0) /* 0 == max power */ | QH_INFO3_TX_PWR(0) /* 0 == max power */
); );
qset->qh.cur_window = cpu_to_le32((1 << qset->max_burst) - 1);
} }
/** /**
* qset_clear - clear fields in a qset so it may be reinserted into a * qset_clear - clear fields in a qset so it may be reinserted into a
* schedule * schedule.
*
* The sequence number and current window are not cleared (see
* qset_reset()).
*/ */
void qset_clear(struct whc *whc, struct whc_qset *qset) void qset_clear(struct whc *whc, struct whc_qset *qset)
{ {
...@@ -101,9 +106,8 @@ void qset_clear(struct whc *whc, struct whc_qset *qset) ...@@ -101,9 +106,8 @@ void qset_clear(struct whc *whc, struct whc_qset *qset)
qset->remove = 0; qset->remove = 0;
qset->qh.link = cpu_to_le32(QH_LINK_NTDS(8) | QH_LINK_T); qset->qh.link = cpu_to_le32(QH_LINK_NTDS(8) | QH_LINK_T);
qset->qh.status = cpu_to_le16(QH_STATUS_ICUR(qset->td_start)); qset->qh.status = qset->qh.status & QH_STATUS_SEQ_MASK;
qset->qh.err_count = 0; qset->qh.err_count = 0;
qset->qh.cur_window = cpu_to_le32((1 << qset->max_burst) - 1);
qset->qh.scratch[0] = 0; qset->qh.scratch[0] = 0;
qset->qh.scratch[1] = 0; qset->qh.scratch[1] = 0;
qset->qh.scratch[2] = 0; qset->qh.scratch[2] = 0;
...@@ -113,6 +117,20 @@ void qset_clear(struct whc *whc, struct whc_qset *qset) ...@@ -113,6 +117,20 @@ void qset_clear(struct whc *whc, struct whc_qset *qset)
init_completion(&qset->remove_complete); init_completion(&qset->remove_complete);
} }
/**
* qset_reset - reset endpoint state in a qset.
*
* Clears the sequence number and current window. This qset must not
* be in the ASL or PZL.
*/
void qset_reset(struct whc *whc, struct whc_qset *qset)
{
wait_for_completion(&qset->remove_complete);
qset->qh.status &= ~QH_STATUS_SEQ_MASK;
qset->qh.cur_window = cpu_to_le32((1 << qset->max_burst) - 1);
}
/** /**
* get_qset - get the qset for an async endpoint * get_qset - get the qset for an async endpoint
* *
......
...@@ -184,6 +184,7 @@ void qset_free(struct whc *whc, struct whc_qset *qset); ...@@ -184,6 +184,7 @@ void qset_free(struct whc *whc, struct whc_qset *qset);
struct whc_qset *get_qset(struct whc *whc, struct urb *urb, gfp_t mem_flags); struct whc_qset *get_qset(struct whc *whc, struct urb *urb, gfp_t mem_flags);
void qset_delete(struct whc *whc, struct whc_qset *qset); void qset_delete(struct whc *whc, struct whc_qset *qset);
void qset_clear(struct whc *whc, struct whc_qset *qset); void qset_clear(struct whc *whc, struct whc_qset *qset);
void qset_reset(struct whc *whc, struct whc_qset *qset);
int qset_add_urb(struct whc *whc, struct whc_qset *qset, struct urb *urb, int qset_add_urb(struct whc *whc, struct whc_qset *qset, struct urb *urb,
gfp_t mem_flags); gfp_t mem_flags);
void qset_free_std(struct whc *whc, struct whc_std *std); void qset_free_std(struct whc *whc, struct whc_std *std);
......
...@@ -185,6 +185,7 @@ struct whc_qhead { ...@@ -185,6 +185,7 @@ struct whc_qhead {
#define QH_STATUS_FLOW_CTRL (1 << 15) #define QH_STATUS_FLOW_CTRL (1 << 15)
#define QH_STATUS_ICUR(i) ((i) << 5) #define QH_STATUS_ICUR(i) ((i) << 5)
#define QH_STATUS_TO_ICUR(s) (((s) >> 5) & 0x7) #define QH_STATUS_TO_ICUR(s) (((s) >> 5) & 0x7)
#define QH_STATUS_SEQ_MASK 0x1f
/** /**
* usb_pipe_to_qh_type - USB core pipe type to QH transfer type * usb_pipe_to_qh_type - USB core pipe type to QH transfer type
......
...@@ -579,6 +579,7 @@ cppi_next_tx_segment(struct musb *musb, struct cppi_channel *tx) ...@@ -579,6 +579,7 @@ cppi_next_tx_segment(struct musb *musb, struct cppi_channel *tx)
* trigger the "send a ZLP?" confusion. * trigger the "send a ZLP?" confusion.
*/ */
rndis = (maxpacket & 0x3f) == 0 rndis = (maxpacket & 0x3f) == 0
&& length > maxpacket
&& length < 0xffff && length < 0xffff
&& (length % maxpacket) != 0; && (length % maxpacket) != 0;
...@@ -1228,27 +1229,7 @@ void cppi_completion(struct musb *musb, u32 rx, u32 tx) ...@@ -1228,27 +1229,7 @@ void cppi_completion(struct musb *musb, u32 rx, u32 tx)
hw_ep = tx_ch->hw_ep; hw_ep = tx_ch->hw_ep;
/* Peripheral role never repurposes the musb_dma_completion(musb, index + 1, 1);
* endpoint, so immediate completion is
* safe. Host role waits for the fifo
* to empty (TXPKTRDY irq) before going
* to the next queued bulk transfer.
*/
if (is_host_active(cppi->musb)) {
#if 0
/* WORKAROUND because we may
* not always get TXKPTRDY ...
*/
int csr;
csr = musb_readw(hw_ep->regs,
MUSB_TXCSR);
if (csr & MUSB_TXCSR_TXPKTRDY)
#endif
completed = false;
}
if (completed)
musb_dma_completion(musb, index + 1, 1);
} else { } else {
/* Bigger transfer than we could fit in /* Bigger transfer than we could fit in
......
...@@ -2170,26 +2170,22 @@ static int musb_suspend(struct platform_device *pdev, pm_message_t message) ...@@ -2170,26 +2170,22 @@ static int musb_suspend(struct platform_device *pdev, pm_message_t message)
return 0; return 0;
} }
static int musb_resume(struct platform_device *pdev) static int musb_resume_early(struct platform_device *pdev)
{ {
unsigned long flags;
struct musb *musb = dev_to_musb(&pdev->dev); struct musb *musb = dev_to_musb(&pdev->dev);
if (!musb->clock) if (!musb->clock)
return 0; return 0;
spin_lock_irqsave(&musb->lock, flags);
if (musb->set_clock) if (musb->set_clock)
musb->set_clock(musb->clock, 1); musb->set_clock(musb->clock, 1);
else else
clk_enable(musb->clock); clk_enable(musb->clock);
/* for static cmos like DaVinci, register values were preserved /* for static cmos like DaVinci, register values were preserved
* unless for some reason the whole soc powered down and we're * unless for some reason the whole soc powered down or the USB
* not treating that as a whole-system restart (e.g. swsusp) * module got reset through the PSC (vs just being disabled).
*/ */
spin_unlock_irqrestore(&musb->lock, flags);
return 0; return 0;
} }
...@@ -2207,7 +2203,7 @@ static struct platform_driver musb_driver = { ...@@ -2207,7 +2203,7 @@ static struct platform_driver musb_driver = {
.remove = __devexit_p(musb_remove), .remove = __devexit_p(musb_remove),
.shutdown = musb_shutdown, .shutdown = musb_shutdown,
.suspend = musb_suspend, .suspend = musb_suspend,
.resume = musb_resume, .resume_early = musb_resume_early,
}; };
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
......
...@@ -165,9 +165,15 @@ static void nuke(struct musb_ep *ep, const int status) ...@@ -165,9 +165,15 @@ static void nuke(struct musb_ep *ep, const int status)
if (is_dma_capable() && ep->dma) { if (is_dma_capable() && ep->dma) {
struct dma_controller *c = ep->musb->dma_controller; struct dma_controller *c = ep->musb->dma_controller;
int value; int value;
if (ep->is_in) { if (ep->is_in) {
/*
* The programming guide says that we must not clear
* the DMAMODE bit before DMAENAB, so we only
* clear it in the second write...
*/
musb_writew(epio, MUSB_TXCSR, musb_writew(epio, MUSB_TXCSR,
0 | MUSB_TXCSR_FLUSHFIFO); MUSB_TXCSR_DMAMODE | MUSB_TXCSR_FLUSHFIFO);
musb_writew(epio, MUSB_TXCSR, musb_writew(epio, MUSB_TXCSR,
0 | MUSB_TXCSR_FLUSHFIFO); 0 | MUSB_TXCSR_FLUSHFIFO);
} else { } else {
...@@ -230,7 +236,7 @@ static inline int max_ep_writesize(struct musb *musb, struct musb_ep *ep) ...@@ -230,7 +236,7 @@ static inline int max_ep_writesize(struct musb *musb, struct musb_ep *ep)
| IN token(s) are recd from Host. | IN token(s) are recd from Host.
| -> DMA interrupt on completion | -> DMA interrupt on completion
| calls TxAvail. | calls TxAvail.
| -> stop DMA, ~DmaEenab, | -> stop DMA, ~DMAENAB,
| -> set TxPktRdy for last short pkt or zlp | -> set TxPktRdy for last short pkt or zlp
| -> Complete Request | -> Complete Request
| -> Continue next request (call txstate) | -> Continue next request (call txstate)
...@@ -315,9 +321,17 @@ static void txstate(struct musb *musb, struct musb_request *req) ...@@ -315,9 +321,17 @@ static void txstate(struct musb *musb, struct musb_request *req)
request->dma, request_size); request->dma, request_size);
if (use_dma) { if (use_dma) {
if (musb_ep->dma->desired_mode == 0) { if (musb_ep->dma->desired_mode == 0) {
/* ASSERT: DMAENAB is clear */ /*
csr &= ~(MUSB_TXCSR_AUTOSET | * We must not clear the DMAMODE bit
MUSB_TXCSR_DMAMODE); * before the DMAENAB bit -- and the
* latter doesn't always get cleared
* before we get here...
*/
csr &= ~(MUSB_TXCSR_AUTOSET
| MUSB_TXCSR_DMAENAB);
musb_writew(epio, MUSB_TXCSR, csr
| MUSB_TXCSR_P_WZC_BITS);
csr &= ~MUSB_TXCSR_DMAMODE;
csr |= (MUSB_TXCSR_DMAENAB | csr |= (MUSB_TXCSR_DMAENAB |
MUSB_TXCSR_MODE); MUSB_TXCSR_MODE);
/* against programming guide */ /* against programming guide */
...@@ -334,10 +348,7 @@ static void txstate(struct musb *musb, struct musb_request *req) ...@@ -334,10 +348,7 @@ static void txstate(struct musb *musb, struct musb_request *req)
#elif defined(CONFIG_USB_TI_CPPI_DMA) #elif defined(CONFIG_USB_TI_CPPI_DMA)
/* program endpoint CSR first, then setup DMA */ /* program endpoint CSR first, then setup DMA */
csr &= ~(MUSB_TXCSR_AUTOSET csr &= ~(MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY);
| MUSB_TXCSR_DMAMODE
| MUSB_TXCSR_P_UNDERRUN
| MUSB_TXCSR_TXPKTRDY);
csr |= MUSB_TXCSR_MODE | MUSB_TXCSR_DMAENAB; csr |= MUSB_TXCSR_MODE | MUSB_TXCSR_DMAENAB;
musb_writew(epio, MUSB_TXCSR, musb_writew(epio, MUSB_TXCSR,
(MUSB_TXCSR_P_WZC_BITS & ~MUSB_TXCSR_P_UNDERRUN) (MUSB_TXCSR_P_WZC_BITS & ~MUSB_TXCSR_P_UNDERRUN)
...@@ -364,8 +375,8 @@ static void txstate(struct musb *musb, struct musb_request *req) ...@@ -364,8 +375,8 @@ static void txstate(struct musb *musb, struct musb_request *req)
if (!use_dma) { if (!use_dma) {
c->channel_release(musb_ep->dma); c->channel_release(musb_ep->dma);
musb_ep->dma = NULL; musb_ep->dma = NULL;
/* ASSERT: DMAENAB clear */ csr &= ~MUSB_TXCSR_DMAENAB;
csr &= ~(MUSB_TXCSR_DMAMODE | MUSB_TXCSR_MODE); musb_writew(epio, MUSB_TXCSR, csr);
/* invariant: prequest->buf is non-null */ /* invariant: prequest->buf is non-null */
} }
#elif defined(CONFIG_USB_TUSB_OMAP_DMA) #elif defined(CONFIG_USB_TUSB_OMAP_DMA)
......
This diff is collapsed.
...@@ -195,30 +195,32 @@ static int dma_channel_abort(struct dma_channel *channel) ...@@ -195,30 +195,32 @@ static int dma_channel_abort(struct dma_channel *channel)
void __iomem *mbase = musb_channel->controller->base; void __iomem *mbase = musb_channel->controller->base;
u8 bchannel = musb_channel->idx; u8 bchannel = musb_channel->idx;
int offset;
u16 csr; u16 csr;
if (channel->status == MUSB_DMA_STATUS_BUSY) { if (channel->status == MUSB_DMA_STATUS_BUSY) {
if (musb_channel->transmit) { if (musb_channel->transmit) {
offset = MUSB_EP_OFFSET(musb_channel->epnum,
csr = musb_readw(mbase, MUSB_TXCSR);
MUSB_EP_OFFSET(musb_channel->epnum,
MUSB_TXCSR)); /*
csr &= ~(MUSB_TXCSR_AUTOSET | * The programming guide says that we must clear
MUSB_TXCSR_DMAENAB | * the DMAENAB bit before the DMAMODE bit...
MUSB_TXCSR_DMAMODE); */
musb_writew(mbase, csr = musb_readw(mbase, offset);
MUSB_EP_OFFSET(musb_channel->epnum, MUSB_TXCSR), csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB);
csr); musb_writew(mbase, offset, csr);
csr &= ~MUSB_TXCSR_DMAMODE;
musb_writew(mbase, offset, csr);
} else { } else {
csr = musb_readw(mbase, offset = MUSB_EP_OFFSET(musb_channel->epnum,
MUSB_EP_OFFSET(musb_channel->epnum, MUSB_RXCSR);
MUSB_RXCSR));
csr = musb_readw(mbase, offset);
csr &= ~(MUSB_RXCSR_AUTOCLEAR | csr &= ~(MUSB_RXCSR_AUTOCLEAR |
MUSB_RXCSR_DMAENAB | MUSB_RXCSR_DMAENAB |
MUSB_RXCSR_DMAMODE); MUSB_RXCSR_DMAMODE);
musb_writew(mbase, musb_writew(mbase, offset, csr);
MUSB_EP_OFFSET(musb_channel->epnum, MUSB_RXCSR),
csr);
} }
musb_writew(mbase, musb_writew(mbase,
...@@ -296,20 +298,28 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data) ...@@ -296,20 +298,28 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data)
&& ((channel->desired_mode == 0) && ((channel->desired_mode == 0)
|| (channel->actual_len & || (channel->actual_len &
(musb_channel->max_packet_sz - 1))) (musb_channel->max_packet_sz - 1)))
) { ) {
u8 epnum = musb_channel->epnum;
int offset = MUSB_EP_OFFSET(epnum,
MUSB_TXCSR);
u16 txcsr;
/*
* The programming guide says that we
* must clear DMAENAB before DMAMODE.
*/
musb_ep_select(mbase, epnum);
txcsr = musb_readw(mbase, offset);
txcsr &= ~(MUSB_TXCSR_DMAENAB
| MUSB_TXCSR_AUTOSET);
musb_writew(mbase, offset, txcsr);
/* Send out the packet */ /* Send out the packet */
musb_ep_select(mbase, txcsr &= ~MUSB_TXCSR_DMAMODE;
musb_channel->epnum); txcsr |= MUSB_TXCSR_TXPKTRDY;
musb_writew(mbase, MUSB_EP_OFFSET( musb_writew(mbase, offset, txcsr);
musb_channel->epnum,
MUSB_TXCSR),
MUSB_TXCSR_TXPKTRDY);
} else {
musb_dma_completion(
musb,
musb_channel->epnum,
musb_channel->transmit);
} }
musb_dma_completion(musb, musb_channel->epnum,
musb_channel->transmit);
} }
} }
} }
......
...@@ -668,6 +668,7 @@ static struct usb_device_id id_table_combined [] = { ...@@ -668,6 +668,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(DE_VID, WHT_PID) }, { USB_DEVICE(DE_VID, WHT_PID) },
{ USB_DEVICE(ADI_VID, ADI_GNICE_PID), { USB_DEVICE(ADI_VID, ADI_GNICE_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(JETI_VID, JETI_SPC1201_PID) },
{ }, /* Optional parameter entry */ { }, /* Optional parameter entry */
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
......
...@@ -912,6 +912,13 @@ ...@@ -912,6 +912,13 @@
#define ADI_VID 0x0456 #define ADI_VID 0x0456
#define ADI_GNICE_PID 0xF000 #define ADI_GNICE_PID 0xF000
/*
* JETI SPECTROMETER SPECBOS 1201
* http://www.jeti.com/products/sys/scb/scb1201.php
*/
#define JETI_VID 0x0c6c
#define JETI_SPC1201_PID 0x04b2
/* /*
* BmRequestType: 1100 0000b * BmRequestType: 1100 0000b
* bRequest: FTDI_E2_READ * bRequest: FTDI_E2_READ
......
...@@ -25,6 +25,7 @@ static struct usb_device_id id_table [] = { ...@@ -25,6 +25,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x05c6, 0x3197) }, /* unknown Motorola phone */ { USB_DEVICE(0x05c6, 0x3197) }, /* unknown Motorola phone */
{ USB_DEVICE(0x0c44, 0x0022) }, /* unknown Mororola phone */ { USB_DEVICE(0x0c44, 0x0022) }, /* unknown Mororola phone */
{ USB_DEVICE(0x22b8, 0x2a64) }, /* Motorola KRZR K1m */ { USB_DEVICE(0x22b8, 0x2a64) }, /* Motorola KRZR K1m */
{ USB_DEVICE(0x22b8, 0x2c64) }, /* Motorola V950 phone */
{ }, { },
}; };
MODULE_DEVICE_TABLE(usb, id_table); MODULE_DEVICE_TABLE(usb, id_table);
......
...@@ -300,6 +300,10 @@ static int option_resume(struct usb_serial *serial); ...@@ -300,6 +300,10 @@ static int option_resume(struct usb_serial *serial);
#define BENQ_VENDOR_ID 0x04a5 #define BENQ_VENDOR_ID 0x04a5
#define BENQ_PRODUCT_H10 0x4068 #define BENQ_PRODUCT_H10 0x4068
#define DLINK_VENDOR_ID 0x1186
#define DLINK_PRODUCT_DWM_652 0x3e04
static struct usb_device_id option_ids[] = { static struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
...@@ -516,6 +520,7 @@ static struct usb_device_id option_ids[] = { ...@@ -516,6 +520,7 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628) }, { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628) },
{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) }, { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) },
{ USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) }, { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
{ USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },
{ USB_DEVICE(0x1da5, 0x4515) }, /* BenQ H20 */ { USB_DEVICE(0x1da5, 0x4515) }, /* BenQ H20 */
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
......
...@@ -26,6 +26,27 @@ static struct usb_device_id id_table[] = { ...@@ -26,6 +26,27 @@ static struct usb_device_id id_table[] = {
{USB_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ {USB_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */
{USB_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */ {USB_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */
{USB_DEVICE(0x03f0, 0x201d)}, /* HP un2400 Gobi QDL Device */ {USB_DEVICE(0x03f0, 0x201d)}, /* HP un2400 Gobi QDL Device */
{USB_DEVICE(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */
{USB_DEVICE(0x04da, 0x250c)}, /* Panasonic Gobi QDL device */
{USB_DEVICE(0x413c, 0x8172)}, /* Dell Gobi Modem device */
{USB_DEVICE(0x413c, 0x8171)}, /* Dell Gobi QDL device */
{USB_DEVICE(0x1410, 0xa001)}, /* Novatel Gobi Modem device */
{USB_DEVICE(0x1410, 0xa008)}, /* Novatel Gobi QDL device */
{USB_DEVICE(0x0b05, 0x1776)}, /* Asus Gobi Modem device */
{USB_DEVICE(0x0b05, 0x1774)}, /* Asus Gobi QDL device */
{USB_DEVICE(0x19d2, 0xfff3)}, /* ONDA Gobi Modem device */
{USB_DEVICE(0x19d2, 0xfff2)}, /* ONDA Gobi QDL device */
{USB_DEVICE(0x1557, 0x0a80)}, /* OQO Gobi QDL device */
{USB_DEVICE(0x05c6, 0x9001)}, /* Generic Gobi Modem device */
{USB_DEVICE(0x05c6, 0x9002)}, /* Generic Gobi Modem device */
{USB_DEVICE(0x05c6, 0x9202)}, /* Generic Gobi Modem device */
{USB_DEVICE(0x05c6, 0x9203)}, /* Generic Gobi Modem device */
{USB_DEVICE(0x05c6, 0x9222)}, /* Generic Gobi Modem device */
{USB_DEVICE(0x05c6, 0x9008)}, /* Generic Gobi QDL device */
{USB_DEVICE(0x05c6, 0x9201)}, /* Generic Gobi QDL device */
{USB_DEVICE(0x05c6, 0x9221)}, /* Generic Gobi QDL device */
{USB_DEVICE(0x05c6, 0x9231)}, /* Generic Gobi QDL device */
{USB_DEVICE(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
MODULE_DEVICE_TABLE(usb, id_table); MODULE_DEVICE_TABLE(usb, id_table);
......
...@@ -17,7 +17,8 @@ usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \ ...@@ -17,7 +17,8 @@ usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \
ifeq ($(CONFIG_USB_LIBUSUAL),) ifeq ($(CONFIG_USB_LIBUSUAL),)
usb-storage-objs += usual-tables.o usb-storage-objs += usual-tables.o
else else
obj-$(CONFIG_USB) += libusual.o usual-tables.o obj-$(CONFIG_USB) += usb-libusual.o
usb-libusual-objs := libusual.o usual-tables.o
endif endif
obj-$(CONFIG_USB_STORAGE_ALAUDA) += ums-alauda.o obj-$(CONFIG_USB_STORAGE_ALAUDA) += ums-alauda.o
......
...@@ -247,10 +247,8 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe) ...@@ -247,10 +247,8 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe)
USB_ENDPOINT_HALT, endp, USB_ENDPOINT_HALT, endp,
NULL, 0, 3*HZ); NULL, 0, 3*HZ);
/* reset the endpoint toggle */
if (result >= 0) if (result >= 0)
usb_settoggle(us->pusb_dev, usb_pipeendpoint(pipe), usb_reset_endpoint(us->pusb_dev, endp);
usb_pipeout(pipe), 0);
US_DEBUGP("%s: result = %d\n", __func__, result); US_DEBUGP("%s: result = %d\n", __func__, result);
return result; return result;
......
...@@ -975,12 +975,14 @@ UNUSUAL_DEV( 0x07c4, 0xa400, 0x0000, 0xffff, ...@@ -975,12 +975,14 @@ UNUSUAL_DEV( 0x07c4, 0xa400, 0x0000, 0xffff,
US_SC_DEVICE, US_PR_DEVICE, NULL, US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY | US_FL_FIX_CAPACITY ), US_FL_FIX_INQUIRY | US_FL_FIX_CAPACITY ),
/* Reported by Rauch Wolke <rauchwolke@gmx.net> */ /* Reported by Rauch Wolke <rauchwolke@gmx.net>
* and augmented by binbin <binbinsh@gmail.com> (Bugzilla #12882)
*/
UNUSUAL_DEV( 0x07c4, 0xa4a5, 0x0000, 0xffff, UNUSUAL_DEV( 0x07c4, 0xa4a5, 0x0000, 0xffff,
"Simple Tech/Datafab", "Simple Tech/Datafab",
"CF+SM Reader", "CF+SM Reader",
US_SC_DEVICE, US_PR_DEVICE, NULL, US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ), US_FL_IGNORE_RESIDUE | US_FL_MAX_SECTORS_64 ),
/* Casio QV 2x00/3x00/4000/8000 digital still cameras are not conformant /* Casio QV 2x00/3x00/4000/8000 digital still cameras are not conformant
* to the USB storage specification in two ways: * to the USB storage specification in two ways:
...@@ -1376,6 +1378,14 @@ UNUSUAL_DEV( 0x10d6, 0x2200, 0x0100, 0x0100, ...@@ -1376,6 +1378,14 @@ UNUSUAL_DEV( 0x10d6, 0x2200, 0x0100, 0x0100,
US_SC_DEVICE, US_PR_DEVICE, NULL, US_SC_DEVICE, US_PR_DEVICE, NULL,
0), 0),
/* Reported by Pascal Terjan <pterjan@mandriva.com>
* Ignore driver CD mode and force into modem mode by default.
*/
UNUSUAL_DEV( 0x1186, 0x3e04, 0x0000, 0x0000,
"D-Link",
"USB Mass Storage",
US_SC_DEVICE, US_PR_DEVICE, option_ms_init, 0),
/* Reported by Kevin Lloyd <linux@sierrawireless.com> /* Reported by Kevin Lloyd <linux@sierrawireless.com>
* Entry is needed for the initializer function override, * Entry is needed for the initializer function override,
* which instructs the device to load as a modem * which instructs the device to load as a modem
......
...@@ -267,6 +267,8 @@ static void wusbhc_devconnect_acked_work(struct work_struct *work) ...@@ -267,6 +267,8 @@ static void wusbhc_devconnect_acked_work(struct work_struct *work)
mutex_lock(&wusbhc->mutex); mutex_lock(&wusbhc->mutex);
wusbhc_devconnect_acked(wusbhc, wusb_dev); wusbhc_devconnect_acked(wusbhc, wusb_dev);
mutex_unlock(&wusbhc->mutex); mutex_unlock(&wusbhc->mutex);
wusb_dev_put(wusb_dev);
} }
/* /*
...@@ -396,7 +398,8 @@ static void __wusbhc_dev_disconnect(struct wusbhc *wusbhc, ...@@ -396,7 +398,8 @@ static void __wusbhc_dev_disconnect(struct wusbhc *wusbhc,
/* After a device disconnects, change the GTK (see [WUSB] /* After a device disconnects, change the GTK (see [WUSB]
* section 6.2.11.2). */ * section 6.2.11.2). */
wusbhc_gtk_rekey(wusbhc); if (wusbhc->active)
wusbhc_gtk_rekey(wusbhc);
/* The Wireless USB part has forgotten about the device already; now /* The Wireless USB part has forgotten about the device already; now
* khubd's timer will pick up the disconnection and remove the USB * khubd's timer will pick up the disconnection and remove the USB
...@@ -1084,15 +1087,21 @@ int wusbhc_devconnect_start(struct wusbhc *wusbhc) ...@@ -1084,15 +1087,21 @@ int wusbhc_devconnect_start(struct wusbhc *wusbhc)
* wusbhc_devconnect_stop - stop managing connected devices * wusbhc_devconnect_stop - stop managing connected devices
* @wusbhc: the WUSB HC * @wusbhc: the WUSB HC
* *
* Removes the Host Info IE and stops the keep alives. * Disconnects any devices still connected, stops the keep alives and
* * removes the Host Info IE.
* FIXME: should this disconnect all devices?
*/ */
void wusbhc_devconnect_stop(struct wusbhc *wusbhc) void wusbhc_devconnect_stop(struct wusbhc *wusbhc)
{ {
cancel_delayed_work_sync(&wusbhc->keep_alive_timer); int i;
WARN_ON(!list_empty(&wusbhc->cack_list));
mutex_lock(&wusbhc->mutex);
for (i = 0; i < wusbhc->ports_max; i++) {
if (wusbhc->port[i].wusb_dev)
__wusbhc_dev_disconnect(wusbhc, &wusbhc->port[i]);
}
mutex_unlock(&wusbhc->mutex);
cancel_delayed_work_sync(&wusbhc->keep_alive_timer);
wusbhc_mmcie_rm(wusbhc, &wusbhc->wuie_host_info->hdr); wusbhc_mmcie_rm(wusbhc, &wusbhc->wuie_host_info->hdr);
kfree(wusbhc->wuie_host_info); kfree(wusbhc->wuie_host_info);
wusbhc->wuie_host_info = NULL; wusbhc->wuie_host_info = NULL;
......
...@@ -88,33 +88,31 @@ static DEVICE_ATTR(wusb_trust_timeout, 0644, wusb_trust_timeout_show, ...@@ -88,33 +88,31 @@ static DEVICE_ATTR(wusb_trust_timeout, 0644, wusb_trust_timeout_show,
wusb_trust_timeout_store); wusb_trust_timeout_store);
/* /*
* Show & store the current WUSB CHID * Show the current WUSB CHID.
*/ */
static ssize_t wusb_chid_show(struct device *dev, static ssize_t wusb_chid_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct wusbhc *wusbhc = usbhc_dev_to_wusbhc(dev); struct wusbhc *wusbhc = usbhc_dev_to_wusbhc(dev);
const struct wusb_ckhdid *chid;
ssize_t result = 0; ssize_t result = 0;
if (wusbhc->wuie_host_info != NULL) if (wusbhc->wuie_host_info != NULL)
result += ckhdid_printf(buf, PAGE_SIZE, chid = &wusbhc->wuie_host_info->CHID;
&wusbhc->wuie_host_info->CHID); else
chid = &wusb_ckhdid_zero;
result += ckhdid_printf(buf, PAGE_SIZE, chid);
result += sprintf(buf + result, "\n");
return result; return result;
} }
/* /*
* Store a new CHID * Store a new CHID.
*
* This will (FIXME) trigger many changes.
*
* - Send an all zeros CHID and it will stop the controller
* - Send a non-zero CHID and it will start it
* (unless it was started, it will just change the CHID,
* diconnecting all devices first).
* *
* So first we scan the MMC we are sent and then we act on it. We * - Write an all zeros CHID and it will stop the controller
* read it in the same format as we print it, an ASCII string of 16 * - Write a non-zero CHID and it will start it.
* hex bytes.
* *
* See wusbhc_chid_set() for more info. * See wusbhc_chid_set() for more info.
*/ */
...@@ -339,13 +337,15 @@ void wusbhc_giveback_urb(struct wusbhc *wusbhc, struct urb *urb, int status) ...@@ -339,13 +337,15 @@ void wusbhc_giveback_urb(struct wusbhc *wusbhc, struct urb *urb, int status)
{ {
struct wusb_dev *wusb_dev = __wusb_dev_get_by_usb_dev(wusbhc, urb->dev); struct wusb_dev *wusb_dev = __wusb_dev_get_by_usb_dev(wusbhc, urb->dev);
if (status == 0) { if (status == 0 && wusb_dev) {
wusb_dev->entry_ts = jiffies; wusb_dev->entry_ts = jiffies;
/* wusbhc_devconnect_acked() can't be called from from /* wusbhc_devconnect_acked() can't be called from
atomic context so defer it to a work queue. */ atomic context so defer it to a work queue. */
if (!list_empty(&wusb_dev->cack_node)) if (!list_empty(&wusb_dev->cack_node))
queue_work(wusbd, &wusb_dev->devconnect_acked_work); queue_work(wusbd, &wusb_dev->devconnect_acked_work);
else
wusb_dev_put(wusb_dev);
} }
usb_hcd_giveback_urb(&wusbhc->usb_hcd, urb, status); usb_hcd_giveback_urb(&wusbhc->usb_hcd, urb, status);
......
...@@ -1387,6 +1387,7 @@ extern int usb_string(struct usb_device *dev, int index, ...@@ -1387,6 +1387,7 @@ extern int usb_string(struct usb_device *dev, int index,
extern int usb_clear_halt(struct usb_device *dev, int pipe); extern int usb_clear_halt(struct usb_device *dev, int pipe);
extern int usb_reset_configuration(struct usb_device *dev); extern int usb_reset_configuration(struct usb_device *dev);
extern int usb_set_interface(struct usb_device *dev, int ifnum, int alternate); extern int usb_set_interface(struct usb_device *dev, int ifnum, int alternate);
extern void usb_reset_endpoint(struct usb_device *dev, unsigned int epaddr);
/* this request isn't really synchronous, but it belongs with the others */ /* this request isn't really synchronous, but it belongs with the others */
extern int usb_driver_set_configuration(struct usb_device *udev, int config); extern int usb_driver_set_configuration(struct usb_device *udev, int config);
...@@ -1491,14 +1492,6 @@ void usb_sg_wait(struct usb_sg_request *io); ...@@ -1491,14 +1492,6 @@ void usb_sg_wait(struct usb_sg_request *io);
#define usb_pipecontrol(pipe) (usb_pipetype((pipe)) == PIPE_CONTROL) #define usb_pipecontrol(pipe) (usb_pipetype((pipe)) == PIPE_CONTROL)
#define usb_pipebulk(pipe) (usb_pipetype((pipe)) == PIPE_BULK) #define usb_pipebulk(pipe) (usb_pipetype((pipe)) == PIPE_BULK)
/* The D0/D1 toggle bits ... USE WITH CAUTION (they're almost hcd-internal) */
#define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> (ep)) & 1)
#define usb_dotoggle(dev, ep, out) ((dev)->toggle[out] ^= (1 << (ep)))
#define usb_settoggle(dev, ep, out, bit) \
((dev)->toggle[out] = ((dev)->toggle[out] & ~(1 << (ep))) | \
((bit) << (ep)))
static inline unsigned int __create_pipe(struct usb_device *dev, static inline unsigned int __create_pipe(struct usb_device *dev,
unsigned int endpoint) unsigned int endpoint)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment