Commit 80edade6 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://linuxusb.bkbits.net/linus-2.5

into penguin.transmeta.com:/home/penguin/torvalds/repositories/kernel/linux
parents 0abd9281 baf56435
...@@ -36,7 +36,7 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length) ...@@ -36,7 +36,7 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
add_wait_queue(&awd.wqh, &wait); add_wait_queue(&awd.wqh, &wait);
urb->context = &awd; urb->context = &awd;
status = usb_submit_urb(urb, GFP_KERNEL); status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) { if (status) {
// something went wrong // something went wrong
usb_free_urb(urb); usb_free_urb(urb);
......
...@@ -12,6 +12,9 @@ ...@@ -12,6 +12,9 @@
* *
* History: * History:
* *
* 2002/06/01 remember frame when HC won't see EDs any more; use that info
* to fix urb unlink races caused by interrupt latency assumptions;
* minor ED field and function naming updates
* 2002/01/18 package as a patch for 2.5.3; this should match the * 2002/01/18 package as a patch for 2.5.3; this should match the
* 2.4.17 kernel modulo some bugs being fixed. * 2.4.17 kernel modulo some bugs being fixed.
* *
...@@ -106,7 +109,7 @@ ...@@ -106,7 +109,7 @@
* - lots more testing!! * - lots more testing!!
*/ */
#define DRIVER_VERSION "$Revision: 1.9 $" #define DRIVER_VERSION "2002-Jun-01"
#define DRIVER_AUTHOR "Roman Weissgaerber <weissg@vienna.at>, David Brownell" #define DRIVER_AUTHOR "Roman Weissgaerber <weissg@vienna.at>, David Brownell"
#define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver" #define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver"
...@@ -287,7 +290,7 @@ static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) ...@@ -287,7 +290,7 @@ static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
} }
urb_priv->state = URB_DEL; urb_priv->state = URB_DEL;
ed_unlink (urb->dev, urb_priv->ed); start_urb_unlink (ohci, urb_priv->ed);
spin_unlock_irqrestore (&ohci->lock, flags); spin_unlock_irqrestore (&ohci->lock, flags);
} else { } else {
/* /*
...@@ -508,16 +511,15 @@ static void ohci_irq (struct usb_hcd *hcd) ...@@ -508,16 +511,15 @@ static void ohci_irq (struct usb_hcd *hcd)
/* could track INTR_SO to reduce available PCI/... bandwidth */ /* could track INTR_SO to reduce available PCI/... bandwidth */
// FIXME: this assumes SOF (1/ms) interrupts don't get lost... /* handle any pending URB/ED unlinks, leaving INTR_SF enabled
if (ints & OHCI_INTR_SF) { * when there's still unlinking to be done (next frame).
unsigned int frame = le16_to_cpu (ohci->hcca->frame_no) & 1; */
spin_lock (&ohci->lock);
if (ohci->ed_rm_list)
finish_unlinks (ohci, le16_to_cpu (ohci->hcca->frame_no));
if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list)
writel (OHCI_INTR_SF, &regs->intrdisable); writel (OHCI_INTR_SF, &regs->intrdisable);
if (ohci->ed_rm_list [!frame] != NULL) { spin_unlock (&ohci->lock);
dl_del_list (ohci, !frame);
}
if (ohci->ed_rm_list [frame] != NULL)
writel (OHCI_INTR_SF, &regs->intrenable);
}
writel (ints, &regs->intrstatus); writel (ints, &regs->intrstatus);
writel (OHCI_INTR_MIE, &regs->intrenable); writel (OHCI_INTR_MIE, &regs->intrenable);
...@@ -719,8 +721,7 @@ static int hc_restart (struct ohci_hcd *ohci) ...@@ -719,8 +721,7 @@ static int hc_restart (struct ohci_hcd *ohci)
for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table [i] = 0; for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table [i] = 0;
/* no EDs to remove */ /* no EDs to remove */
ohci->ed_rm_list [0] = NULL; ohci->ed_rm_list = NULL;
ohci->ed_rm_list [1] = NULL;
/* empty control and bulk lists */ /* empty control and bulk lists */
ohci->ed_isotail = NULL; ohci->ed_isotail = NULL;
...@@ -802,7 +803,7 @@ static int ohci_resume (struct usb_hcd *hcd) ...@@ -802,7 +803,7 @@ static int ohci_resume (struct usb_hcd *hcd)
ohci->disabled = 0; ohci->disabled = 0;
ohci->sleeping = 0; ohci->sleeping = 0;
ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
if (!ohci->ed_rm_list [0] && !ohci->ed_rm_list [1]) { if (!ohci->ed_rm_list) {
if (ohci->ed_controltail) if (ohci->ed_controltail)
ohci->hc_control |= OHCI_CTRL_CLE; ohci->hc_control |= OHCI_CTRL_CLE;
if (ohci->ed_bulktail) if (ohci->ed_bulktail)
......
This diff is collapsed.
...@@ -27,22 +27,29 @@ struct ed { ...@@ -27,22 +27,29 @@ struct ed {
__u32 hwNextED; /* next ED in list */ __u32 hwNextED; /* next ED in list */
/* rest are purely for the driver's use */ /* rest are purely for the driver's use */
struct ed *ed_prev; dma_addr_t dma; /* addr of ED */
__u8 int_period; struct ed *ed_prev; /* for non-interrupt EDs */
__u8 int_branch;
__u8 int_load; u8 type; /* PIPE_{BULK,...} */
__u8 int_interval; u8 interval; /* interrupt, isochronous */
__u8 state; // ED_{NEW,UNLINK,OPER} union {
struct intr_info { /* interrupt */
u8 int_period;
u8 int_branch;
u8 int_load;
};
u16 last_iso; /* isochronous */
};
u8 state; /* ED_{NEW,UNLINK,OPER} */
#define ED_NEW 0x00 /* unused, no dummy td */ #define ED_NEW 0x00 /* unused, no dummy td */
#define ED_UNLINK 0x01 /* dummy td, maybe linked to hc */ #define ED_UNLINK 0x01 /* dummy td, maybe linked to hc */
#define ED_OPER 0x02 /* dummy td, _is_ linked to hc */ #define ED_OPER 0x02 /* dummy td, _is_ linked to hc */
#define ED_URB_DEL 0x08 /* for unlinking; masked in */ #define ED_URB_DEL 0x08 /* for unlinking; masked in */
__u8 type; /* HC may see EDs on rm_list until next frame (frame_no == tick) */
__u16 last_iso; u16 tick;
struct ed *ed_rm_list; struct ed *ed_rm_list;
dma_addr_t dma; /* addr of ED */
} __attribute__ ((aligned(16))); } __attribute__ ((aligned(16)));
#define ED_MASK ((u32)~0x0f) /* strip hw status in low addr bits */ #define ED_MASK ((u32)~0x0f) /* strip hw status in low addr bits */
...@@ -335,7 +342,7 @@ struct ohci_hcd { ...@@ -335,7 +342,7 @@ struct ohci_hcd {
struct ohci_hcca *hcca; struct ohci_hcca *hcca;
dma_addr_t hcca_dma; dma_addr_t hcca_dma;
struct ed *ed_rm_list [2]; /* to be removed */ struct ed *ed_rm_list; /* to be removed */
struct ed *ed_bulktail; /* last in bulk list */ struct ed *ed_bulktail; /* last in bulk list */
struct ed *ed_controltail; /* last in ctrl list */ struct ed *ed_controltail; /* last in ctrl list */
......
...@@ -2515,7 +2515,7 @@ static const struct hc_driver uhci_driver = { ...@@ -2515,7 +2515,7 @@ static const struct hc_driver uhci_driver = {
suspend: uhci_suspend, suspend: uhci_suspend,
resume: uhci_resume, resume: uhci_resume,
#endif #endif
stop: uhci_stop, stop: __devexit_p(uhci_stop),
hcd_alloc: uhci_hcd_alloc, hcd_alloc: uhci_hcd_alloc,
hcd_free: uhci_hcd_free, hcd_free: uhci_hcd_free,
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h>
#include <linux/usb.h> #include <linux/usb.h>
#define MAX_INTEL_HEX_RECORD_LENGTH 16 #define MAX_INTEL_HEX_RECORD_LENGTH 16
......
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