diff options
author | Raymond Chen <Raymond.Chen@Sun.COM> | 2010-05-11 09:55:26 +0800 |
---|---|---|
committer | Raymond Chen <Raymond.Chen@Sun.COM> | 2010-05-11 09:55:26 +0800 |
commit | 09af7b171f644af72732347ebe410256b25568c9 (patch) | |
tree | 377449547050fbc54cb951747ddd518c8fe6f57e | |
parent | 3b132919bc64fe4496e5b282129832928afb0c8c (diff) | |
download | illumos-gate-09af7b171f644af72732347ebe410256b25568c9.tar.gz |
6917240 USB port may become disabled due to hardware error, should be re-enabled by software
-rw-r--r-- | usr/src/uts/common/io/usb/hcd/uhci/uhcitgt.c | 32 |
1 files changed, 30 insertions, 2 deletions
diff --git a/usr/src/uts/common/io/usb/hcd/uhci/uhcitgt.c b/usr/src/uts/common/io/usb/hcd/uhci/uhcitgt.c index c7dd4ffb5c..74013d7aae 100644 --- a/usr/src/uts/common/io/usb/hcd/uhci/uhcitgt.c +++ b/usr/src/uts/common/io/usb/hcd/uhci/uhcitgt.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. */ @@ -455,11 +454,40 @@ uhci_hcdi_pipe_reset(usba_pipe_handle_data_t *ph, usb_flags_t usb_flags) ph->p_usba_device->usb_root_hub_dip); uhci_pipe_private_t *pp = (uhci_pipe_private_t *)ph->p_hcd_private; usb_ep_descr_t *eptd = &ph->p_ep; + int i = 0; + uint_t new_port_status = 0, old_port_status = 0; USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, "uhci_hcdi_pipe_reset: usb_flags = 0x%x", usb_flags); /* + * Under some circumstances, uhci internal hub's port + * may become disabled because of some errors(see UHCI HCD Spec) + * to make the UHCI driver robust enough, we should try to + * re-enable it again here because HCD has already know something + * bad happened. + */ + USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, + "uhci_hcdi_pipe_reset: try " + "to enable disabled ports if necessary."); + for (i = 0; i < uhcip->uhci_root_hub.rh_num_ports; i++) { + old_port_status = Get_OpReg16(PORTSC[i]); + if (!(old_port_status & HCR_PORT_ENABLE)) { + Set_OpReg16(PORTSC[i], + (old_port_status | HCR_PORT_ENABLE)); + drv_usecwait(UHCI_ONE_MS * 2); + new_port_status = Get_OpReg16(PORTSC[i]); + /* + * Refresh Root Hub port status + */ + uhcip->uhci_root_hub.rh_port_status[i] = + new_port_status; + uhcip->uhci_root_hub.rh_port_changes[i] |= + ((old_port_status ^ new_port_status) & 0xff); + } + } + + /* * Return failure immediately for any other pipe reset on the root * hub except control or interrupt pipe. */ |