diff options
Diffstat (limited to 'drivers/usb/host/u132-hcd.c')
-rw-r--r-- | drivers/usb/host/u132-hcd.c | 92 |
1 files changed, 32 insertions, 60 deletions
diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index a9d7119e3176..a7fa0d75567d 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/moduleparam.h> | 40 | #include <linux/moduleparam.h> |
41 | #include <linux/delay.h> | 41 | #include <linux/delay.h> |
42 | #include <linux/ioport.h> | 42 | #include <linux/ioport.h> |
43 | #include <linux/pci_ids.h> | ||
43 | #include <linux/sched.h> | 44 | #include <linux/sched.h> |
44 | #include <linux/slab.h> | 45 | #include <linux/slab.h> |
45 | #include <linux/smp_lock.h> | 46 | #include <linux/smp_lock.h> |
@@ -210,15 +211,16 @@ struct u132 { | |||
210 | * these cannot be inlines because we need the structure offset!! | 211 | * these cannot be inlines because we need the structure offset!! |
211 | * Does anyone have a better way????? | 212 | * Does anyone have a better way????? |
212 | */ | 213 | */ |
214 | #define ftdi_read_pcimem(pdev, member, data) usb_ftdi_elan_read_pcimem(pdev, \ | ||
215 | offsetof(struct ohci_regs, member), 0, data); | ||
216 | #define ftdi_write_pcimem(pdev, member, data) usb_ftdi_elan_write_pcimem(pdev, \ | ||
217 | offsetof(struct ohci_regs, member), 0, data); | ||
213 | #define u132_read_pcimem(u132, member, data) \ | 218 | #define u132_read_pcimem(u132, member, data) \ |
214 | usb_ftdi_elan_read_pcimem(u132->platform_dev, offsetof(struct \ | 219 | usb_ftdi_elan_read_pcimem(u132->platform_dev, offsetof(struct \ |
215 | ohci_regs, member), 0, data); | 220 | ohci_regs, member), 0, data); |
216 | #define u132_write_pcimem(u132, member, data) \ | 221 | #define u132_write_pcimem(u132, member, data) \ |
217 | usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \ | 222 | usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \ |
218 | ohci_regs, member), 0, data); | 223 | ohci_regs, member), 0, data); |
219 | #define u132_write_pcimem_byte(u132, member, data) \ | ||
220 | usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \ | ||
221 | ohci_regs, member), 0x0e, data); | ||
222 | static inline struct u132 *udev_to_u132(struct u132_udev *udev) | 224 | static inline struct u132 *udev_to_u132(struct u132_udev *udev) |
223 | { | 225 | { |
224 | u8 udev_number = udev->udev_number; | 226 | u8 udev_number = udev->udev_number; |
@@ -1574,59 +1576,12 @@ static char *hcfs2string(int state) | |||
1574 | return "?"; | 1576 | return "?"; |
1575 | } | 1577 | } |
1576 | 1578 | ||
1577 | static int u132_usb_reset(struct u132 *u132) | ||
1578 | { | ||
1579 | int retval; | ||
1580 | retval = u132_read_pcimem(u132, control, &u132->hc_control); | ||
1581 | if (retval) | ||
1582 | return retval; | ||
1583 | u132->hc_control &= OHCI_CTRL_RWC; | ||
1584 | retval = u132_write_pcimem(u132, control, u132->hc_control); | ||
1585 | if (retval) | ||
1586 | return retval; | ||
1587 | return 0; | ||
1588 | } | ||
1589 | |||
1590 | static int u132_init(struct u132 *u132) | 1579 | static int u132_init(struct u132 *u132) |
1591 | { | 1580 | { |
1592 | int retval; | 1581 | int retval; |
1593 | u32 control; | 1582 | u32 control; |
1594 | u132_disable(u132); | 1583 | u132_disable(u132); |
1595 | u132->next_statechange = | 1584 | u132->next_statechange = jiffies; |
1596 | jiffies; /* SMM owns the HC? not for long! */ { | ||
1597 | u32 control; | ||
1598 | retval = u132_read_pcimem(u132, control, &control); | ||
1599 | if (retval) | ||
1600 | return retval; | ||
1601 | if (control & OHCI_CTRL_IR) { | ||
1602 | u32 temp = 50; | ||
1603 | retval = u132_write_pcimem(u132, intrenable, | ||
1604 | OHCI_INTR_OC); | ||
1605 | if (retval) | ||
1606 | return retval; | ||
1607 | retval = u132_write_pcimem_byte(u132, cmdstatus, | ||
1608 | OHCI_OCR); | ||
1609 | if (retval) | ||
1610 | return retval; | ||
1611 | check:{ | ||
1612 | retval = u132_read_pcimem(u132, control, | ||
1613 | &control); | ||
1614 | if (retval) | ||
1615 | return retval; | ||
1616 | } | ||
1617 | if (control & OHCI_CTRL_IR) { | ||
1618 | msleep(10); | ||
1619 | if (--temp == 0) { | ||
1620 | dev_err(&u132->platform_dev->dev, "USB " | ||
1621 | "HC takeover failed!(BIOS/SMM b" | ||
1622 | "ug) control=%08X\n", control); | ||
1623 | return -EBUSY; | ||
1624 | } | ||
1625 | goto check; | ||
1626 | } | ||
1627 | u132_usb_reset(u132); | ||
1628 | } | ||
1629 | } | ||
1630 | retval = u132_write_pcimem(u132, intrdisable, OHCI_INTR_MIE); | 1585 | retval = u132_write_pcimem(u132, intrdisable, OHCI_INTR_MIE); |
1631 | if (retval) | 1586 | if (retval) |
1632 | return retval; | 1587 | return retval; |
@@ -1725,7 +1680,7 @@ static int u132_run(struct u132 *u132) | |||
1725 | retry:retval = u132_read_pcimem(u132, cmdstatus, &status); | 1680 | retry:retval = u132_read_pcimem(u132, cmdstatus, &status); |
1726 | if (retval) | 1681 | if (retval) |
1727 | return retval; | 1682 | return retval; |
1728 | retval = u132_write_pcimem_byte(u132, cmdstatus, OHCI_HCR); | 1683 | retval = u132_write_pcimem(u132, cmdstatus, OHCI_HCR); |
1729 | if (retval) | 1684 | if (retval) |
1730 | return retval; | 1685 | return retval; |
1731 | extra:{ | 1686 | extra:{ |
@@ -1782,7 +1737,7 @@ static int u132_run(struct u132 *u132) | |||
1782 | retval = u132_write_pcimem(u132, control, u132->hc_control); | 1737 | retval = u132_write_pcimem(u132, control, u132->hc_control); |
1783 | if (retval) | 1738 | if (retval) |
1784 | return retval; | 1739 | return retval; |
1785 | retval = u132_write_pcimem_byte(u132, cmdstatus, OHCI_BLF); | 1740 | retval = u132_write_pcimem(u132, cmdstatus, OHCI_BLF); |
1786 | if (retval) | 1741 | if (retval) |
1787 | return retval; | 1742 | return retval; |
1788 | retval = u132_read_pcimem(u132, cmdstatus, &cmdstatus); | 1743 | retval = u132_read_pcimem(u132, cmdstatus, &cmdstatus); |
@@ -1839,8 +1794,8 @@ static void u132_hcd_stop(struct usb_hcd *hcd) | |||
1839 | { | 1794 | { |
1840 | struct u132 *u132 = hcd_to_u132(hcd); | 1795 | struct u132 *u132 = hcd_to_u132(hcd); |
1841 | if (u132->going > 1) { | 1796 | if (u132->going > 1) { |
1842 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 1797 | dev_err(&u132->platform_dev->dev, "u132 device %p(hcd=%p) has b" |
1843 | , u132->going); | 1798 | "een removed %d\n", u132, hcd, u132->going); |
1844 | } else if (u132->going > 0) { | 1799 | } else if (u132->going > 0) { |
1845 | dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov" | 1800 | dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov" |
1846 | "ed\n", hcd); | 1801 | "ed\n", hcd); |
@@ -2545,8 +2500,9 @@ static void u132_endpoint_disable(struct usb_hcd *hcd, | |||
2545 | { | 2500 | { |
2546 | struct u132 *u132 = hcd_to_u132(hcd); | 2501 | struct u132 *u132 = hcd_to_u132(hcd); |
2547 | if (u132->going > 2) { | 2502 | if (u132->going > 2) { |
2548 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 2503 | dev_err(&u132->platform_dev->dev, "u132 device %p(hcd=%p hep=%p" |
2549 | , u132->going); | 2504 | ") has been removed %d\n", u132, hcd, hep, |
2505 | u132->going); | ||
2550 | } else { | 2506 | } else { |
2551 | struct u132_endp *endp = hep->hcpriv; | 2507 | struct u132_endp *endp = hep->hcpriv; |
2552 | if (endp) | 2508 | if (endp) |
@@ -2790,7 +2746,6 @@ static int u132_hub_status_data(struct usb_hcd *hcd, char *buf) | |||
2790 | } else if (u132->going > 0) { | 2746 | } else if (u132->going > 0) { |
2791 | dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov" | 2747 | dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov" |
2792 | "ed\n", hcd); | 2748 | "ed\n", hcd); |
2793 | dump_stack(); | ||
2794 | return -ESHUTDOWN; | 2749 | return -ESHUTDOWN; |
2795 | } else { | 2750 | } else { |
2796 | int i, changed = 0, length = 1; | 2751 | int i, changed = 0, length = 1; |
@@ -3034,12 +2989,15 @@ static int __devexit u132_remove(struct platform_device *pdev) | |||
3034 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | 2989 | struct usb_hcd *hcd = platform_get_drvdata(pdev); |
3035 | if (hcd) { | 2990 | if (hcd) { |
3036 | struct u132 *u132 = hcd_to_u132(hcd); | 2991 | struct u132 *u132 = hcd_to_u132(hcd); |
3037 | dump_stack(); | ||
3038 | if (u132->going++ > 1) { | 2992 | if (u132->going++ > 1) { |
2993 | dev_err(&u132->platform_dev->dev, "already being remove" | ||
2994 | "d\n"); | ||
3039 | return -ENODEV; | 2995 | return -ENODEV; |
3040 | } else { | 2996 | } else { |
3041 | int rings = MAX_U132_RINGS; | 2997 | int rings = MAX_U132_RINGS; |
3042 | int endps = MAX_U132_ENDPS; | 2998 | int endps = MAX_U132_ENDPS; |
2999 | dev_err(&u132->platform_dev->dev, "removing device u132" | ||
3000 | ".%d\n", u132->sequence_num); | ||
3043 | msleep(100); | 3001 | msleep(100); |
3044 | down(&u132->sw_lock); | 3002 | down(&u132->sw_lock); |
3045 | u132_monitor_cancel_work(u132); | 3003 | u132_monitor_cancel_work(u132); |
@@ -3121,10 +3079,24 @@ static void u132_initialise(struct u132 *u132, struct platform_device *pdev) | |||
3121 | static int __devinit u132_probe(struct platform_device *pdev) | 3079 | static int __devinit u132_probe(struct platform_device *pdev) |
3122 | { | 3080 | { |
3123 | struct usb_hcd *hcd; | 3081 | struct usb_hcd *hcd; |
3082 | int retval; | ||
3083 | u32 control; | ||
3084 | u32 rh_a = -1; | ||
3085 | u32 num_ports; | ||
3124 | msleep(100); | 3086 | msleep(100); |
3125 | if (u132_exiting > 0) { | 3087 | if (u132_exiting > 0) { |
3126 | return -ENODEV; | 3088 | return -ENODEV; |
3127 | } /* refuse to confuse usbcore */ | 3089 | } |
3090 | retval = ftdi_write_pcimem(pdev, intrdisable, OHCI_INTR_MIE); | ||
3091 | if (retval) | ||
3092 | return retval; | ||
3093 | retval = ftdi_read_pcimem(pdev, control, &control); | ||
3094 | if (retval) | ||
3095 | return retval; | ||
3096 | retval = ftdi_read_pcimem(pdev, roothub.a, &rh_a); | ||
3097 | if (retval) | ||
3098 | return retval; | ||
3099 | num_ports = rh_a & RH_A_NDP; /* refuse to confuse usbcore */ | ||
3128 | if (pdev->dev.dma_mask) { | 3100 | if (pdev->dev.dma_mask) { |
3129 | return -EINVAL; | 3101 | return -EINVAL; |
3130 | } | 3102 | } |