diff options
| author | Jeff Garzik <jgarzik@pobox.com> | 2006-02-09 04:29:00 -0500 |
|---|---|---|
| committer | Jeff Garzik <jgarzik@pobox.com> | 2006-02-09 04:29:00 -0500 |
| commit | 9caafa6c8686e319cf4d5f3757b3972c6c522b7c (patch) | |
| tree | b38979b835b5d22e681b175d0b98a3c7560d9c59 /drivers/usb/host | |
| parent | 51e9f2ff83df6b1c81c5c44f4486c68ed87aa20e (diff) | |
| parent | cac0e8e8bb2e7a086643bdd00c41d900a79bb4fa (diff) | |
Merge branch 'upstream-fixes'
Diffstat (limited to 'drivers/usb/host')
| -rw-r--r-- | drivers/usb/host/ehci-pci.c | 64 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-sched.c | 4 | ||||
| -rw-r--r-- | drivers/usb/host/isp116x-hcd.c | 21 | ||||
| -rw-r--r-- | drivers/usb/host/ohci-au1xxx.c | 2 | ||||
| -rw-r--r-- | drivers/usb/host/pci-quirks.c | 106 | ||||
| -rw-r--r-- | drivers/usb/host/uhci-q.c | 4 |
6 files changed, 87 insertions, 114 deletions
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 08ca0f849dab..3a6687df5594 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c | |||
| @@ -24,46 +24,11 @@ | |||
| 24 | 24 | ||
| 25 | /*-------------------------------------------------------------------------*/ | 25 | /*-------------------------------------------------------------------------*/ |
| 26 | 26 | ||
| 27 | /* EHCI 0.96 (and later) section 5.1 says how to kick BIOS/SMM/... | ||
| 28 | * off the controller (maybe it can boot from highspeed USB disks). | ||
| 29 | */ | ||
| 30 | static int bios_handoff(struct ehci_hcd *ehci, int where, u32 cap) | ||
| 31 | { | ||
| 32 | struct pci_dev *pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller); | ||
| 33 | |||
| 34 | /* always say Linux will own the hardware */ | ||
| 35 | pci_write_config_byte(pdev, where + 3, 1); | ||
| 36 | |||
| 37 | /* maybe wait a while for BIOS to respond */ | ||
| 38 | if (cap & (1 << 16)) { | ||
| 39 | int msec = 5000; | ||
| 40 | |||
| 41 | do { | ||
| 42 | msleep(10); | ||
| 43 | msec -= 10; | ||
| 44 | pci_read_config_dword(pdev, where, &cap); | ||
| 45 | } while ((cap & (1 << 16)) && msec); | ||
| 46 | if (cap & (1 << 16)) { | ||
| 47 | ehci_err(ehci, "BIOS handoff failed (%d, %08x)\n", | ||
| 48 | where, cap); | ||
| 49 | // some BIOS versions seem buggy... | ||
| 50 | // return 1; | ||
| 51 | ehci_warn(ehci, "continuing after BIOS bug...\n"); | ||
| 52 | /* disable all SMIs, and clear "BIOS owns" flag */ | ||
| 53 | pci_write_config_dword(pdev, where + 4, 0); | ||
| 54 | pci_write_config_byte(pdev, where + 2, 0); | ||
| 55 | } else | ||
| 56 | ehci_dbg(ehci, "BIOS handoff succeeded\n"); | ||
| 57 | } | ||
| 58 | return 0; | ||
| 59 | } | ||
| 60 | |||
| 61 | /* called after powerup, by probe or system-pm "wakeup" */ | 27 | /* called after powerup, by probe or system-pm "wakeup" */ |
| 62 | static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev) | 28 | static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev) |
| 63 | { | 29 | { |
| 64 | u32 temp; | 30 | u32 temp; |
| 65 | int retval; | 31 | int retval; |
| 66 | unsigned count = 256/4; | ||
| 67 | 32 | ||
| 68 | /* optional debug port, normally in the first BAR */ | 33 | /* optional debug port, normally in the first BAR */ |
| 69 | temp = pci_find_capability(pdev, 0x0a); | 34 | temp = pci_find_capability(pdev, 0x0a); |
| @@ -84,32 +49,9 @@ static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev) | |||
| 84 | } | 49 | } |
| 85 | } | 50 | } |
| 86 | 51 | ||
| 87 | temp = HCC_EXT_CAPS(readl(&ehci->caps->hcc_params)); | 52 | /* we expect static quirk code to handle the "extended capabilities" |
| 88 | 53 | * (currently just BIOS handoff) allowed starting with EHCI 0.96 | |
| 89 | /* EHCI 0.96 and later may have "extended capabilities" */ | 54 | */ |
| 90 | while (temp && count--) { | ||
| 91 | u32 cap; | ||
| 92 | |||
| 93 | pci_read_config_dword(pdev, temp, &cap); | ||
| 94 | ehci_dbg(ehci, "capability %04x at %02x\n", cap, temp); | ||
| 95 | switch (cap & 0xff) { | ||
| 96 | case 1: /* BIOS/SMM/... handoff */ | ||
| 97 | if (bios_handoff(ehci, temp, cap) != 0) | ||
| 98 | return -EOPNOTSUPP; | ||
| 99 | break; | ||
| 100 | case 0: /* illegal reserved capability */ | ||
| 101 | ehci_dbg(ehci, "illegal capability!\n"); | ||
| 102 | cap = 0; | ||
| 103 | /* FALLTHROUGH */ | ||
| 104 | default: /* unknown */ | ||
| 105 | break; | ||
| 106 | } | ||
| 107 | temp = (cap >> 8) & 0xff; | ||
| 108 | } | ||
| 109 | if (!count) { | ||
| 110 | ehci_err(ehci, "bogus capabilities ... PCI problems!\n"); | ||
| 111 | return -EIO; | ||
| 112 | } | ||
| 113 | 55 | ||
| 114 | /* PCI Memory-Write-Invalidate cycle support is optional (uncommon) */ | 56 | /* PCI Memory-Write-Invalidate cycle support is optional (uncommon) */ |
| 115 | retval = pci_set_mwi(pdev); | 57 | retval = pci_set_mwi(pdev); |
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 57e77374d228..ebcca9700671 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
| @@ -1063,6 +1063,7 @@ sitd_slot_ok ( | |||
| 1063 | 1063 | ||
| 1064 | /* for IN, check CSPLIT */ | 1064 | /* for IN, check CSPLIT */ |
| 1065 | if (stream->c_usecs) { | 1065 | if (stream->c_usecs) { |
| 1066 | uf = uframe & 7; | ||
| 1066 | max_used = 100 - stream->c_usecs; | 1067 | max_used = 100 - stream->c_usecs; |
| 1067 | do { | 1068 | do { |
| 1068 | tmp = 1 << uf; | 1069 | tmp = 1 << uf; |
| @@ -1843,8 +1844,7 @@ done: | |||
| 1843 | #else | 1844 | #else |
| 1844 | 1845 | ||
| 1845 | static inline int | 1846 | static inline int |
| 1846 | sitd_submit (struct ehci_hcd *ehci, struct urb *urb, | 1847 | sitd_submit (struct ehci_hcd *ehci, struct urb *urb, gfp_t mem_flags) |
| 1847 | unsigned mem_flags) | ||
| 1848 | { | 1848 | { |
| 1849 | ehci_dbg (ehci, "split iso support is disabled\n"); | 1849 | ehci_dbg (ehci, "split iso support is disabled\n"); |
| 1850 | return -ENOSYS; | 1850 | return -ENOSYS; |
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 584b8dc65119..972ce04889f8 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c | |||
| @@ -1420,20 +1420,22 @@ static int isp116x_bus_suspend(struct usb_hcd *hcd) | |||
| 1420 | int ret = 0; | 1420 | int ret = 0; |
| 1421 | 1421 | ||
| 1422 | spin_lock_irqsave(&isp116x->lock, flags); | 1422 | spin_lock_irqsave(&isp116x->lock, flags); |
| 1423 | |||
| 1424 | val = isp116x_read_reg32(isp116x, HCCONTROL); | 1423 | val = isp116x_read_reg32(isp116x, HCCONTROL); |
| 1424 | |||
| 1425 | switch (val & HCCONTROL_HCFS) { | 1425 | switch (val & HCCONTROL_HCFS) { |
| 1426 | case HCCONTROL_USB_OPER: | 1426 | case HCCONTROL_USB_OPER: |
| 1427 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
| 1427 | val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE); | 1428 | val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE); |
| 1428 | val |= HCCONTROL_USB_SUSPEND; | 1429 | val |= HCCONTROL_USB_SUSPEND; |
| 1429 | if (device_may_wakeup(&hcd->self.root_hub->dev)) | 1430 | if (device_may_wakeup(&hcd->self.root_hub->dev)) |
| 1430 | val |= HCCONTROL_RWE; | 1431 | val |= HCCONTROL_RWE; |
| 1431 | /* Wait for usb transfers to finish */ | 1432 | /* Wait for usb transfers to finish */ |
| 1432 | mdelay(2); | 1433 | msleep(2); |
| 1434 | spin_lock_irqsave(&isp116x->lock, flags); | ||
| 1433 | isp116x_write_reg32(isp116x, HCCONTROL, val); | 1435 | isp116x_write_reg32(isp116x, HCCONTROL, val); |
| 1436 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
| 1434 | /* Wait for devices to suspend */ | 1437 | /* Wait for devices to suspend */ |
| 1435 | mdelay(5); | 1438 | msleep(5); |
| 1436 | case HCCONTROL_USB_SUSPEND: | ||
| 1437 | break; | 1439 | break; |
| 1438 | case HCCONTROL_USB_RESUME: | 1440 | case HCCONTROL_USB_RESUME: |
| 1439 | isp116x_write_reg32(isp116x, HCCONTROL, | 1441 | isp116x_write_reg32(isp116x, HCCONTROL, |
| @@ -1441,12 +1443,11 @@ static int isp116x_bus_suspend(struct usb_hcd *hcd) | |||
| 1441 | HCCONTROL_USB_RESET); | 1443 | HCCONTROL_USB_RESET); |
| 1442 | case HCCONTROL_USB_RESET: | 1444 | case HCCONTROL_USB_RESET: |
| 1443 | ret = -EBUSY; | 1445 | ret = -EBUSY; |
| 1446 | default: /* HCCONTROL_USB_SUSPEND */ | ||
| 1447 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
| 1444 | break; | 1448 | break; |
| 1445 | default: | ||
| 1446 | ret = -EINVAL; | ||
| 1447 | } | 1449 | } |
| 1448 | 1450 | ||
| 1449 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
| 1450 | return ret; | 1451 | return ret; |
| 1451 | } | 1452 | } |
| 1452 | 1453 | ||
| @@ -1715,9 +1716,9 @@ static struct platform_driver isp116x_driver = { | |||
| 1715 | .remove = isp116x_remove, | 1716 | .remove = isp116x_remove, |
| 1716 | .suspend = isp116x_suspend, | 1717 | .suspend = isp116x_suspend, |
| 1717 | .resume = isp116x_resume, | 1718 | .resume = isp116x_resume, |
| 1718 | .driver = { | 1719 | .driver = { |
| 1719 | .name = (char *)hcd_name, | 1720 | .name = (char *)hcd_name, |
| 1720 | }, | 1721 | }, |
| 1721 | }; | 1722 | }; |
| 1722 | 1723 | ||
| 1723 | /*-----------------------------------------------------------------*/ | 1724 | /*-----------------------------------------------------------------*/ |
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c index 77cd6ac07e3c..db280ca7b7a0 100644 --- a/drivers/usb/host/ohci-au1xxx.c +++ b/drivers/usb/host/ohci-au1xxx.c | |||
| @@ -67,7 +67,7 @@ static void au1xxx_stop_hc(struct platform_device *dev) | |||
| 67 | ": stopping Au1xxx OHCI USB Controller\n"); | 67 | ": stopping Au1xxx OHCI USB Controller\n"); |
| 68 | 68 | ||
| 69 | /* Disable clock */ | 69 | /* Disable clock */ |
| 70 | au_writel(readl((void *)USB_HOST_CONFIG) & ~USBH_ENABLE_CE, USB_HOST_CONFIG); | 70 | au_writel(au_readl(USB_HOST_CONFIG) & ~USBH_ENABLE_CE, USB_HOST_CONFIG); |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | 73 | ||
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 3ef2c0cdf1db..e9e5bc178cef 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c | |||
| @@ -190,7 +190,7 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev) | |||
| 190 | msleep(10); | 190 | msleep(10); |
| 191 | } | 191 | } |
| 192 | if (wait_time <= 0) | 192 | if (wait_time <= 0) |
| 193 | printk(KERN_WARNING "%s %s: early BIOS handoff " | 193 | printk(KERN_WARNING "%s %s: BIOS handoff " |
| 194 | "failed (BIOS bug ?)\n", | 194 | "failed (BIOS bug ?)\n", |
| 195 | pdev->dev.bus_id, "OHCI"); | 195 | pdev->dev.bus_id, "OHCI"); |
| 196 | 196 | ||
| @@ -212,8 +212,9 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) | |||
| 212 | { | 212 | { |
| 213 | int wait_time, delta; | 213 | int wait_time, delta; |
| 214 | void __iomem *base, *op_reg_base; | 214 | void __iomem *base, *op_reg_base; |
| 215 | u32 hcc_params, val, temp; | 215 | u32 hcc_params, val; |
| 216 | u8 cap_length; | 216 | u8 offset, cap_length; |
| 217 | int count = 256/4; | ||
| 217 | 218 | ||
| 218 | if (!mmio_resource_enabled(pdev, 0)) | 219 | if (!mmio_resource_enabled(pdev, 0)) |
| 219 | return; | 220 | return; |
| @@ -224,51 +225,80 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) | |||
| 224 | 225 | ||
| 225 | cap_length = readb(base); | 226 | cap_length = readb(base); |
| 226 | op_reg_base = base + cap_length; | 227 | op_reg_base = base + cap_length; |
| 228 | |||
| 229 | /* EHCI 0.96 and later may have "extended capabilities" | ||
| 230 | * spec section 5.1 explains the bios handoff, e.g. for | ||
| 231 | * booting from USB disk or using a usb keyboard | ||
| 232 | */ | ||
| 227 | hcc_params = readl(base + EHCI_HCC_PARAMS); | 233 | hcc_params = readl(base + EHCI_HCC_PARAMS); |
| 228 | hcc_params = (hcc_params >> 8) & 0xff; | 234 | offset = (hcc_params >> 8) & 0xff; |
| 229 | if (hcc_params) { | 235 | while (offset && count--) { |
| 230 | pci_read_config_dword(pdev, | 236 | u32 cap; |
| 231 | hcc_params + EHCI_USBLEGSUP, | 237 | int msec; |
| 232 | &val); | 238 | |
| 233 | if (((val & 0xff) == 1) && (val & EHCI_USBLEGSUP_BIOS)) { | 239 | pci_read_config_dword(pdev, offset, &cap); |
| 234 | /* | 240 | switch (cap & 0xff) { |
| 235 | * Ok, BIOS is in smm mode, try to hand off... | 241 | case 1: /* BIOS/SMM/... handoff support */ |
| 242 | if ((cap & EHCI_USBLEGSUP_BIOS)) { | ||
| 243 | pr_debug("%s %s: BIOS handoff\n", | ||
| 244 | pdev->dev.bus_id, "EHCI"); | ||
| 245 | |||
| 246 | /* BIOS workaround (?): be sure the | ||
| 247 | * pre-Linux code receives the SMI | ||
| 248 | */ | ||
| 249 | pci_read_config_dword(pdev, | ||
| 250 | offset + EHCI_USBLEGCTLSTS, | ||
| 251 | &val); | ||
| 252 | pci_write_config_dword(pdev, | ||
| 253 | offset + EHCI_USBLEGCTLSTS, | ||
| 254 | val | EHCI_USBLEGCTLSTS_SOOE); | ||
| 255 | } | ||
| 256 | |||
| 257 | /* always say Linux will own the hardware | ||
| 258 | * by setting EHCI_USBLEGSUP_OS. | ||
| 236 | */ | 259 | */ |
| 237 | pci_read_config_dword(pdev, | 260 | pci_write_config_byte(pdev, offset + 3, 1); |
| 238 | hcc_params + EHCI_USBLEGCTLSTS, | ||
| 239 | &temp); | ||
| 240 | pci_write_config_dword(pdev, | ||
| 241 | hcc_params + EHCI_USBLEGCTLSTS, | ||
| 242 | temp | EHCI_USBLEGCTLSTS_SOOE); | ||
| 243 | val |= EHCI_USBLEGSUP_OS; | ||
| 244 | pci_write_config_dword(pdev, | ||
| 245 | hcc_params + EHCI_USBLEGSUP, | ||
| 246 | val); | ||
| 247 | 261 | ||
| 248 | wait_time = 500; | 262 | /* if boot firmware now owns EHCI, spin till |
| 249 | do { | 263 | * it hands it over. |
| 264 | */ | ||
| 265 | msec = 5000; | ||
| 266 | while ((cap & EHCI_USBLEGSUP_BIOS) && (msec > 0)) { | ||
| 250 | msleep(10); | 267 | msleep(10); |
| 251 | wait_time -= 10; | 268 | msec -= 10; |
| 252 | pci_read_config_dword(pdev, | 269 | pci_read_config_dword(pdev, offset, &cap); |
| 253 | hcc_params + EHCI_USBLEGSUP, | 270 | } |
| 254 | &val); | 271 | |
| 255 | } while (wait_time && (val & EHCI_USBLEGSUP_BIOS)); | 272 | if (cap & EHCI_USBLEGSUP_BIOS) { |
| 256 | if (!wait_time) { | 273 | /* well, possibly buggy BIOS... try to shut |
| 257 | /* | 274 | * it down, and hope nothing goes too wrong |
| 258 | * well, possibly buggy BIOS... | ||
| 259 | */ | 275 | */ |
| 260 | printk(KERN_WARNING "%s %s: early BIOS handoff " | 276 | printk(KERN_WARNING "%s %s: BIOS handoff " |
| 261 | "failed (BIOS bug ?)\n", | 277 | "failed (BIOS bug ?)\n", |
| 262 | pdev->dev.bus_id, "EHCI"); | 278 | pdev->dev.bus_id, "EHCI"); |
| 263 | pci_write_config_dword(pdev, | 279 | pci_write_config_byte(pdev, offset + 2, 0); |
| 264 | hcc_params + EHCI_USBLEGSUP, | ||
| 265 | EHCI_USBLEGSUP_OS); | ||
| 266 | pci_write_config_dword(pdev, | ||
| 267 | hcc_params + EHCI_USBLEGCTLSTS, | ||
| 268 | 0); | ||
| 269 | } | 280 | } |
| 281 | |||
| 282 | /* just in case, always disable EHCI SMIs */ | ||
| 283 | pci_write_config_dword(pdev, | ||
| 284 | offset + EHCI_USBLEGCTLSTS, | ||
| 285 | 0); | ||
| 286 | break; | ||
| 287 | case 0: /* illegal reserved capability */ | ||
| 288 | cap = 0; | ||
| 289 | /* FALLTHROUGH */ | ||
| 290 | default: | ||
| 291 | printk(KERN_WARNING "%s %s: unrecognized " | ||
| 292 | "capability %02x\n", | ||
| 293 | pdev->dev.bus_id, "EHCI", | ||
| 294 | cap & 0xff); | ||
| 295 | break; | ||
| 270 | } | 296 | } |
| 297 | offset = (cap >> 8) & 0xff; | ||
| 271 | } | 298 | } |
| 299 | if (!count) | ||
| 300 | printk(KERN_DEBUG "%s %s: capability loop?\n", | ||
| 301 | pdev->dev.bus_id, "EHCI"); | ||
| 272 | 302 | ||
| 273 | /* | 303 | /* |
| 274 | * halt EHCI & disable its interrupts in any case | 304 | * halt EHCI & disable its interrupts in any case |
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index b6076004a437..782398045f9f 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c | |||
| @@ -672,9 +672,9 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur | |||
| 672 | /* Low-speed transfers get a different queue, and won't hog the bus. | 672 | /* Low-speed transfers get a different queue, and won't hog the bus. |
| 673 | * Also, some devices enumerate better without FSBR; the easiest way | 673 | * Also, some devices enumerate better without FSBR; the easiest way |
| 674 | * to do that is to put URBs on the low-speed queue while the device | 674 | * to do that is to put URBs on the low-speed queue while the device |
| 675 | * is in the DEFAULT state. */ | 675 | * isn't in the CONFIGURED state. */ |
| 676 | if (urb->dev->speed == USB_SPEED_LOW || | 676 | if (urb->dev->speed == USB_SPEED_LOW || |
| 677 | urb->dev->state == USB_STATE_DEFAULT) | 677 | urb->dev->state != USB_STATE_CONFIGURED) |
| 678 | skelqh = uhci->skel_ls_control_qh; | 678 | skelqh = uhci->skel_ls_control_qh; |
| 679 | else { | 679 | else { |
| 680 | skelqh = uhci->skel_fs_control_qh; | 680 | skelqh = uhci->skel_fs_control_qh; |
