mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-15 00:04:15 +08:00
USB: add ep->enable
This patch (as944) adds an explicit "enabled" field to the usb_host_endpoint structure and uses it in place of the current mechanism. This is merely a time-space tradeoff; it makes checking whether URBs may be submitted to an endpoint simpler. The existing mechanism is efficient when converting urb->pipe to an endpoint pointer, but it's not so efficient when urb->ep is used instead. As a side effect, the procedure for enabling an endpoint is now a little more complicated. The ad-hoc inline code in usb.c and hub.c for enabling ep0 is now replaced with calls to usb_enable_endpoint, which is no longer static. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
5b653c79c0
commit
bdd016ba64
@ -943,7 +943,6 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
|
|||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
struct usb_hcd *hcd = bus_to_hcd(urb->dev->bus);
|
struct usb_hcd *hcd = bus_to_hcd(urb->dev->bus);
|
||||||
struct usb_host_endpoint *ep;
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if (!hcd)
|
if (!hcd)
|
||||||
@ -960,9 +959,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
|
|||||||
// FIXME: verify that quiescing hc works right (RH cleans up)
|
// FIXME: verify that quiescing hc works right (RH cleans up)
|
||||||
|
|
||||||
spin_lock_irqsave(&hcd_urb_list_lock, flags);
|
spin_lock_irqsave(&hcd_urb_list_lock, flags);
|
||||||
ep = (usb_pipein(urb->pipe) ? urb->dev->ep_in : urb->dev->ep_out)
|
if (unlikely(!urb->ep->enabled))
|
||||||
[usb_pipeendpoint(urb->pipe)];
|
|
||||||
if (unlikely(ep != urb->ep))
|
|
||||||
status = -ENOENT;
|
status = -ENOENT;
|
||||||
else if (unlikely (urb->reject))
|
else if (unlikely (urb->reject))
|
||||||
status = -EPERM;
|
status = -EPERM;
|
||||||
|
@ -1999,7 +1999,7 @@ static void ep0_reinit(struct usb_device *udev)
|
|||||||
{
|
{
|
||||||
usb_disable_endpoint(udev, 0 + USB_DIR_IN);
|
usb_disable_endpoint(udev, 0 + USB_DIR_IN);
|
||||||
usb_disable_endpoint(udev, 0 + USB_DIR_OUT);
|
usb_disable_endpoint(udev, 0 + USB_DIR_OUT);
|
||||||
udev->ep_in[0] = udev->ep_out[0] = &udev->ep0;
|
usb_enable_endpoint(udev, &udev->ep0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define usb_sndaddr0pipe() (PIPE_CONTROL << 30)
|
#define usb_sndaddr0pipe() (PIPE_CONTROL << 30)
|
||||||
|
@ -1013,8 +1013,10 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr)
|
|||||||
ep = dev->ep_in[epnum];
|
ep = dev->ep_in[epnum];
|
||||||
dev->ep_in[epnum] = NULL;
|
dev->ep_in[epnum] = NULL;
|
||||||
}
|
}
|
||||||
if (ep && dev->bus)
|
if (ep) {
|
||||||
|
ep->enabled = 0;
|
||||||
usb_hcd_endpoint_disable(dev, ep);
|
usb_hcd_endpoint_disable(dev, ep);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1096,23 +1098,21 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
|
|||||||
* Resets the endpoint toggle, and sets dev->ep_{in,out} pointers.
|
* Resets the endpoint toggle, 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.
|
||||||
*/
|
*/
|
||||||
static void
|
void usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep)
|
||||||
usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep)
|
|
||||||
{
|
{
|
||||||
unsigned int epaddr = ep->desc.bEndpointAddress;
|
int epnum = usb_endpoint_num(&ep->desc);
|
||||||
unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK;
|
int is_out = usb_endpoint_dir_out(&ep->desc);
|
||||||
int is_control;
|
int is_control = usb_endpoint_xfer_control(&ep->desc);
|
||||||
|
|
||||||
is_control = ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
|
if (is_out || is_control) {
|
||||||
== USB_ENDPOINT_XFER_CONTROL);
|
|
||||||
if (usb_endpoint_out(epaddr) || is_control) {
|
|
||||||
usb_settoggle(dev, epnum, 1, 0);
|
usb_settoggle(dev, epnum, 1, 0);
|
||||||
dev->ep_out[epnum] = ep;
|
dev->ep_out[epnum] = ep;
|
||||||
}
|
}
|
||||||
if (!usb_endpoint_out(epaddr) || is_control) {
|
if (!is_out || is_control) {
|
||||||
usb_settoggle(dev, epnum, 0, 0);
|
usb_settoggle(dev, epnum, 0, 0);
|
||||||
dev->ep_in[epnum] = ep;
|
dev->ep_in[epnum] = ep;
|
||||||
}
|
}
|
||||||
|
ep->enabled = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -260,7 +260,7 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
|
|||||||
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 */
|
||||||
dev->ep_in[0] = dev->ep_out[0] = &dev->ep0;
|
usb_enable_endpoint(dev, &dev->ep0);
|
||||||
|
|
||||||
/* Save readable and stable topology id, distinguishing devices
|
/* Save readable and stable topology id, distinguishing devices
|
||||||
* by location for diagnostics, tools, driver model, etc. The
|
* by location for diagnostics, tools, driver model, etc. The
|
||||||
|
@ -8,6 +8,8 @@ extern int usb_create_ep_files(struct device *parent, struct usb_host_endpoint *
|
|||||||
struct usb_device *udev);
|
struct usb_device *udev);
|
||||||
extern void usb_remove_ep_files(struct usb_host_endpoint *endpoint);
|
extern void usb_remove_ep_files(struct usb_host_endpoint *endpoint);
|
||||||
|
|
||||||
|
extern void usb_enable_endpoint(struct usb_device *dev,
|
||||||
|
struct usb_host_endpoint *ep);
|
||||||
extern void usb_disable_endpoint (struct usb_device *dev, unsigned int epaddr);
|
extern void usb_disable_endpoint (struct usb_device *dev, unsigned int epaddr);
|
||||||
extern void usb_disable_interface (struct usb_device *dev,
|
extern void usb_disable_interface (struct usb_device *dev,
|
||||||
struct usb_interface *intf);
|
struct usb_interface *intf);
|
||||||
|
@ -52,6 +52,7 @@ struct ep_device;
|
|||||||
* @ep_dev: ep_device for sysfs info
|
* @ep_dev: ep_device for sysfs info
|
||||||
* @extra: descriptors following this endpoint in the configuration
|
* @extra: descriptors following this endpoint in the configuration
|
||||||
* @extralen: how many bytes of "extra" are valid
|
* @extralen: how many bytes of "extra" are valid
|
||||||
|
* @enabled: URBs may be submitted to this endpoint
|
||||||
*
|
*
|
||||||
* USB requests are always queued to a given endpoint, identified by a
|
* USB requests are always queued to a given endpoint, identified by a
|
||||||
* descriptor within an active interface in a given USB configuration.
|
* descriptor within an active interface in a given USB configuration.
|
||||||
@ -64,6 +65,7 @@ struct usb_host_endpoint {
|
|||||||
|
|
||||||
unsigned char *extra; /* Extra descriptors */
|
unsigned char *extra; /* Extra descriptors */
|
||||||
int extralen;
|
int extralen;
|
||||||
|
int enabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* host-side wrapper for one interface setting's parsed descriptors */
|
/* host-side wrapper for one interface setting's parsed descriptors */
|
||||||
|
Loading…
Reference in New Issue
Block a user