kernel: USB update from stlinux24_217

This commit is contained in:
Jaroslav Kysela
2015-08-03 18:18:03 +02:00
parent 07aa6b0e5a
commit c48033761a
48 changed files with 621 additions and 269 deletions

View File

@@ -41,7 +41,7 @@
* (host controller _Structural_ parameters)
* see EHCI spec, Table 2-4 for each value
*/
static void dbg_hcs_params (struct ehci_hcd *ehci, char *label)
static inline void dbg_hcs_params(struct ehci_hcd *ehci, char *label)
{
u32 params = ehci_readl(ehci, &ehci->caps->hcs_params);
@@ -85,7 +85,7 @@ static inline void dbg_hcs_params (struct ehci_hcd *ehci, char *label) {}
* (host controller _Capability_ parameters)
* see EHCI Spec, Table 2-5 for each value
* */
static void dbg_hcc_params (struct ehci_hcd *ehci, char *label)
static inline void dbg_hcc_params(struct ehci_hcd *ehci, char *label)
{
u32 params = ehci_readl(ehci, &ehci->caps->hcc_params);

View File

@@ -84,7 +84,8 @@ static const char hcd_name [] = "ehci_hcd";
#define EHCI_IAA_MSECS 10 /* arbitrary */
#define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */
#define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */
#define EHCI_SHRINK_FRAMES 5 /* async qh unlink delay */
#define EHCI_SHRINK_JIFFIES (DIV_ROUND_UP(HZ, 200) + 1)
/* 200-ms async qh unlink delay */
/* Initial IRQ latency: faster than hw default */
static int log2_irq_thresh = 0; // 0 to 6
@@ -139,10 +140,7 @@ timer_action(struct ehci_hcd *ehci, enum ehci_timer_action action)
break;
/* case TIMER_ASYNC_SHRINK: */
default:
/* add a jiffie since we synch against the
* 8 KHz uframe counter.
*/
t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1;
t = EHCI_SHRINK_JIFFIES;
break;
}
mod_timer(&ehci->watchdog, t + jiffies);
@@ -432,7 +430,7 @@ static void ehci_shutdown(struct usb_hcd *hcd)
spin_unlock_irq(&ehci->lock);
}
static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
static inline void ehci_port_power(struct ehci_hcd *ehci, int is_on)
{
unsigned port;

View File

@@ -264,7 +264,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
u32 temp;
u32 power_okay;
int i;
u8 resume_needed = 0;
unsigned long resume_needed = 0;
if (time_before (jiffies, ehci->next_statechange))
msleep(5);
@@ -328,7 +328,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
if (test_bit(i, &ehci->bus_suspended) &&
(temp & PORT_SUSPEND)) {
temp |= PORT_RESUME;
resume_needed = 1;
set_bit(i, &resume_needed);
}
ehci_writel(ehci, temp, &ehci->regs->port_status [i]);
}
@@ -343,8 +343,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
i = HCS_N_PORTS (ehci->hcs_params);
while (i--) {
temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
if (test_bit(i, &ehci->bus_suspended) &&
(temp & PORT_SUSPEND)) {
if (test_bit(i, &resume_needed)) {
temp &= ~(PORT_RWC_BITS | PORT_RESUME);
ehci_writel(ehci, temp, &ehci->regs->port_status [i]);
ehci_vdbg (ehci, "resumed port %d\n", i + 1);
@@ -779,10 +778,11 @@ static int ehci_hub_control (
* power switching; they're allowed to just limit the
* current. khubd will turn the power back on.
*/
if (HCS_PPC (ehci->hcs_params)){
if ((temp & PORT_OC) && HCS_PPC(ehci->hcs_params)) {
ehci_writel(ehci,
temp & ~(PORT_RWC_BITS | PORT_POWER),
status_reg);
temp = ehci_readl(ehci, status_reg);
}
}

View File

@@ -103,7 +103,7 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)
if (!(hw->hw_info1 & cpu_to_hc32(ehci, 1 << 14))) {
unsigned is_out, epnum;
is_out = !(qtd->hw_token & cpu_to_hc32(ehci, 1 << 8));
is_out = qh->is_out;
epnum = (hc32_to_cpup(ehci, &hw->hw_info1) >> 8) & 0x0f;
if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) {
hw->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE);
@@ -936,6 +936,7 @@ done:
hw = qh->hw;
hw->hw_info1 = cpu_to_hc32(ehci, info1);
hw->hw_info2 = cpu_to_hc32(ehci, info2);
qh->is_out = !is_input;
usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1);
qh_refresh (ehci, qh);
return qh;
@@ -1216,6 +1217,8 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
prev->hw->hw_next = qh->hw->hw_next;
prev->qh_next = qh->qh_next;
if (ehci->qh_scan_next == qh)
ehci->qh_scan_next = qh->qh_next.qh;
wmb ();
/* If the controller isn't running, we don't have to wait for it */
@@ -1241,53 +1244,49 @@ static void scan_async (struct ehci_hcd *ehci)
struct ehci_qh *qh;
enum ehci_timer_action action = TIMER_IO_WATCHDOG;
ehci->stamp = ehci_readl(ehci, &ehci->regs->frame_index);
timer_action_done (ehci, TIMER_ASYNC_SHRINK);
rescan:
stopped = !HC_IS_RUNNING(ehci_to_hcd(ehci)->state);
qh = ehci->async->qh_next.qh;
if (likely (qh != NULL)) {
do {
/* clean any finished work for this qh */
if (!list_empty(&qh->qtd_list) && (stopped ||
qh->stamp != ehci->stamp)) {
int temp;
/* unlinks could happen here; completion
* reporting drops the lock. rescan using
* the latest schedule, but don't rescan
* qhs we already finished (no looping)
* unless the controller is stopped.
*/
qh = qh_get (qh);
qh->stamp = ehci->stamp;
temp = qh_completions (ehci, qh);
if (qh->needs_rescan)
unlink_async(ehci, qh);
qh_put (qh);
if (temp != 0) {
goto rescan;
}
}
ehci->qh_scan_next = ehci->async->qh_next.qh;
while (ehci->qh_scan_next) {
qh = ehci->qh_scan_next;
ehci->qh_scan_next = qh->qh_next.qh;
rescan:
/* clean any finished work for this qh */
if (!list_empty(&qh->qtd_list)) {
int temp;
/* unlink idle entries, reducing DMA usage as well
* as HCD schedule-scanning costs. delay for any qh
* we just scanned, there's a not-unusual case that it
* doesn't stay idle for long.
* (plus, avoids some kind of re-activation race.)
/*
* Unlinks could happen here; completion reporting
* drops the lock. That's why ehci->qh_scan_next
* always holds the next qh to scan; if the next qh
* gets unlinked then ehci->qh_scan_next is adjusted
* in start_unlink_async().
*/
if (list_empty(&qh->qtd_list)
&& qh->qh_state == QH_STATE_LINKED) {
if (!ehci->reclaim && (stopped ||
((ehci->stamp - qh->stamp) & 0x1fff)
>= EHCI_SHRINK_FRAMES * 8))
start_unlink_async(ehci, qh);
else
action = TIMER_ASYNC_SHRINK;
}
qh = qh_get(qh);
temp = qh_completions(ehci, qh);
if (qh->needs_rescan)
unlink_async(ehci, qh);
qh->unlink_time = jiffies + EHCI_SHRINK_JIFFIES;
qh_put(qh);
if (temp != 0)
goto rescan;
}
qh = qh->qh_next.qh;
} while (qh);
/* unlink idle entries, reducing DMA usage as well
* as HCD schedule-scanning costs. delay for any qh
* we just scanned, there's a not-unusual case that it
* doesn't stay idle for long.
* (plus, avoids some kind of re-activation race.)
*/
if (list_empty(&qh->qtd_list)
&& qh->qh_state == QH_STATE_LINKED) {
if (!ehci->reclaim && (stopped ||
time_after_eq(jiffies, qh->unlink_time)))
start_unlink_async(ehci, qh);
else
action = TIMER_ASYNC_SHRINK;
}
}
if (action == TIMER_ASYNC_SHRINK)
timer_action (ehci, TIMER_ASYNC_SHRINK);

View File

@@ -62,7 +62,7 @@ stm_ehci_bus_resume(struct usb_hcd *hcd)
static const struct hc_driver ehci_stm_hc_driver = {
.description = hcd_name,
.product_desc = "st-ehci",
.product_desc = "STMicroelectronics EHCI Host Controller",
.hcd_priv_size = sizeof(struct ehci_hcd),
/*
@@ -199,6 +199,7 @@ static struct platform_driver ehci_hcd_stm_driver = {
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "stm-ehci",
.owner = THIS_MODULE,
},
};
@@ -216,7 +217,7 @@ int stm_ehci_hcd_unregister(struct platform_device *dev)
ret = ehci_hcd_stm_remove(dev);
mutex_unlock(&stm_ehci_usb_mutex);
if (ret)
dgb_print("[STM][USB] Error on %s 0x%x\n", __func__, dev);
dgb_print("[STM][USB] Error on %s %p\n", __func__, dev);
return ret;
}
@@ -230,7 +231,7 @@ int stm_ehci_hcd_register(struct platform_device *dev)
ret = ehci_hcd_stm_probe(dev);
mutex_unlock(&stm_ehci_usb_mutex);
if (ret)
dgb_print("[STM][USB] Error on %s 0x%x\n", __func__, dev);
dgb_print("[STM][USB] Error on %s %p\n", __func__, dev);
return ret;
}
EXPORT_SYMBOL(stm_ehci_hcd_register);

View File

@@ -74,6 +74,7 @@ struct ehci_hcd { /* one per controller */
/* async schedule support */
struct ehci_qh *async;
struct ehci_qh *reclaim;
struct ehci_qh *qh_scan_next;
unsigned scanning : 1;
/* periodic schedule support */
@@ -116,7 +117,6 @@ struct ehci_hcd { /* one per controller */
struct timer_list iaa_watchdog;
struct timer_list watchdog;
unsigned long actions;
unsigned stamp;
unsigned random_frame;
unsigned long next_statechange;
ktime_t last_periodic_enable;
@@ -336,6 +336,7 @@ struct ehci_qh {
struct ehci_qh *reclaim; /* next to reclaim */
struct ehci_hcd *ehci;
unsigned long unlink_time;
/*
* Do NOT use atomic operations for QH refcounting. On some CPUs
@@ -367,6 +368,7 @@ struct ehci_qh {
#define NO_FRAME ((unsigned short)~0) /* pick new start */
struct usb_device *dev; /* access to TT */
unsigned is_out:1; /* bulk or intr OUT */
unsigned clearing_tt:1; /* Clear-TT-Buf in progress */
};

View File

@@ -1,7 +1,7 @@
/*
* Freescale QUICC Engine USB Host Controller Driver
*
* Copyright (c) Freescale Semicondutor, Inc. 2006.
* Copyright (c) Freescale Semicondutor, Inc. 2006, 2011.
* Shlomi Gridish <gridish@freescale.com>
* Jerry Huang <Chang-Ming.Huang@freescale.com>
* Copyright (c) Logic Product Development, Inc. 2007
@@ -810,9 +810,11 @@ void fhci_queue_urb(struct fhci_hcd *fhci, struct urb *urb)
ed->dev_addr = usb_pipedevice(urb->pipe);
ed->max_pkt_size = usb_maxpacket(urb->dev, urb->pipe,
usb_pipeout(urb->pipe));
/* setup stage */
td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt++, FHCI_TA_SETUP,
USB_TD_TOGGLE_DATA0, urb->setup_packet, 8, 0, 0, true);
/* data stage */
if (data_len > 0) {
td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt++,
usb_pipeout(urb->pipe) ? FHCI_TA_OUT :
@@ -820,9 +822,18 @@ void fhci_queue_urb(struct fhci_hcd *fhci, struct urb *urb)
USB_TD_TOGGLE_DATA1, data, data_len, 0, 0,
true);
}
td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt++,
usb_pipeout(urb->pipe) ? FHCI_TA_IN : FHCI_TA_OUT,
USB_TD_TOGGLE_DATA1, data, 0, 0, 0, true);
/* status stage */
if (data_len > 0)
td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt++,
(usb_pipeout(urb->pipe) ? FHCI_TA_IN :
FHCI_TA_OUT),
USB_TD_TOGGLE_DATA1, data, 0, 0, 0, true);
else
td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt++,
FHCI_TA_IN,
USB_TD_TOGGLE_DATA1, data, 0, 0, 0, true);
urb_state = US_CTRL_SETUP;
break;
case FHCI_TF_ISO:

View File

@@ -71,20 +71,21 @@ static int stm_usb_boot(struct platform_device *pdev)
void *wrapper_base = usb_data->ahb2stbus_wrapper_glue_base;
void *protocol_base = usb_data->ahb2stbus_protocol_base;
unsigned long reg, req_reg;
unsigned long flags = pl_data->flags;
if (pl_data->flags &
(STM_PLAT_USB_FLAGS_STRAP_8BIT |
STM_PLAT_USB_FLAGS_STRAP_16BIT)) {
if (flags & (STM_PLAT_USB_FLAGS_STRAP_8BIT |
STM_PLAT_USB_FLAGS_STRAP_16BIT)) {
/* Set strap mode */
reg = readl(wrapper_base + AHB2STBUS_STRAP_OFFSET);
if (pl_data->flags & STM_PLAT_USB_FLAGS_STRAP_16BIT)
if (flags & STM_PLAT_USB_FLAGS_STRAP_16BIT)
reg |= AHB2STBUS_STRAP_16_BIT;
else
reg &= ~AHB2STBUS_STRAP_16_BIT;
writel(reg, wrapper_base + AHB2STBUS_STRAP_OFFSET);
}
if (pl_data->flags & STM_PLAT_USB_FLAGS_STRAP_PLL) {
if (flags & STM_PLAT_USB_FLAGS_STRAP_PLL) {
/* Start PLL */
reg = readl(wrapper_base + AHB2STBUS_STRAP_OFFSET);
writel(reg | AHB2STBUS_STRAP_PLL,
@@ -95,7 +96,7 @@ static int stm_usb_boot(struct platform_device *pdev)
mdelay(30);
}
if (pl_data->flags & STM_PLAT_USB_FLAGS_OPC_MSGSIZE_CHUNKSIZE) {
if (flags & STM_PLAT_USB_FLAGS_OPC_MSGSIZE_CHUNKSIZE) {
/* Set the STBus Opcode Config for load/store 32 */
writel(AHB2STBUS_STBUS_OPC_32BIT,
protocol_base + AHB2STBUS_STBUS_OPC_OFFSET);
@@ -109,7 +110,7 @@ static int stm_usb_boot(struct platform_device *pdev)
protocol_base + AHB2STBUS_CHUNKSIZE_OFFSET);
}
if (pl_data->flags &
if (flags &
(STM_PLAT_USB_FLAGS_STBUS_CONFIG_THRESHOLD128 |
STM_PLAT_USB_FLAGS_STBUS_CONFIG_THRESHOLD256)) {
@@ -134,24 +135,14 @@ static int stm_usb_boot(struct platform_device *pdev)
static int stm_usb_remove(struct platform_device *pdev)
{
struct resource *res;
struct device *dev = &pdev->dev;
struct drv_usb_data *dr_data = platform_get_drvdata(pdev);
platform_device_unregister(dr_data->ehci_device);
platform_device_unregister(dr_data->ohci_device);
stm_device_power(dr_data->device_state, stm_device_power_off);
stm_usb_clk_disable(dr_data);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "wrapper");
devm_release_mem_region(dev, res->start, resource_size(res));
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "protocol");
devm_release_mem_region(dev, res->start, resource_size(res));
if (dr_data->ehci_device)
platform_device_unregister(dr_data->ehci_device);
if (dr_data->ohci_device)
platform_device_unregister(dr_data->ohci_device);
return 0;
}
@@ -191,7 +182,7 @@ static int __init stm_usb_probe(struct platform_device *pdev)
struct drv_usb_data *dr_data;
struct device *dev = &pdev->dev;
struct resource *res;
int ret = 0, i;
int i;
static char __initdata *usb_clks_n[USB_CLKS_NR] = {
[USB_48_CLK] = "usb_48_clk",
[USB_IC_CLK] = "usb_ic_clk",
@@ -200,7 +191,7 @@ static int __init stm_usb_probe(struct platform_device *pdev)
resource_size_t len;
dgb_print("\n");
dr_data = kzalloc(sizeof(struct drv_usb_data), GFP_KERNEL);
dr_data = devm_kzalloc(dev, sizeof(*dr_data), GFP_KERNEL);
if (!dr_data)
return -ENOMEM;
@@ -215,57 +206,47 @@ static int __init stm_usb_probe(struct platform_device *pdev)
stm_usb_clk_enable(dr_data);
dr_data->device_state = devm_stm_device_init(&pdev->dev,
plat_data->device_config);
if (!dr_data->device_state) {
ret = -EBUSY;
goto err_0;
}
dr_data->device_state =
devm_stm_device_init(&pdev->dev, plat_data->device_config);
if (!dr_data->device_state)
return -EBUSY;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "wrapper");
if (!res) {
ret = -ENXIO;
goto err_0;
}
if (!res)
return -ENXIO;
len = resource_size(res);
if (devm_request_mem_region(dev, res->start, len, pdev->name) < 0) {
ret = -EBUSY;
goto err_0;
}
if (devm_request_mem_region(dev, res->start, len, pdev->name) < 0)
return -EBUSY;
dr_data->ahb2stbus_wrapper_glue_base =
devm_ioremap_nocache(dev, res->start, len);
if (!dr_data->ahb2stbus_wrapper_glue_base) {
ret = -EFAULT;
goto err_1;
}
if (!dr_data->ahb2stbus_wrapper_glue_base)
return -EFAULT;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "protocol");
if (!res) {
ret = -ENXIO;
goto err_2;
}
if (!res)
return -ENXIO;
len = resource_size(res);
if (devm_request_mem_region(dev, res->start, len, pdev->name) < 0) {
ret = -EBUSY;
goto err_2;
}
if (devm_request_mem_region(dev, res->start, len, pdev->name) < 0)
return -EBUSY;
dr_data->ahb2stbus_protocol_base =
devm_ioremap_nocache(dev, res->start, len);
if (!dr_data->ahb2stbus_protocol_base) {
ret = -EFAULT;
goto err_3;
}
if (!dr_data->ahb2stbus_protocol_base)
return -EFAULT;
stm_usb_boot(pdev);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ehci");
if (res) {
dr_data->ehci_device = stm_usb_device_create("stm-ehci",
pdev->id, pdev);
if (IS_ERR(dr_data->ehci_device)) {
ret = (int)dr_data->ehci_device;
goto err_4;
}
if (IS_ERR(dr_data->ehci_device))
return PTR_ERR(dr_data->ehci_device);
}
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ohci");
@@ -273,10 +254,8 @@ static int __init stm_usb_probe(struct platform_device *pdev)
dr_data->ohci_device =
stm_usb_device_create("stm-ohci", pdev->id, pdev);
if (IS_ERR(dr_data->ohci_device)) {
if (dr_data->ehci_device)
platform_device_del(dr_data->ehci_device);
ret = (int)dr_data->ohci_device;
goto err_4;
platform_device_del(dr_data->ehci_device);
return PTR_ERR(dr_data->ohci_device);
}
}
@@ -285,21 +264,7 @@ static int __init stm_usb_probe(struct platform_device *pdev)
pm_suspend_ignore_children(&pdev->dev, 1);
pm_runtime_enable(&pdev->dev);
return ret;
err_4:
devm_iounmap(dev, dr_data->ahb2stbus_protocol_base);
err_3:
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "protocol");
devm_release_mem_region(dev, res->start, resource_size(res));
err_2:
devm_iounmap(dev, dr_data->ahb2stbus_wrapper_glue_base);
err_1:
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "wrapper");
devm_release_mem_region(dev, res->start, resource_size(res));
err_0:
kfree(dr_data);
return ret;
return 0;
}
static void stm_usb_shutdown(struct platform_device *pdev)

View File

@@ -56,7 +56,7 @@ static int stm_ohci_bus_suspend(struct usb_hcd *hcd)
static const struct hc_driver ohci_st40_hc_driver = {
.description = hcd_name,
.product_desc = "stm-ohci",
.product_desc = "STMicroelectronics OHCI Host Controller",
.hcd_priv_size = sizeof(struct ohci_hcd),
/* generic hardware linkage */
@@ -165,6 +165,7 @@ static struct platform_driver ohci_hcd_stm_driver = {
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "stm-ohci",
.owner = THIS_MODULE,
},
};
@@ -183,7 +184,7 @@ int stm_ohci_hcd_unregister(struct platform_device *dev)
ret = ohci_hcd_stm_remove(dev);
mutex_unlock(&stm_ohci_usb_mutex);
if (ret)
dgb_print("[STM][USB] Error on %s 0x%x\n", __func__, dev);
dgb_print("[STM][USB] Error on %s %p\n", __func__, dev);
return ret;
}
EXPORT_SYMBOL(stm_ohci_hcd_unregister);
@@ -196,7 +197,7 @@ int stm_ohci_hcd_register(struct platform_device *dev)
ret = ohci_hcd_stm_probe(dev);
mutex_unlock(&stm_ohci_usb_mutex);
if (ret)
dgb_print("[STM][USB] Error on %s 0x%x\n", __func__, dev);
dgb_print("[STM][USB] Error on %s %p\n", __func__, dev);
return ret;
}

View File

@@ -34,6 +34,8 @@
#define OHCI_INTRSTATUS 0x0c
#define OHCI_INTRENABLE 0x10
#define OHCI_INTRDISABLE 0x14
#define OHCI_FMINTERVAL 0x34
#define OHCI_HCR (1 << 0) /* host controller reset */
#define OHCI_OCR (1 << 3) /* ownership change request */
#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */
#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */
@@ -204,6 +206,32 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
/* reset controller, preserving RWC (and possibly IR) */
writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL);
readl(base + OHCI_CONTROL);
/* Some NVIDIA controllers stop working if kept in RESET for too long */
if (pdev->vendor == PCI_VENDOR_ID_NVIDIA) {
u32 fminterval;
int cnt;
/* drive reset for at least 50 ms (7.1.7.5) */
msleep(50);
/* software reset of the controller, preserving HcFmInterval */
fminterval = readl(base + OHCI_FMINTERVAL);
writel(OHCI_HCR, base + OHCI_CMDSTATUS);
/* reset requires max 10 us delay */
for (cnt = 30; cnt > 0; --cnt) { /* ... allow extra time */
if ((readl(base + OHCI_CMDSTATUS) & OHCI_HCR) == 0)
break;
udelay(1);
}
writel(fminterval, base + OHCI_FMINTERVAL);
/* Now we're in the SUSPEND state with all devices reset
* and wakeups and interrupts disabled
*/
}
/*
* disable interrupts
@@ -390,12 +418,12 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
void __iomem *op_reg_base;
u32 val;
int timeout;
int len = pci_resource_len(pdev, 0);
if (!mmio_resource_enabled(pdev, 0))
return;
base = ioremap_nocache(pci_resource_start(pdev, 0),
pci_resource_len(pdev, 0));
base = ioremap_nocache(pci_resource_start(pdev, 0), len);
if (base == NULL)
return;
@@ -405,9 +433,17 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
*/
ext_cap_offset = xhci_find_next_cap_offset(base, XHCI_HCC_PARAMS_OFFSET);
do {
if ((ext_cap_offset + sizeof(val)) > len) {
/* We're reading garbage from the controller */
dev_warn(&pdev->dev,
"xHCI controller failing to respond");
return;
}
if (!ext_cap_offset)
/* We've reached the end of the extended capabilities */
goto hc_init;
val = readl(base + ext_cap_offset);
if (XHCI_EXT_CAPS_ID(val) == XHCI_EXT_CAPS_LEGACY)
break;
@@ -416,7 +452,7 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
/* If the BIOS owns the HC, signal that the OS wants it, and wait */
if (val & XHCI_HC_BIOS_OWNED) {
writel(val & XHCI_HC_OS_OWNED, base + ext_cap_offset);
writel(val | XHCI_HC_OS_OWNED, base + ext_cap_offset);
/* Wait for 5 seconds with 10 microsecond polling interval */
timeout = handshake(base + ext_cap_offset, XHCI_HC_BIOS_OWNED,
@@ -430,9 +466,13 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
}
}
/* Disable any BIOS SMIs */
writel(XHCI_LEGACY_DISABLE_SMI,
base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET);
val = readl(base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET);
/* Mask off (turn off) any enabled SMIs */
val &= XHCI_LEGACY_DISABLE_SMI;
/* Mask all SMI events bits, RW1C */
val |= XHCI_LEGACY_SMI_EVENTS;
/* Disable any BIOS SMIs and clear all SMI events*/
writel(val, base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET);
hc_init:
op_reg_base = base + XHCI_HC_LENGTH(readl(base));
@@ -470,6 +510,22 @@ hc_init:
static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
{
/* Skip Netlogic mips SoC's internal PCI USB controller.
* This device does not need/support EHCI/OHCI handoff
*/
if (pdev->vendor == 0x184e) /* vendor Netlogic */
return;
if (pdev->class != PCI_CLASS_SERIAL_USB_UHCI &&
pdev->class != PCI_CLASS_SERIAL_USB_OHCI &&
pdev->class != PCI_CLASS_SERIAL_USB_EHCI &&
pdev->class != PCI_CLASS_SERIAL_USB_XHCI)
return;
if (pci_enable_device(pdev) < 0) {
dev_warn(&pdev->dev, "Can't enable PCI device, "
"BIOS handoff failed.\n");
return;
}
if (pdev->class == PCI_CLASS_SERIAL_USB_UHCI)
quirk_usb_handoff_uhci(pdev);
else if (pdev->class == PCI_CLASS_SERIAL_USB_OHCI)
@@ -478,5 +534,6 @@ static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
quirk_usb_disable_ehci(pdev);
else if (pdev->class == PCI_CLASS_SERIAL_USB_XHCI)
quirk_usb_handoff_xhci(pdev);
pci_disable_device(pdev);
}
DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff);

View File

@@ -104,7 +104,7 @@ void qset_clear(struct whc *whc, struct whc_qset *qset)
{
qset->td_start = qset->td_end = qset->ntds = 0;
qset->qh.link = cpu_to_le32(QH_LINK_NTDS(8) | QH_LINK_T);
qset->qh.link = cpu_to_le64(QH_LINK_NTDS(8) | QH_LINK_T);
qset->qh.status = qset->qh.status & QH_STATUS_SEQ_MASK;
qset->qh.err_count = 0;
qset->qh.scratch[0] = 0;

View File

@@ -62,8 +62,9 @@
/* USB Legacy Support Control and Status Register - section 7.1.2 */
/* Add this offset, plus the value of xECP in HCCPARAMS to the base address */
#define XHCI_LEGACY_CONTROL_OFFSET (0x04)
/* bits 1:2, 5:12, and 17:19 need to be preserved; bits 21:28 should be zero */
#define XHCI_LEGACY_DISABLE_SMI ((0x3 << 1) + (0xff << 5) + (0x7 << 17))
/* bits 1:3, 5:12, and 17:19 need to be preserved; bits 21:28 should be zero */
#define XHCI_LEGACY_DISABLE_SMI ((0x7 << 1) + (0xff << 5) + (0x7 << 17))
#define XHCI_LEGACY_SMI_EVENTS (0x7 << 29)
/* command register values to disable interrupts and halt the HC */
/* start/stop HC execution - do not write unless HC is halted*/

View File

@@ -150,7 +150,7 @@ int xhci_reset(struct xhci_hcd *xhci)
xhci_to_hcd(xhci)->state = HC_STATE_HALT;
ret = handshake(xhci, &xhci->op_regs->command,
CMD_RESET, 0, 250 * 1000);
CMD_RESET, 0, 10 * 1000 * 1000);
if (ret)
return ret;
@@ -979,6 +979,7 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
u32 added_ctxs;
unsigned int last_ctx;
u32 new_add_flags, new_drop_flags, new_slot_info;
struct xhci_virt_device *virt_dev;
int ret = 0;
ret = xhci_check_args(hcd, udev, ep, 1, __func__);
@@ -1007,11 +1008,25 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
return -EINVAL;
}
in_ctx = xhci->devs[udev->slot_id]->in_ctx;
out_ctx = xhci->devs[udev->slot_id]->out_ctx;
virt_dev = xhci->devs[udev->slot_id];
in_ctx = virt_dev->in_ctx;
out_ctx = virt_dev->out_ctx;
ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
ep_index = xhci_get_endpoint_index(&ep->desc);
ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index);
/* If this endpoint is already in use, and the upper layers are trying
* to add it again without dropping it, reject the addition.
*/
if (virt_dev->eps[ep_index].ring &&
!(le32_to_cpu(ctrl_ctx->drop_flags) &
xhci_get_endpoint_flag(&ep->desc))) {
xhci_warn(xhci, "Trying to add endpoint 0x%x "
"without dropping it.\n",
(unsigned int) ep->desc.bEndpointAddress);
return -EINVAL;
}
/* If the HCD has already noted the endpoint is enabled,
* ignore this request.
*/
@@ -1026,8 +1041,7 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
* process context, not interrupt context (or so documenation
* for usb_set_interface() and usb_set_configuration() claim).
*/
if (xhci_endpoint_init(xhci, xhci->devs[udev->slot_id],
udev, ep, GFP_KERNEL) < 0) {
if (xhci_endpoint_init(xhci, virt_dev, udev, ep, GFP_NOIO) < 0) {
dev_dbg(&udev->dev, "%s - could not initialize ep %#x\n",
__func__, ep->desc.bEndpointAddress);
return -ENOMEM;

View File

@@ -110,18 +110,20 @@ void xhci_ring_free(struct xhci_hcd *xhci, struct xhci_ring *ring)
struct xhci_segment *seg;
struct xhci_segment *first_seg;
if (!ring || !ring->first_seg)
if (!ring)
return;
first_seg = ring->first_seg;
seg = first_seg->next;
xhci_dbg(xhci, "Freeing ring at %p\n", ring);
while (seg != first_seg) {
struct xhci_segment *next = seg->next;
xhci_segment_free(xhci, seg);
seg = next;
if (ring->first_seg) {
first_seg = ring->first_seg;
seg = first_seg->next;
xhci_dbg(xhci, "Freeing ring at %p\n", ring);
while (seg != first_seg) {
struct xhci_segment *next = seg->next;
xhci_segment_free(xhci, seg);
seg = next;
}
xhci_segment_free(xhci, first_seg);
ring->first_seg = NULL;
}
xhci_segment_free(xhci, first_seg);
ring->first_seg = NULL;
kfree(ring);
}
@@ -470,26 +472,42 @@ static unsigned int xhci_parse_exponent_interval(struct usb_device *udev,
}
/*
* Convert bInterval expressed in frames (in 1-255 range) to exponent of
* Convert bInterval expressed in microframes (in 1-255 range) to exponent of
* microframes, rounded down to nearest power of 2.
*/
static unsigned int xhci_parse_frame_interval(struct usb_device *udev,
struct usb_host_endpoint *ep)
static unsigned int xhci_microframes_to_exponent(struct usb_device *udev,
struct usb_host_endpoint *ep, unsigned int desc_interval,
unsigned int min_exponent, unsigned int max_exponent)
{
unsigned int interval;
interval = fls(8 * ep->desc.bInterval) - 1;
interval = clamp_val(interval, 3, 10);
if ((1 << interval) != 8 * ep->desc.bInterval)
interval = fls(desc_interval) - 1;
interval = clamp_val(interval, min_exponent, max_exponent);
if ((1 << interval) != desc_interval)
dev_warn(&udev->dev,
"ep %#x - rounding interval to %d microframes, ep desc says %d microframes\n",
ep->desc.bEndpointAddress,
1 << interval,
8 * ep->desc.bInterval);
desc_interval);
return interval;
}
static unsigned int xhci_parse_microframe_interval(struct usb_device *udev,
struct usb_host_endpoint *ep)
{
return xhci_microframes_to_exponent(udev, ep,
ep->desc.bInterval, 0, 15);
}
static unsigned int xhci_parse_frame_interval(struct usb_device *udev,
struct usb_host_endpoint *ep)
{
return xhci_microframes_to_exponent(udev, ep,
ep->desc.bInterval * 8, 3, 10);
}
/* Return the polling or NAK interval.
*
* The polling interval is expressed in "microframes". If xHCI's Interval field
@@ -508,7 +526,7 @@ static inline unsigned int xhci_get_endpoint_interval(struct usb_device *udev,
/* Max NAK rate */
if (usb_endpoint_xfer_control(&ep->desc) ||
usb_endpoint_xfer_bulk(&ep->desc)) {
interval = ep->desc.bInterval;
interval = xhci_parse_microframe_interval(udev, ep);
break;
}
/* Fall through - SS and HS isoc/int have same decoding */
@@ -916,11 +934,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
int i;
/* Free the Event Ring Segment Table and the actual Event Ring */
if (xhci->ir_set) {
xhci_writel(xhci, 0, &xhci->ir_set->erst_size);
xhci_write_64(xhci, 0, &xhci->ir_set->erst_base);
xhci_write_64(xhci, 0, &xhci->ir_set->erst_dequeue);
}
size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries);
if (xhci->erst.entries)
pci_free_consistent(pdev, size,
@@ -932,7 +945,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
xhci->event_ring = NULL;
xhci_dbg(xhci, "Freed event ring\n");
xhci_write_64(xhci, 0, &xhci->op_regs->cmd_ring);
xhci->cmd_ring_reserved_trbs = 0;
if (xhci->cmd_ring)
xhci_ring_free(xhci, xhci->cmd_ring);
xhci->cmd_ring = NULL;
@@ -951,7 +964,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
xhci->device_pool = NULL;
xhci_dbg(xhci, "Freed device context pool\n");
xhci_write_64(xhci, 0, &xhci->op_regs->dcbaa_ptr);
if (xhci->dcbaa)
pci_free_consistent(pdev, sizeof(*xhci->dcbaa),
xhci->dcbaa, xhci->dcbaa->dma);
@@ -1128,6 +1140,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
fail:
xhci_warn(xhci, "Couldn't initialize memory\n");
xhci_halt(xhci);
xhci_reset(xhci);
xhci_mem_cleanup(xhci);
return -ENOMEM;
}