Commit bdd016ba authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

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: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 5b653c79
...@@ -943,7 +943,6 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 * ...@@ -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; ...@@ -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 { ...@@ -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 */
......
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