Commit 2dc4da94 authored by Christopher Hoover's avatar Christopher Hoover Committed by Greg Kroah-Hartman

[PATCH] [PATCH] 2.5.44 sa-1111 ohci hcd

Dereferencing hcd.pdev will always oops with SA-1111.  It has to be
treated as a cookie, not a pointer in any common OHCI HCD code.

Apparently we need a clean way to go from struct device * to struct
ohci_hcd *.  I added dev_to_ohci that does the obvious thing and added
separate implementations for PCI and SA-1111.  Two implementations is
ugly but I didn't think it wise (for me) to hack on the PCI/driverfs
interface, so I just cut & paste the old code.

Two patches.  The first is a diff from linux-2.5.44 and
linux-2.5.44-rmk1.  It is from rmk and adds a struct device pointer to
ohci_hcd.  The second depends on the first and contains my changes to
clean up to the pdev oops problems.  (Some fuzz may occur as I have
ohci-1024 applied.)

With these changes, SA111 OHCI-HC/HCD is showing some signs of life on
linux-2.5.44-rmk1.  usb-storage is currentl blowing chunks, but I think
I saw some patches go by against 2.5.44 that I haven't yet tried.
parent 90f8a197
...@@ -77,6 +77,7 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */ ...@@ -77,6 +77,7 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */
/* a few non-PCI controllers exist, mostly for OHCI */ /* a few non-PCI controllers exist, mostly for OHCI */
struct pci_dev *pdev; /* pci is typical */ struct pci_dev *pdev; /* pci is typical */
struct device *parent; /* parent device driver */
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
int region; /* pci region for regs */ int region; /* pci region for regs */
u32 pci_state [16]; /* for PM state save */ u32 pci_state [16]; /* for PM state save */
......
...@@ -394,15 +394,14 @@ show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed) ...@@ -394,15 +394,14 @@ show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed)
static ssize_t static ssize_t
show_async (struct device *dev, char *buf, size_t count, loff_t off) show_async (struct device *dev, char *buf, size_t count, loff_t off)
{ {
struct pci_dev *pdev;
struct ohci_hcd *ohci; struct ohci_hcd *ohci;
size_t temp; size_t temp;
unsigned long flags; unsigned long flags;
if (off != 0) if (off != 0)
return 0; return 0;
pdev = container_of (dev, struct pci_dev, dev);
ohci = container_of (pci_get_drvdata (pdev), struct ohci_hcd, hcd); ohci = dev_to_ohci(dev);
/* display control and bulk lists together, for simplicity */ /* display control and bulk lists together, for simplicity */
spin_lock_irqsave (&ohci->lock, flags); spin_lock_irqsave (&ohci->lock, flags);
...@@ -420,7 +419,6 @@ static DEVICE_ATTR (async, S_IRUGO, show_async, NULL); ...@@ -420,7 +419,6 @@ static DEVICE_ATTR (async, S_IRUGO, show_async, NULL);
static ssize_t static ssize_t
show_periodic (struct device *dev, char *buf, size_t count, loff_t off) show_periodic (struct device *dev, char *buf, size_t count, loff_t off)
{ {
struct pci_dev *pdev;
struct ohci_hcd *ohci; struct ohci_hcd *ohci;
struct ed **seen, *ed; struct ed **seen, *ed;
unsigned long flags; unsigned long flags;
...@@ -434,8 +432,7 @@ show_periodic (struct device *dev, char *buf, size_t count, loff_t off) ...@@ -434,8 +432,7 @@ show_periodic (struct device *dev, char *buf, size_t count, loff_t off)
return 0; return 0;
seen_count = 0; seen_count = 0;
pdev = container_of (dev, struct pci_dev, dev); ohci = dev_to_ohci(dev);
ohci = container_of (pci_get_drvdata (pdev), struct ohci_hcd, hcd);
next = buf; next = buf;
size = count; size = count;
...@@ -513,16 +510,16 @@ static DEVICE_ATTR (periodic, S_IRUGO, show_periodic, NULL); ...@@ -513,16 +510,16 @@ static DEVICE_ATTR (periodic, S_IRUGO, show_periodic, NULL);
static inline void create_debug_files (struct ohci_hcd *bus) static inline void create_debug_files (struct ohci_hcd *bus)
{ {
device_create_file (&bus->hcd.pdev->dev, &dev_attr_async); device_create_file (bus->hcd.parent, &dev_attr_async);
device_create_file (&bus->hcd.pdev->dev, &dev_attr_periodic); device_create_file (bus->hcd.parent, &dev_attr_periodic);
// registers // registers
dbg ("%s: created debug files", bus->hcd.self.bus_name); dbg ("%s: created debug files", bus->hcd.self.bus_name);
} }
static inline void remove_debug_files (struct ohci_hcd *bus) static inline void remove_debug_files (struct ohci_hcd *bus)
{ {
device_remove_file (&bus->hcd.pdev->dev, &dev_attr_async); device_remove_file (bus->hcd.parent, &dev_attr_async);
device_remove_file (&bus->hcd.pdev->dev, &dev_attr_periodic); device_remove_file (bus->hcd.parent, &dev_attr_periodic);
} }
#else /* empty stubs for creating those files */ #else /* empty stubs for creating those files */
......
...@@ -29,6 +29,17 @@ ...@@ -29,6 +29,17 @@
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
struct ohci_hcd *dev_to_ohci(struct device *dev) {
struct pci_dev *pdev =
container_of (dev, struct pci_dev, dev);
struct ohci_hcd *ohci =
container_of (pci_get_drvdata (pdev), struct ohci_hcd, hcd);
return ohci;
}
/*-------------------------------------------------------------------------*/
static int __devinit static int __devinit
ohci_pci_start (struct usb_hcd *hcd) ohci_pci_start (struct usb_hcd *hcd)
{ {
......
...@@ -27,6 +27,14 @@ extern int usb_disabled(void); ...@@ -27,6 +27,14 @@ extern int usb_disabled(void);
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
struct ohci_hcd *dev_to_ohci(struct device *dev) {
struct usb_hcd *hcd = dev->driver_data;
return hcd_to_ohci(hcd);
}
/*-------------------------------------------------------------------------*/
static void sa1111_start_hc(struct sa1111_dev *dev) static void sa1111_start_hc(struct sa1111_dev *dev)
{ {
unsigned int usb_rst = 0; unsigned int usb_rst = 0;
...@@ -120,7 +128,7 @@ static void usb_hcd_sa1111_hcim_irq (int irq, void *__hcd, struct pt_regs * r) ...@@ -120,7 +128,7 @@ static void usb_hcd_sa1111_hcim_irq (int irq, void *__hcd, struct pt_regs * r)
} }
#endif #endif
usb_hcd_irq(irq, __hcd, r); usb_hcd_irq(irq, hcd, r);
} }
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
......
...@@ -400,3 +400,4 @@ struct ohci_hcd { ...@@ -400,3 +400,4 @@ struct ohci_hcd {
#define hcd_to_ohci(hcd_ptr) container_of(hcd_ptr, struct ohci_hcd, hcd) #define hcd_to_ohci(hcd_ptr) container_of(hcd_ptr, struct ohci_hcd, hcd)
struct ohci_hcd *dev_to_ohci(struct device *);
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