aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/host/oxu210hp-hcd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/oxu210hp-hcd.c')
-rw-r--r--drivers/usb/host/oxu210hp-hcd.c123
1 files changed, 49 insertions, 74 deletions
diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c
index 5ac489ee3da..e07248b6ab6 100644
--- a/drivers/usb/host/oxu210hp-hcd.c
+++ b/drivers/usb/host/oxu210hp-hcd.c
@@ -29,20 +29,16 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/errno.h>
-#include <linux/init.h>
#include <linux/timer.h>
#include <linux/list.h>
#include <linux/interrupt.h>
-#include <linux/reboot.h>
#include <linux/usb.h>
+#include <linux/usb/hcd.h>
#include <linux/moduleparam.h>
#include <linux/dma-mapping.h>
#include <linux/io.h>
-#include "../core/hcd.h"
-
#include <asm/irq.h>
-#include <asm/system.h>
#include <asm/unaligned.h>
#include <linux/irq.h>
@@ -63,6 +59,10 @@
#define oxu_info(oxu, fmt, args...) \
dev_info(oxu_to_hcd(oxu)->self.controller , fmt , ## args)
+#ifdef CONFIG_DYNAMIC_DEBUG
+#define DEBUG
+#endif
+
static inline struct usb_hcd *oxu_to_hcd(struct oxu_hcd *oxu)
{
return container_of((void *) oxu, struct usb_hcd, hcd_priv);
@@ -235,7 +235,7 @@ module_param(park, uint, S_IRUGO);
MODULE_PARM_DESC(park, "park setting; 1-3 back-to-back async packets");
/* For flakey hardware, ignore overcurrent indicators */
-static int ignore_oc;
+static bool ignore_oc;
module_param(ignore_oc, bool, S_IRUGO);
MODULE_PARM_DESC(ignore_oc, "ignore bogus hardware overcurrent indications");
@@ -453,9 +453,9 @@ static void ehci_hub_descriptor(struct oxu_hcd *oxu,
temp = 1 + (ports / 8);
desc->bDescLength = 7 + 2 * temp;
- /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */
- memset(&desc->bitmap[0], 0, temp);
- memset(&desc->bitmap[temp], 0xff, temp);
+ /* ports removable, and usb 1.0 legacy PortPwrCtrlMask */
+ memset(&desc->u.hs.DeviceRemovable[0], 0, temp);
+ memset(&desc->u.hs.DeviceRemovable[temp], 0xff, temp);
temp = 0x0008; /* per-port overcurrent reporting */
if (HCS_PPC(oxu->hcs_params))
@@ -546,8 +546,6 @@ static void oxu_buf_free(struct oxu_hcd *oxu, struct ehci_qtd *qtd)
qtd->buffer = NULL;
spin_unlock(&oxu->mem_lock);
-
- return;
}
static inline void ehci_qtd_init(struct ehci_qtd *qtd, dma_addr_t dma)
@@ -573,8 +571,6 @@ static inline void oxu_qtd_free(struct oxu_hcd *oxu, struct ehci_qtd *qtd)
oxu->qtd_used[index] = 0;
spin_unlock(&oxu->mem_lock);
-
- return;
}
static struct ehci_qtd *ehci_qtd_alloc(struct oxu_hcd *oxu)
@@ -617,8 +613,6 @@ static void oxu_qh_free(struct oxu_hcd *oxu, struct ehci_qh *qh)
oxu->qh_used[index] = 0;
spin_unlock(&oxu->mem_lock);
-
- return;
}
static void qh_destroy(struct kref *kref)
@@ -661,13 +655,13 @@ static struct ehci_qh *oxu_qh_alloc(struct oxu_hcd *oxu)
if (qh->dummy == NULL) {
oxu_dbg(oxu, "no dummy td\n");
oxu->qh_used[i] = 0;
-
- return NULL;
+ qh = NULL;
+ goto unlock;
}
oxu->qh_used[i] = 1;
}
-
+unlock:
spin_unlock(&oxu->mem_lock);
return qh;
@@ -695,8 +689,6 @@ static void oxu_murb_free(struct oxu_hcd *oxu, struct oxu_murb *murb)
oxu->murb_used[index] = 0;
spin_unlock(&oxu->mem_lock);
-
- return;
}
static struct oxu_murb *oxu_murb_alloc(struct oxu_hcd *oxu)
@@ -1410,8 +1402,8 @@ static struct ehci_qh *qh_make(struct oxu_hcd *oxu,
* But interval 1 scheduling is simpler, and
* includes high bandwidth.
*/
- dbg("intr period %d uframes, NYET!",
- urb->interval);
+ oxu_dbg(oxu, "intr period %d uframes, NYET!\n",
+ urb->interval);
goto done;
}
} else {
@@ -1482,7 +1474,7 @@ static struct ehci_qh *qh_make(struct oxu_hcd *oxu,
}
break;
default:
- dbg("bogus dev %p speed %d", urb->dev, urb->dev->speed);
+ oxu_dbg(oxu, "bogus dev %p speed %d\n", urb->dev, urb->dev->speed);
done:
qh_put(qh);
return NULL;
@@ -1643,8 +1635,7 @@ static int submit_async(struct oxu_hcd *oxu, struct urb *urb,
#endif
spin_lock_irqsave(&oxu->lock, flags);
- if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
- &oxu_to_hcd(oxu)->flags))) {
+ if (unlikely(!HCD_HW_ACCESSIBLE(oxu_to_hcd(oxu)))) {
rc = -ESHUTDOWN;
goto done;
}
@@ -1895,6 +1886,7 @@ static int enable_periodic(struct oxu_hcd *oxu)
status = handshake(oxu, &oxu->regs->status, STS_PSS, 0, 9 * 125);
if (status != 0) {
oxu_to_hcd(oxu)->state = HC_STATE_HALT;
+ usb_hc_died(oxu_to_hcd(oxu));
return status;
}
@@ -1920,6 +1912,7 @@ static int disable_periodic(struct oxu_hcd *oxu)
status = handshake(oxu, &oxu->regs->status, STS_PSS, STS_PSS, 9 * 125);
if (status != 0) {
oxu_to_hcd(oxu)->state = HC_STATE_HALT;
+ usb_hc_died(oxu_to_hcd(oxu));
return status;
}
@@ -2211,8 +2204,7 @@ static int intr_submit(struct oxu_hcd *oxu, struct urb *urb,
spin_lock_irqsave(&oxu->lock, flags);
- if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
- &oxu_to_hcd(oxu)->flags))) {
+ if (unlikely(!HCD_HW_ACCESSIBLE(oxu_to_hcd(oxu)))) {
status = -ESHUTDOWN;
goto done;
}
@@ -2318,7 +2310,7 @@ restart:
qh_put(temp.qh);
break;
default:
- dbg("corrupt type %d frame %d shadow %p",
+ oxu_dbg(oxu, "corrupt type %d frame %d shadow %p\n",
type, frame, q.ptr);
q.ptr = NULL;
}
@@ -2461,8 +2453,9 @@ static irqreturn_t oxu210_hcd_irq(struct usb_hcd *hcd)
goto dead;
}
+ /* Shared IRQ? */
status &= INTR_MASK;
- if (!status) { /* irq sharing? */
+ if (!status || unlikely(hcd->state == HC_STATE_HALT)) {
spin_unlock(&oxu->lock);
return IRQ_NONE;
}
@@ -2528,6 +2521,7 @@ static irqreturn_t oxu210_hcd_irq(struct usb_hcd *hcd)
dead:
ehci_reset(oxu);
writel(0, &oxu->regs->configured_flag);
+ usb_hc_died(hcd);
/* generic layer kills/unlinks all urbs, then
* uses oxu_stop to clean up the rest
*/
@@ -2717,7 +2711,6 @@ static int oxu_run(struct usb_hcd *hcd)
u32 temp, hcc_params;
hcd->uses_new_polling = 1;
- hcd->poll_rh = 0;
/* EHCI spec section 4.1 */
retval = ehci_reset(oxu);
@@ -2892,7 +2885,7 @@ static int oxu_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
/* Ok, we have more job to do! :) */
for (i = 0; i < num - 1; i++) {
- /* Get free micro URB poll till a free urb is recieved */
+ /* Get free micro URB poll till a free urb is received */
do {
murb = (struct urb *) oxu_murb_alloc(oxu);
@@ -2924,7 +2917,7 @@ static int oxu_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
/* Last urb requires special handling */
- /* Get free micro URB poll till a free urb is recieved */
+ /* Get free micro URB poll till a free urb is received */
do {
murb = (struct urb *) oxu_murb_alloc(oxu);
if (!murb)
@@ -3001,8 +2994,9 @@ static int oxu_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
/* shouldn't happen often, but ...
* FIXME kill those tds' urbs
*/
- err("can't reschedule qh %p, err %d",
- qh, status);
+ dev_err(hcd->self.controller,
+ "can't reschedule qh %p, err %d\n", qh,
+ status);
}
return status;
}
@@ -3075,7 +3069,6 @@ nogood:
ep->hcpriv = NULL;
done:
spin_unlock_irqrestore(&oxu->lock, flags);
- return;
}
static int oxu_get_frame(struct usb_hcd *hcd)
@@ -3094,7 +3087,7 @@ static int oxu_hub_status_data(struct usb_hcd *hcd, char *buf)
int ports, i, retval = 1;
unsigned long flags;
- /* if !USB_SUSPEND, root hub timers won't get shut down ... */
+ /* if !PM_RUNTIME, root hub timers won't get shut down ... */
if (!HC_IS_RUNNING(hcd->state))
return 0;
@@ -3108,7 +3101,7 @@ static int oxu_hub_status_data(struct usb_hcd *hcd, char *buf)
/* Some boards (mostly VIA?) report bogus overcurrent indications,
* causing massive log spam unless we completely ignore them. It
- * may be relevant that VIA VT8235 controlers, where PORT_POWER is
+ * may be relevant that VIA VT8235 controllers, where PORT_POWER is
* always set, seem to clear PORT_OCC and PORT_CSC when writing to
* PORT_POWER; that's surprising, but maybe within-spec.
*/
@@ -3155,10 +3148,10 @@ static inline unsigned int oxu_port_speed(struct oxu_hcd *oxu,
case 0:
return 0;
case 1:
- return 1 << USB_PORT_FEAT_LOWSPEED;
+ return USB_PORT_STAT_LOW_SPEED;
case 2:
default:
- return 1 << USB_PORT_FEAT_HIGHSPEED;
+ return USB_PORT_STAT_HIGH_SPEED;
}
}
@@ -3203,7 +3196,7 @@ static int oxu_hub_control(struct usb_hcd *hcd, u16 typeReq,
* Even if OWNER is set, so the port is owned by the
* companion controller, khubd needs to be able to clear
* the port-change status bits (especially
- * USB_PORT_FEAT_C_CONNECTION).
+ * USB_PORT_STAT_C_CONNECTION).
*/
switch (wValue) {
@@ -3265,11 +3258,11 @@ static int oxu_hub_control(struct usb_hcd *hcd, u16 typeReq,
/* wPortChange bits */
if (temp & PORT_CSC)
- status |= 1 << USB_PORT_FEAT_C_CONNECTION;
+ status |= USB_PORT_STAT_C_CONNECTION << 16;
if (temp & PORT_PEC)
- status |= 1 << USB_PORT_FEAT_C_ENABLE;
+ status |= USB_PORT_STAT_C_ENABLE << 16;
if ((temp & PORT_OCC) && !ignore_oc)
- status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT;
+ status |= USB_PORT_STAT_C_OVERCURRENT << 16;
/* whoever resumes must GetPortStatus to complete it!! */
if (temp & PORT_RESUME) {
@@ -3287,7 +3280,7 @@ static int oxu_hub_control(struct usb_hcd *hcd, u16 typeReq,
/* resume completed? */
else if (time_after_eq(jiffies,
oxu->reset_done[wIndex])) {
- status |= 1 << USB_PORT_FEAT_C_SUSPEND;
+ status |= USB_PORT_STAT_C_SUSPEND << 16;
oxu->reset_done[wIndex] = 0;
/* stop resume signaling */
@@ -3310,7 +3303,7 @@ static int oxu_hub_control(struct usb_hcd *hcd, u16 typeReq,
if ((temp & PORT_RESET)
&& time_after_eq(jiffies,
oxu->reset_done[wIndex])) {
- status |= 1 << USB_PORT_FEAT_C_RESET;
+ status |= USB_PORT_STAT_C_RESET << 16;
oxu->reset_done[wIndex] = 0;
/* force reset to complete */
@@ -3349,20 +3342,20 @@ static int oxu_hub_control(struct usb_hcd *hcd, u16 typeReq,
*/
if (temp & PORT_CONNECT) {
- status |= 1 << USB_PORT_FEAT_CONNECTION;
+ status |= USB_PORT_STAT_CONNECTION;
/* status may be from integrated TT */
status |= oxu_port_speed(oxu, temp);
}
if (temp & PORT_PE)
- status |= 1 << USB_PORT_FEAT_ENABLE;
+ status |= USB_PORT_STAT_ENABLE;
if (temp & (PORT_SUSPEND|PORT_RESUME))
- status |= 1 << USB_PORT_FEAT_SUSPEND;
+ status |= USB_PORT_STAT_SUSPEND;
if (temp & PORT_OC)
- status |= 1 << USB_PORT_FEAT_OVER_CURRENT;
+ status |= USB_PORT_STAT_OVERCURRENT;
if (temp & PORT_RESET)
- status |= 1 << USB_PORT_FEAT_RESET;
+ status |= USB_PORT_STAT_RESET;
if (temp & PORT_POWER)
- status |= 1 << USB_PORT_FEAT_POWER;
+ status |= USB_PORT_STAT_POWER;
#ifndef OXU_VERBOSE_DEBUG
if (status & ~0xffff) /* only if wPortChange is interesting */
@@ -3701,7 +3694,7 @@ static void oxu_configuration(struct platform_device *pdev, void *base)
static int oxu_verify_id(struct platform_device *pdev, void *base)
{
u32 id;
- char *bo[] = {
+ static const char * const bo[] = {
"reserved",
"128-pin LQFP",
"84-pin TFBGA",
@@ -3757,6 +3750,7 @@ static struct usb_hcd *oxu_create(struct platform_device *pdev,
if (ret < 0)
return ERR_PTR(ret);
+ device_wakeup_enable(hcd->self.controller);
return hcd;
}
@@ -3838,7 +3832,7 @@ static int oxu_drv_probe(struct platform_device *pdev)
return -ENODEV;
}
memstart = res->start;
- memlen = res->end - res->start + 1;
+ memlen = resource_size(res);
dev_dbg(&pdev->dev, "MEM resource %lx-%lx\n", memstart, memlen);
if (!request_mem_region(memstart, memlen,
oxu_hc_driver.description)) {
@@ -3846,7 +3840,7 @@ static int oxu_drv_probe(struct platform_device *pdev)
return -EBUSY;
}
- ret = set_irq_type(irq, IRQF_TRIGGER_FALLING);
+ ret = irq_set_irq_type(irq, IRQF_TRIGGER_FALLING);
if (ret) {
dev_err(&pdev->dev, "error setting irq type\n");
ret = -EFAULT;
@@ -3884,7 +3878,6 @@ static int oxu_drv_probe(struct platform_device *pdev)
error_init:
kfree(info);
- platform_set_drvdata(pdev, NULL);
error_alloc:
iounmap(base);
@@ -3917,7 +3910,6 @@ static int oxu_drv_remove(struct platform_device *pdev)
release_mem_region(memstart, memlen);
kfree(info);
- platform_set_drvdata(pdev, NULL);
return 0;
}
@@ -3961,24 +3953,7 @@ static struct platform_driver oxu_driver = {
}
};
-static int __init oxu_module_init(void)
-{
- int retval = 0;
-
- retval = platform_driver_register(&oxu_driver);
- if (retval < 0)
- return retval;
-
- return retval;
-}
-
-static void __exit oxu_module_cleanup(void)
-{
- platform_driver_unregister(&oxu_driver);
-}
-
-module_init(oxu_module_init);
-module_exit(oxu_module_cleanup);
+module_platform_driver(oxu_driver);
MODULE_DESCRIPTION("Oxford OXU210HP HCD driver - ver. " DRIVER_VERSION);
MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");