Commit 2193b1ea authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

usb host controllers:

	- add mem_flags support
	- portions of this patch by Oliver Neukum and David Brownell.
parent a707e953
...@@ -916,14 +916,13 @@ static void hc_died (struct usb_hcd *hcd) ...@@ -916,14 +916,13 @@ static void hc_died (struct usb_hcd *hcd)
/* may be called in any context with a valid urb->dev usecount */ /* may be called in any context with a valid urb->dev usecount */
/* caller surrenders "ownership" of urb (and chain at urb->next). */ /* caller surrenders "ownership" of urb (and chain at urb->next). */
static int hcd_submit_urb (struct urb *urb) static int hcd_submit_urb (struct urb *urb, int mem_flags)
{ {
int status; int status;
struct usb_hcd *hcd; struct usb_hcd *hcd;
struct hcd_dev *dev; struct hcd_dev *dev;
unsigned long flags; unsigned long flags;
int pipe; int pipe;
int mem_flags;
if (!urb || urb->hcpriv || !urb->complete) if (!urb || urb->hcpriv || !urb->complete)
return -EINVAL; return -EINVAL;
...@@ -947,11 +946,6 @@ static int hcd_submit_urb (struct urb *urb) ...@@ -947,11 +946,6 @@ static int hcd_submit_urb (struct urb *urb)
usb_pipeout (pipe))) usb_pipeout (pipe)))
return -EPIPE; return -EPIPE;
// FIXME paging/swapping requests over USB should not use GFP_KERNEL
// and might even need to use GFP_NOIO ... that flag actually needs
// to be passed from the higher level.
mem_flags = in_interrupt () ? GFP_ATOMIC : GFP_KERNEL;
#ifdef DEBUG #ifdef DEBUG
{ {
unsigned int orig_flags = urb->transfer_flags; unsigned int orig_flags = urb->transfer_flags;
...@@ -1316,7 +1310,7 @@ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb) ...@@ -1316,7 +1310,7 @@ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb)
else if (urb->next) { else if (urb->next) {
int status; int status;
status = usb_submit_urb (urb->next); status = usb_submit_urb (urb->next, GFP_ATOMIC);
if (status) { if (status) {
dbg ("urb %p chain fail, %d", urb->next, status); dbg ("urb %p chain fail, %d", urb->next, status);
urb->next->status = -ENOTCONN; urb->next->status = -ENOTCONN;
......
...@@ -1476,7 +1476,7 @@ static struct urb *uhci_find_urb_ep(struct uhci *uhci, struct urb *urb) ...@@ -1476,7 +1476,7 @@ static struct urb *uhci_find_urb_ep(struct uhci *uhci, struct urb *urb)
return u; return u;
} }
static int uhci_submit_urb(struct urb *urb) static int uhci_submit_urb(struct urb *urb, int mem_flags)
{ {
int ret = -EINVAL; int ret = -EINVAL;
struct uhci *uhci; struct uhci *uhci;
...@@ -1823,11 +1823,11 @@ static int uhci_get_current_frame_number(struct usb_device *dev) ...@@ -1823,11 +1823,11 @@ static int uhci_get_current_frame_number(struct usb_device *dev)
} }
struct usb_operations uhci_device_operations = { struct usb_operations uhci_device_operations = {
uhci_alloc_dev, allocate: uhci_alloc_dev,
uhci_free_dev, deallocate: uhci_free_dev,
uhci_get_current_frame_number, get_frame_number: uhci_get_current_frame_number,
uhci_submit_urb, submit_urb: uhci_submit_urb,
uhci_unlink_urb unlink_urb: uhci_unlink_urb,
}; };
/* Virtual Root Hub */ /* Virtual Root Hub */
...@@ -2294,7 +2294,7 @@ static void uhci_call_completion(struct urb *urb) ...@@ -2294,7 +2294,7 @@ static void uhci_call_completion(struct urb *urb)
} else { } else {
if (is_ring && !killed) { if (is_ring && !killed) {
urb->dev = dev; urb->dev = dev;
uhci_submit_urb(urb); uhci_submit_urb(urb, GFP_KERNEL);
} else { } else {
/* We decrement the usage count after we're done */ /* We decrement the usage count after we're done */
/* with everything */ /* with everything */
......
...@@ -532,7 +532,7 @@ static int sohci_return_urb (struct ohci *hc, struct urb * urb) ...@@ -532,7 +532,7 @@ static int sohci_return_urb (struct ohci *hc, struct urb * urb)
/* get a transfer request */ /* get a transfer request */
static int sohci_submit_urb (struct urb * urb) static int sohci_submit_urb (struct urb * urb, int mem_flags)
{ {
ohci_t * ohci; ohci_t * ohci;
ed_t * ed; ed_t * ed;
...@@ -542,7 +542,6 @@ static int sohci_submit_urb (struct urb * urb) ...@@ -542,7 +542,6 @@ static int sohci_submit_urb (struct urb * urb)
int i, size = 0; int i, size = 0;
unsigned long flags; unsigned long flags;
int bustime = 0; int bustime = 0;
int mem_flags = ALLOC_FLAGS;
if (!urb->dev || !urb->dev->bus) if (!urb->dev || !urb->dev->bus)
return -ENODEV; return -ENODEV;
...@@ -612,8 +611,7 @@ static int sohci_submit_urb (struct urb * urb) ...@@ -612,8 +611,7 @@ static int sohci_submit_urb (struct urb * urb)
} }
/* allocate the private part of the URB */ /* allocate the private part of the URB */
urb_priv = kmalloc (sizeof (urb_priv_t) + size * sizeof (td_t *), urb_priv = kmalloc (sizeof (urb_priv_t) + size * sizeof (td_t *), mem_flags);
in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
if (!urb_priv) { if (!urb_priv) {
usb_dec_dev_use (urb->dev); usb_dec_dev_use (urb->dev);
return -ENOMEM; return -ENOMEM;
...@@ -919,11 +917,11 @@ static int sohci_get_current_frame_number (struct usb_device *usb_dev) ...@@ -919,11 +917,11 @@ static int sohci_get_current_frame_number (struct usb_device *usb_dev)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
struct usb_operations sohci_device_operations = { struct usb_operations sohci_device_operations = {
sohci_alloc_dev, allocate: sohci_alloc_dev,
sohci_free_dev, deallocate: sohci_free_dev,
sohci_get_current_frame_number, get_frame_number: sohci_get_current_frame_number,
sohci_submit_urb, submit_urb: sohci_submit_urb,
sohci_unlink_urb unlink_urb: sohci_unlink_urb,
}; };
/*-------------------------------------------------------------------------* /*-------------------------------------------------------------------------*
......
...@@ -87,7 +87,6 @@ ...@@ -87,7 +87,6 @@
#endif #endif
#define SLAB_FLAG (in_interrupt ()? SLAB_ATOMIC : SLAB_KERNEL) #define SLAB_FLAG (in_interrupt ()? SLAB_ATOMIC : SLAB_KERNEL)
#define KMALLOC_FLAG (in_interrupt ()? GFP_ATOMIC : GFP_KERNEL)
/* CONFIG_USB_UHCI_HIGH_BANDWITH turns on Full Speed Bandwidth /* CONFIG_USB_UHCI_HIGH_BANDWITH turns on Full Speed Bandwidth
* Reclamation: feature that puts loop on descriptor loop when * Reclamation: feature that puts loop on descriptor loop when
...@@ -1502,7 +1501,7 @@ _static int uhci_submit_int_urb (struct urb *urb) ...@@ -1502,7 +1501,7 @@ _static int uhci_submit_int_urb (struct urb *urb)
return 0; return 0;
} }
/*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/
_static int uhci_submit_iso_urb (struct urb *urb) _static int uhci_submit_iso_urb (struct urb *urb, int mem_flags)
{ {
uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv; uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv;
urb_priv_t *urb_priv = urb->hcpriv; urb_priv_t *urb_priv = urb->hcpriv;
...@@ -1522,7 +1521,7 @@ _static int uhci_submit_iso_urb (struct urb *urb) ...@@ -1522,7 +1521,7 @@ _static int uhci_submit_iso_urb (struct urb *urb)
if (ret) if (ret)
goto err; goto err;
tdm = (uhci_desc_t **) kmalloc (urb->number_of_packets * sizeof (uhci_desc_t*), KMALLOC_FLAG); tdm = (uhci_desc_t **) kmalloc (urb->number_of_packets * sizeof (uhci_desc_t*), mem_flags);
if (!tdm) { if (!tdm) {
ret = -ENOMEM; ret = -ENOMEM;
...@@ -1619,7 +1618,7 @@ _static struct urb* search_dev_ep (uhci_t *s, struct urb *urb) ...@@ -1619,7 +1618,7 @@ _static struct urb* search_dev_ep (uhci_t *s, struct urb *urb)
return 0; return 0;
} }
/*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/
_static int uhci_submit_urb (struct urb *urb) _static int uhci_submit_urb (struct urb *urb, int mem_flags)
{ {
uhci_t *s; uhci_t *s;
urb_priv_t *urb_priv; urb_priv_t *urb_priv;
...@@ -1676,7 +1675,7 @@ _static int uhci_submit_urb (struct urb *urb) ...@@ -1676,7 +1675,7 @@ _static int uhci_submit_urb (struct urb *urb)
#ifdef DEBUG_SLAB #ifdef DEBUG_SLAB
urb_priv = kmem_cache_alloc(urb_priv_kmem, SLAB_FLAG); urb_priv = kmem_cache_alloc(urb_priv_kmem, SLAB_FLAG);
#else #else
urb_priv = kmalloc (sizeof (urb_priv_t), KMALLOC_FLAG); urb_priv = kmalloc (sizeof (urb_priv_t), mem_flags);
#endif #endif
if (!urb_priv) { if (!urb_priv) {
usb_dec_dev_use (urb->dev); usb_dec_dev_use (urb->dev);
...@@ -1729,12 +1728,12 @@ _static int uhci_submit_urb (struct urb *urb) ...@@ -1729,12 +1728,12 @@ _static int uhci_submit_urb (struct urb *urb)
if (bustime < 0) if (bustime < 0)
ret = bustime; ret = bustime;
else { else {
ret = uhci_submit_iso_urb(urb); ret = uhci_submit_iso_urb(urb, mem_flags);
if (ret == 0) if (ret == 0)
usb_claim_bandwidth (urb->dev, urb, bustime, 1); usb_claim_bandwidth (urb->dev, urb, bustime, 1);
} }
} else { /* bandwidth is already set */ } else { /* bandwidth is already set */
ret = uhci_submit_iso_urb(urb); ret = uhci_submit_iso_urb(urb, mem_flags);
} }
break; break;
case PIPE_INTERRUPT: case PIPE_INTERRUPT:
...@@ -2279,11 +2278,11 @@ _static int uhci_get_current_frame_number (struct usb_device *usb_dev) ...@@ -2279,11 +2278,11 @@ _static int uhci_get_current_frame_number (struct usb_device *usb_dev)
struct usb_operations uhci_device_operations = struct usb_operations uhci_device_operations =
{ {
uhci_alloc_dev, allocate: uhci_alloc_dev,
uhci_free_dev, deallocate: uhci_free_dev,
uhci_get_current_frame_number, get_frame_number: uhci_get_current_frame_number,
uhci_submit_urb, submit_urb: uhci_submit_urb,
uhci_unlink_urb unlink_urb: uhci_unlink_urb,
}; };
_static void correct_data_toggles(struct urb *urb) _static void correct_data_toggles(struct urb *urb)
...@@ -2697,7 +2696,10 @@ _static int process_urb (uhci_t *s, struct list_head *p) ...@@ -2697,7 +2696,10 @@ _static int process_urb (uhci_t *s, struct list_head *p)
spin_unlock(&s->urb_list_lock); spin_unlock(&s->urb_list_lock);
ret_submit=uhci_submit_urb(next_urb); // FIXME!!!
// We need to know the real state, so
// GFP_ATOMIC is probably not correct
ret_submit=uhci_submit_urb(next_urb, GFP_ATOMIC);
spin_lock(&s->urb_list_lock); spin_lock(&s->urb_list_lock);
if (ret_submit) if (ret_submit)
...@@ -2721,7 +2723,10 @@ _static int process_urb (uhci_t *s, struct list_head *p) ...@@ -2721,7 +2723,10 @@ _static int process_urb (uhci_t *s, struct list_head *p)
// Re-submit the URB if ring-linked // Re-submit the URB if ring-linked
if (is_ring && !was_unlinked && !contains_killed) { if (is_ring && !was_unlinked && !contains_killed) {
urb->dev=usb_dev; urb->dev=usb_dev;
uhci_submit_urb (urb); // FIXME!!!
// We need to know the real state, so
// GFP_ATOMIC is probably not correct
uhci_submit_urb (urb, GFP_ATOMIC);
} }
spin_lock(&s->urb_list_lock); spin_lock(&s->urb_list_lock);
} }
......
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