summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaymond Chen <Raymond.Chen@Sun.COM>2010-06-30 17:40:22 +0800
committerRaymond Chen <Raymond.Chen@Sun.COM>2010-06-30 17:40:22 +0800
commitdfbb3a42fe4d6d7c50b9f750f514f8c7b66e4ed9 (patch)
tree18a2848401ac6a7dd2ebb0a7d696d967bc66b533
parentc9d8e919f508a150163a68f1be46ba15fffebb7c (diff)
downloadillumos-joyent-dfbb3a42fe4d6d7c50b9f750f514f8c7b66e4ed9.tar.gz
6948314 DMA activities from USB host controller throttle some processor's package C-state
-rw-r--r--usr/src/uts/common/io/usb/hcd/ehci/ehci_isoch_util.c11
-rw-r--r--usr/src/uts/common/io/usb/hcd/ehci/ehci_util.c74
-rw-r--r--usr/src/uts/common/io/usb/hcd/ehci/ehci_xfer.c25
-rw-r--r--usr/src/uts/common/sys/usb/hcd/ehci/ehcid.h7
4 files changed, 96 insertions, 21 deletions
diff --git a/usr/src/uts/common/io/usb/hcd/ehci/ehci_isoch_util.c b/usr/src/uts/common/io/usb/hcd/ehci/ehci_isoch_util.c
index b79aa032bc..fa1968cd0e 100644
--- a/usr/src/uts/common/io/usb/hcd/ehci/ehci_isoch_util.c
+++ b/usr/src/uts/common/io/usb/hcd/ehci/ehci_isoch_util.c
@@ -18,12 +18,11 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
*/
-
/*
* EHCI Host Controller Driver (EHCI)
*
@@ -493,6 +492,9 @@ ehci_allocate_itw(
"ehci_create_itw: itw = 0x%p real_length = 0x%lx",
(void *)itw, real_length);
+ ehcip->ehci_periodic_req_count++;
+ ehci_toggle_scheduler(ehcip);
+
return (itw);
}
@@ -563,6 +565,9 @@ ehci_deallocate_itw(
/* Free this iTWs dma resources */
ehci_free_itw_dma(ehcip, pp, itw);
+
+ ehcip->ehci_periodic_req_count--;
+ ehci_toggle_scheduler(ehcip);
}
diff --git a/usr/src/uts/common/io/usb/hcd/ehci/ehci_util.c b/usr/src/uts/common/io/usb/hcd/ehci/ehci_util.c
index 76f333ccf6..81ac127138 100644
--- a/usr/src/uts/common/io/usb/hcd/ehci/ehci_util.c
+++ b/usr/src/uts/common/io/usb/hcd/ehci/ehci_util.c
@@ -18,9 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
*/
@@ -1095,6 +1095,7 @@ ehci_init_hardware(ehci_state_t *ehcip)
ehcip->ehci_head_of_async_sched_list = dummy_async_qh;
ehcip->ehci_open_async_count++;
+ ehcip->ehci_async_req_count++;
}
}
@@ -4013,9 +4014,32 @@ ehci_wait_for_sof(ehci_state_t *ehcip)
* Turn scheduler based on pipe open count.
*/
void
-ehci_toggle_scheduler(ehci_state_t *ehcip) {
+ehci_toggle_scheduler(ehci_state_t *ehcip)
+{
uint_t temp_reg, cmd_reg;
+ /*
+ * For performance optimization, we need to change the bits
+ * if (async == 1||async == 0) OR (periodic == 1||periodic == 0)
+ *
+ * Related bits already enabled if
+ * async and periodic req counts are > 1
+ * OR async req count > 1 & no periodic pipe
+ * OR periodic req count > 1 & no async pipe
+ */
+ if (((ehcip->ehci_async_req_count > 1) &&
+ (ehcip->ehci_periodic_req_count > 1)) ||
+ ((ehcip->ehci_async_req_count > 1) &&
+ (ehcip->ehci_open_periodic_count == 0)) ||
+ ((ehcip->ehci_periodic_req_count > 1) &&
+ (ehcip->ehci_open_async_count == 0))) {
+ USB_DPRINTF_L4(PRINT_MASK_ATTA,
+ ehcip->ehci_log_hdl, "ehci_toggle_scheduler:"
+ "async/periodic bits no need to change");
+
+ return;
+ }
+
cmd_reg = Get_OpReg(ehci_command);
temp_reg = cmd_reg;
@@ -4023,15 +4047,25 @@ ehci_toggle_scheduler(ehci_state_t *ehcip) {
* Enable/Disable asynchronous scheduler, and
* turn on/off async list door bell
*/
- if (ehcip->ehci_open_async_count) {
+ if (ehcip->ehci_async_req_count > 1) {
+ /* we already enable the async bit */
+ USB_DPRINTF_L4(PRINT_MASK_ATTA,
+ ehcip->ehci_log_hdl, "ehci_toggle_scheduler:"
+ "async bit already enabled: cmd_reg=0x%x", cmd_reg);
+ } else if (ehcip->ehci_async_req_count == 1) {
if (!(cmd_reg & EHCI_CMD_ASYNC_SCHED_ENABLE)) {
/*
* For some reason this address might get nulled out by
* the ehci chip. Set it here just in case it is null.
+ * If it's not null, we should not reset the
+ * ASYNCLISTADDR, because it's updated by hardware to
+ * point to the next queue head to be executed.
*/
- Set_OpReg(ehci_async_list_addr,
- ehci_qh_cpu_to_iommu(ehcip,
- ehcip->ehci_head_of_async_sched_list));
+ if (!Get_OpReg(ehci_async_list_addr)) {
+ Set_OpReg(ehci_async_list_addr,
+ ehci_qh_cpu_to_iommu(ehcip,
+ ehcip->ehci_head_of_async_sched_list));
+ }
/*
* For some reason this register might get nulled out by
@@ -4065,10 +4099,10 @@ ehci_toggle_scheduler(ehci_state_t *ehcip) {
"ehci_toggle_scheduler: "
"ASYNCLISTADDR write failed.");
- USB_DPRINTF_L2(PRINT_MASK_ATTA,
+ USB_DPRINTF_L3(PRINT_MASK_ATTA,
ehcip->ehci_log_hdl,
"ehci_toggle_scheduler: ASYNCLISTADDR "
- "write failed, retry=%d", retry);
+ "write failed, retry=%d", retry);
}
}
cmd_reg |= EHCI_CMD_ASYNC_SCHED_ENABLE;
@@ -4076,7 +4110,12 @@ ehci_toggle_scheduler(ehci_state_t *ehcip) {
cmd_reg &= ~EHCI_CMD_ASYNC_SCHED_ENABLE;
}
- if (ehcip->ehci_open_periodic_count) {
+ if (ehcip->ehci_periodic_req_count > 1) {
+ /* we already enable the periodic bit. */
+ USB_DPRINTF_L4(PRINT_MASK_ATTA,
+ ehcip->ehci_log_hdl, "ehci_toggle_scheduler:"
+ "periodic bit already enabled: cmd_reg=0x%x", cmd_reg);
+ } else if (ehcip->ehci_periodic_req_count == 1) {
if (!(cmd_reg & EHCI_CMD_PERIODIC_SCHED_ENABLE)) {
/*
* For some reason this address get's nulled out by
@@ -4084,7 +4123,7 @@ ehci_toggle_scheduler(ehci_state_t *ehcip) {
*/
Set_OpReg(ehci_periodic_list_base,
(uint32_t)(ehcip->ehci_pflt_cookie.dmac_address &
- 0xFFFFF000));
+ 0xFFFFF000));
}
cmd_reg |= EHCI_CMD_PERIODIC_SCHED_ENABLE;
} else {
@@ -4094,6 +4133,19 @@ ehci_toggle_scheduler(ehci_state_t *ehcip) {
/* Just an optimization */
if (temp_reg != cmd_reg) {
Set_OpReg(ehci_command, cmd_reg);
+
+ /* To make sure the command register is updated correctly */
+ if ((ehcip->ehci_vendor_id == PCI_VENDOR_ULi_M1575) &&
+ (ehcip->ehci_device_id == PCI_DEVICE_ULi_M1575)) {
+ int retry = 0;
+
+ Set_OpRegRetry(ehci_command, cmd_reg, retry);
+ USB_DPRINTF_L3(PRINT_MASK_ATTA,
+ ehcip->ehci_log_hdl,
+ "ehci_toggle_scheduler: CMD write failed, retry=%d",
+ retry);
+ }
+
}
}
diff --git a/usr/src/uts/common/io/usb/hcd/ehci/ehci_xfer.c b/usr/src/uts/common/io/usb/hcd/ehci/ehci_xfer.c
index a6afec8afd..da080b6235 100644
--- a/usr/src/uts/common/io/usb/hcd/ehci/ehci_xfer.c
+++ b/usr/src/uts/common/io/usb/hcd/ehci/ehci_xfer.c
@@ -18,12 +18,11 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
*/
-
/*
* EHCI Host Controller Driver (EHCI)
*
@@ -557,7 +556,6 @@ ehci_insert_qh(
ehcip->ehci_open_periodic_count++;
break;
}
- ehci_toggle_scheduler(ehcip);
}
@@ -1142,7 +1140,6 @@ ehci_remove_qh(
ehcip->ehci_open_periodic_count--;
break;
}
- ehci_toggle_scheduler(ehcip);
}
@@ -2991,6 +2988,7 @@ ehci_create_transfer_wrapper(
ehci_trans_wrapper_t *tw;
int kmem_flag;
int (*dmamem_wait)(caddr_t);
+ usb_ep_descr_t *eptd = &pp->pp_pipe_handle->p_ep;
USB_DPRINTF_L4(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
"ehci_create_transfer_wrapper: length = 0x%lx flags = 0x%x",
@@ -3104,6 +3102,14 @@ dmadone:
ASSERT(tw->tw_id != NULL);
+ /* isoc ep will not come here */
+ if (EHCI_INTR_ENDPOINT(eptd)) {
+ ehcip->ehci_periodic_req_count++;
+ } else {
+ ehcip->ehci_async_req_count++;
+ }
+ ehci_toggle_scheduler(ehcip);
+
USB_DPRINTF_L4(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl,
"ehci_create_transfer_wrapper: tw = 0x%p, ncookies = %u",
(void *)tw, tw->tw_ncookies);
@@ -3515,6 +3521,7 @@ ehci_free_tw(
ehci_trans_wrapper_t *tw)
{
int rval;
+ usb_ep_descr_t *eptd = &pp->pp_pipe_handle->p_ep;
USB_DPRINTF_L4(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl,
"ehci_free_tw: tw = 0x%p", (void *)tw);
@@ -3533,6 +3540,14 @@ ehci_free_tw(
ddi_dma_free_handle(&tw->tw_dmahandle);
}
+ /* interrupt ep will come to this point */
+ if (EHCI_INTR_ENDPOINT(eptd)) {
+ ehcip->ehci_periodic_req_count--;
+ } else {
+ ehcip->ehci_async_req_count--;
+ }
+ ehci_toggle_scheduler(ehcip);
+
/* Free transfer wrapper */
kmem_free(tw, sizeof (ehci_trans_wrapper_t));
}
diff --git a/usr/src/uts/common/sys/usb/hcd/ehci/ehcid.h b/usr/src/uts/common/sys/usb/hcd/ehci/ehcid.h
index aae58e2c66..74b1f12971 100644
--- a/usr/src/uts/common/sys/usb/hcd/ehci/ehcid.h
+++ b/usr/src/uts/common/sys/usb/hcd/ehci/ehcid.h
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _SYS_USB_EHCID_H
@@ -166,6 +165,10 @@ typedef struct ehci_state {
uint_t ehci_open_async_count;
uint_t ehci_open_periodic_count;
+ /* No. of async and periodic requests */
+ uint_t ehci_async_req_count;
+ uint_t ehci_periodic_req_count;
+
/*
* Endpoint Reclamation List
*