Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
Browse files Browse the repository at this point in the history
* 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
  ...
  • Loading branch information
Linus Torvalds committed Apr 17, 2009
2 parents 7217fa9 + fca10c8 commit dd26bf6
Show file tree
Hide file tree
Showing 32 changed files with 532 additions and 348 deletions.
20 changes: 9 additions & 11 deletions drivers/block/ub.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 bulk_cs_wrap *bcs;
int endp;
int len;
int rc;

Expand All @@ -1033,6 +1034,10 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
return;
}

endp = usb_pipeendpoint(sc->last_pipe);
if (usb_pipein(sc->last_pipe))
endp |= USB_DIR_IN;

if (cmd->state == UB_CMDST_CLEAR) {
if (urb->status == -EPIPE) {
/*
Expand All @@ -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.
*/

/* reset the endpoint toggle */
usb_settoggle(sc->dev, usb_pipeendpoint(sc->last_pipe),
usb_pipeout(sc->last_pipe), 0);
usb_reset_endpoint(sc->dev, endp);

ub_state_sense(sc, cmd);

Expand All @@ -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.
*/

/* reset the endpoint toggle */
usb_settoggle(sc->dev, usb_pipeendpoint(sc->last_pipe),
usb_pipeout(sc->last_pipe), 0);
usb_reset_endpoint(sc->dev, endp);

ub_state_stat(sc, cmd);

Expand All @@ -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.
*/

/* reset the endpoint toggle */
usb_settoggle(sc->dev, usb_pipeendpoint(sc->last_pipe),
usb_pipeout(sc->last_pipe), 0);
usb_reset_endpoint(sc->dev, endp);

ub_state_stat_counted(sc, cmd);

Expand Down Expand Up @@ -2119,8 +2118,7 @@ static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe)
del_timer_sync(&timer);
usb_kill_urb(&sc->work_urb);

/* reset the endpoint toggle */
usb_settoggle(sc->dev, endp, usb_pipeout(sc->last_pipe), 0);
usb_reset_endpoint(sc->dev, endp);

return 0;
}
Expand Down
9 changes: 1 addition & 8 deletions drivers/isdn/hisax/st5481_usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,14 +149,7 @@ static void usb_ctrl_complete(struct urb *urb)
if (ctrl_msg->dr.bRequest == USB_REQ_CLEAR_FEATURE) {
/* Special case handling for pipe reset */
le16_to_cpus(&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);


usb_reset_endpoint(adapter->usb_dev, ctrl_msg->dr.wIndex);
}

if (ctrl_msg->complete)
Expand Down
1 change: 0 additions & 1 deletion drivers/media/video/pvrusb2/pvrusb2-hdw.c
Original file line number Diff line number Diff line change
Expand Up @@ -1461,7 +1461,6 @@ static int pvr2_upload_firmware1(struct pvr2_hdw *hdw)
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));

pipe = usb_sndctrlpipe(hdw->usb_dev, 0);
Expand Down
2 changes: 1 addition & 1 deletion drivers/usb/class/cdc-wdm.c
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,7 @@ static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id)

iface = &intf->altsetting[0];
ep = &iface->endpoint[0].desc;
if (!usb_endpoint_is_int_in(ep)) {
if (!ep || !usb_endpoint_is_int_in(ep)) {
rv = -EINVAL;
goto err;
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/usb/core/devio.c
Original file line number Diff line number Diff line change
Expand Up @@ -841,7 +841,7 @@ static int proc_resetep(struct dev_state *ps, void __user *arg)
ret = checkintf(ps, ret);
if (ret)
return ret;
usb_settoggle(ps->dev, ep & 0xf, !(ep & USB_DIR_IN), 0);
usb_reset_endpoint(ps->dev, ep);
return 0;
}

Expand Down
26 changes: 26 additions & 0 deletions drivers/usb/core/hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1539,6 +1539,32 @@ void usb_hcd_disable_endpoint(struct usb_device *udev,
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
* is gone, by waiting until all unlinks for @udev are finished.
* Since we don't currently track URBs by device, simply wait until
Expand Down
14 changes: 14 additions & 0 deletions drivers/usb/core/hcd.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,11 @@ struct hc_driver {
void (*endpoint_disable)(struct usb_hcd *hcd,
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 */
int (*hub_status_data) (struct usb_hcd *hcd, char *buf);
int (*hub_control) (struct usb_hcd *hcd,
Expand Down Expand Up @@ -234,6 +239,8 @@ extern void usb_hcd_flush_endpoint(struct usb_device *udev,
struct usb_host_endpoint *ep);
extern void usb_hcd_disable_endpoint(struct usb_device *udev,
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 int usb_hcd_get_frame_number(struct usb_device *udev);

Expand Down Expand Up @@ -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_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 */
Expand Down
58 changes: 37 additions & 21 deletions drivers/usb/core/message.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/

/* toggle was reset by the clear */
usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0);
usb_reset_endpoint(dev, endp);

return 0;
}
Expand Down Expand Up @@ -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
* @dev: the device whose interface is being disabled
Expand Down Expand Up @@ -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 + USB_DIR_IN, true);
}
dev->toggle[0] = dev->toggle[1] = 0;

/* getting rid of interfaces will disconnect
* any drivers bound to them (a key side effect)
Expand Down Expand Up @@ -1154,47 +1176,43 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
* usb_enable_endpoint - Enable an endpoint for USB communications
* @dev: the device whose interface is being enabled
* @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.
*/
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 is_out = usb_endpoint_dir_out(&ep->desc);
int is_control = usb_endpoint_xfer_control(&ep->desc);

if (is_out || is_control) {
if (reset_toggle)
usb_settoggle(dev, epnum, 1, 0);
if (reset_ep)
usb_hcd_reset_endpoint(dev, ep);
if (is_out || is_control)
dev->ep_out[epnum] = ep;
}
if (!is_out || is_control) {
if (reset_toggle)
usb_settoggle(dev, epnum, 0, 0);
if (!is_out || is_control)
dev->ep_in[epnum] = ep;
}
ep->enabled = 1;
}

/**
* usb_enable_interface - Enable all the endpoints for an interface
* @dev: the device whose interface is being enabled
* @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.
*/
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;
int 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);
}

/**
Expand Down Expand Up @@ -1335,15 +1353,15 @@ EXPORT_SYMBOL_GPL(usb_set_interface);
* This issues a standard SET_CONFIGURATION request to the device using
* the current configuration. The effect is to reset most USB-related
* 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
* usb device drivers to interfaces.
*
* Because this affects multiple interfaces, avoid using this with composite
* (multi-interface) devices. Instead, the driver for each interface may
* 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
* 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.
*
* The caller must own the device lock.
Expand Down Expand Up @@ -1376,8 +1394,6 @@ int usb_reset_configuration(struct usb_device *dev)
if (retval < 0)
return retval;

dev->toggle[0] = dev->toggle[1] = 0;

/* re-init hc/hcd interface/endpoint state */
for (i = 0; i < config->desc.bNumInterfaces; i++) {
struct usb_interface *intf = config->interface[i];
Expand Down
2 changes: 1 addition & 1 deletion drivers/usb/core/usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.bDescriptorType = USB_DT_ENDPOINT;
/* 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;

/* Save readable and stable topology id, distinguishing devices
Expand Down
8 changes: 1 addition & 7 deletions drivers/usb/gadget/u_ether.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

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:
* - WOL (by tracking suspends and issuing remote wakeup)
* - msglevel (implies updated messaging)
Expand All @@ -189,7 +183,7 @@ static u32 eth_get_link(struct net_device *net)

static struct ethtool_ops ops = {
.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)
Expand Down
15 changes: 11 additions & 4 deletions drivers/usb/host/whci/asl.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ static uint32_t process_qset(struct whc *whc, struct whc_qset *qset)
process_inactive_qtd(whc, qset, td);
}

update |= qset_add_qtds(whc, qset);
if (!qset->remove)
update |= qset_add_qtds(whc, qset);

done:
/*
Expand Down Expand Up @@ -254,23 +255,29 @@ int asl_urb_enqueue(struct whc *whc, struct urb *urb, gfp_t mem_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);
if (qset == NULL)
err = -ENOMEM;
else
err = qset_add_urb(whc, qset, urb, GFP_ATOMIC);
if (!err) {
usb_hcd_link_urb_to_ep(&whc->wusbhc.usb_hcd, urb);
if (!qset->in_sw_list)
asl_qset_insert_begin(whc, qset);
}
} else
usb_hcd_unlink_urb_from_ep(&whc->wusbhc.usb_hcd, urb);

spin_unlock_irqrestore(&whc->lock, flags);

if (!err)
queue_work(whc->workqueue, &whc->async_work);

return 0;
return err;
}

/**
Expand Down
Loading

0 comments on commit dd26bf6

Please sign in to comment.