diff options
author | Gabor Juhos <juhosg@openwrt.org> | 2011-06-20 11:22:36 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-06-27 16:46:44 -0400 |
commit | c27d5368ef1f7ea40bcd1fb2626f4c99d77e0080 (patch) | |
tree | 5389426a08143ec7357f38e97ec255be672fbaa1 | |
parent | 309427b6351b763917caac3e4b2ab5651df99823 (diff) |
USB: ehci-ath79: fix a NULL pointer dereference
Loading the ehci-hcd module on the ath79 platform causes
a NULL pointer dereference:
CPU 0 Unable to handle kernel paging request at virtual address 00000000, epc == c0252928, ra == c00de968
Oops[#1]:
Cpu 0
$ 0 : 00000000 00000070 00000001 00000000
$ 4 : 802cf870 0000117e ffffffff 8019c7bc
$ 8 : 0000000a 00000002 00000001 fffffffb
$12 : 8026ef20 0000000f ffffff80 802dad3c
$16 : 8077a2d4 8077a200 c00f3484 8019ed84
$20 : c00f0000 00000003 000000a0 80262c2c
$24 : 00000002 80079da0
$28 : 80788000 80789c80 80262b14 c00de968
Hi : 00000000
Lo : b61f0000
epc : c0252928 __mod_vermagic5+0xc260/0xc7e8 [ehci_hcd]
Not tainted
ra : c00de968 usb_add_hcd+0x2a4/0x858 [usbcore]
Status: 1000c003 KERNEL EXL IE
Cause : 00800008
BadVA : 00000000
PrId : 00019374 (MIPS 24Kc)
Modules linked in: ehci_hcd(+) pppoe pppox ipt_REJECT xt_TCPMSS ipt_LOG
xt_comment xt_multiport xt_mac xt_limit iptable_mangle iptable_filte
r ip_tables xt_tcpudp x_tables ppp_async ppp_generic slhc ath mac80211
usbcore nls_base input_polldev crc_ccitt cfg80211 compat input_core a
rc4 aes_generic crypto_algapi
Process insmod (pid: 379, threadinfo=80788000, task=80ca2180,
tls=77fe52d0)
Stack : c0253184 80c57d80 80789cac 8077a200 00000001 8019edc0 807fa800 8077a200
8077a290 c00f3484 8019ed84 c00f0000 00000003 000000a0 80262c2c c00de968
802d0000 800878cc c0253228 c02528e4 c0253184 80c57d80 80bf6800 80ca2180
8007b75c 00000000 8077a200 802cf830 802d0000 00000003 fffffff4 00000015
00000348 00000124 800b189c c024bb4c c0255000 801a27e8 c0253228 c02528e4
...
Call Trace:
[<c0252928>] __mod_vermagic5+0xc260/0xc7e8 [ehci_hcd]
It is caused by:
commit c430131a02d677aa708f56342c1565edfdacb3c0
Author: Jan Andersson <jan@gaisler.com>
Date: Tue May 3 20:11:57 2011 +0200
USB: EHCI: Support controllers with big endian capability regs
The two first HC capability registers (CAPLENGTH and HCIVERSION)
are defined as one 8-bit and one 16-bit register. Most HC
implementations have selected to treat these registers as part
of a 32-bit register, giving the same layout for both big and
small endian systems.
This patch adds a new quirk, big_endian_capbase, to support
controllers with big endian register interfaces that treat
HCIVERSION and CAPLENGTH as individual registers.
Signed-off-by: Jan Andersson <jan@gaisler.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
The reading of the HC capability register has been moved by that
commit to a place where the ehci->caps field is not initialized
yet. This patch moves the reading of the register back to the
original place.
Acked-by: Jan Andersson <jan@gaisler.com>
Cc: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/usb/host/ehci-ath79.c | 10 |
1 files changed, 6 insertions, 4 deletions
diff --git a/drivers/usb/host/ehci-ath79.c b/drivers/usb/host/ehci-ath79.c index 98cc8a13169c..aa248c2f2c60 100644 --- a/drivers/usb/host/ehci-ath79.c +++ b/drivers/usb/host/ehci-ath79.c | |||
@@ -44,7 +44,6 @@ static int ehci_ath79_init(struct usb_hcd *hcd) | |||
44 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | 44 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
45 | struct platform_device *pdev = to_platform_device(hcd->self.controller); | 45 | struct platform_device *pdev = to_platform_device(hcd->self.controller); |
46 | const struct platform_device_id *id; | 46 | const struct platform_device_id *id; |
47 | int hclength; | ||
48 | int ret; | 47 | int ret; |
49 | 48 | ||
50 | id = platform_get_device_id(pdev); | 49 | id = platform_get_device_id(pdev); |
@@ -53,20 +52,23 @@ static int ehci_ath79_init(struct usb_hcd *hcd) | |||
53 | return -EINVAL; | 52 | return -EINVAL; |
54 | } | 53 | } |
55 | 54 | ||
56 | hclength = HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); | ||
57 | switch (id->driver_data) { | 55 | switch (id->driver_data) { |
58 | case EHCI_ATH79_IP_V1: | 56 | case EHCI_ATH79_IP_V1: |
59 | ehci->has_synopsys_hc_bug = 1; | 57 | ehci->has_synopsys_hc_bug = 1; |
60 | 58 | ||
61 | ehci->caps = hcd->regs; | 59 | ehci->caps = hcd->regs; |
62 | ehci->regs = hcd->regs + hclength; | 60 | ehci->regs = hcd->regs + |
61 | HC_LENGTH(ehci, | ||
62 | ehci_readl(ehci, &ehci->caps->hc_capbase)); | ||
63 | break; | 63 | break; |
64 | 64 | ||
65 | case EHCI_ATH79_IP_V2: | 65 | case EHCI_ATH79_IP_V2: |
66 | hcd->has_tt = 1; | 66 | hcd->has_tt = 1; |
67 | 67 | ||
68 | ehci->caps = hcd->regs + 0x100; | 68 | ehci->caps = hcd->regs + 0x100; |
69 | ehci->regs = hcd->regs + 0x100 + hclength; | 69 | ehci->regs = hcd->regs + 0x100 + |
70 | HC_LENGTH(ehci, | ||
71 | ehci_readl(ehci, &ehci->caps->hc_capbase)); | ||
70 | break; | 72 | break; |
71 | 73 | ||
72 | default: | 74 | default: |