Lines Matching refs:hubd

30  * Most of the code for hubd resides in this file and
31 * is shared between the HCD root hub support and hubd
41 #include <sys/usb/hubd/hub.h>
42 #include <sys/usb/hubd/hubdvar.h>
43 #include <sys/usb/hubd/hubd_impl.h>
501 static int hubd_cleanup(dev_info_t *dip, hubd_t *hubd);
502 static int hubd_check_ports(hubd_t *hubd);
504 static int hubd_open_intr_pipe(hubd_t *hubd);
505 static void hubd_start_polling(hubd_t *hubd, int always);
506 static void hubd_stop_polling(hubd_t *hubd);
507 static void hubd_close_intr_pipe(hubd_t *hubd);
515 hubd_t *hubd,
521 static int hubd_delete_child(hubd_t *hubd, usb_port_t port, uint_t flag,
524 static int hubd_get_hub_descriptor(hubd_t *hubd);
526 static int hubd_get_hub_status_words(hubd_t *hubd, uint16_t *status);
528 static int hubd_reset_port(hubd_t *hubd, usb_port_t port);
530 static int hubd_get_hub_status(hubd_t *hubd);
532 static int hubd_handle_port_connect(hubd_t *hubd, usb_port_t port);
534 static int hubd_disable_port(hubd_t *hubd, usb_port_t port);
536 static int hubd_enable_port(hubd_t *hubd, usb_port_t port);
537 static int hubd_recover_disabled_port(hubd_t *hubd, usb_port_t port);
539 static int hubd_determine_port_status(hubd_t *hubd, usb_port_t port,
542 static int hubd_enable_all_port_power(hubd_t *hubd);
543 static int hubd_disable_all_port_power(hubd_t *hubd);
544 static int hubd_disable_port_power(hubd_t *hubd, usb_port_t port);
545 static int hubd_enable_port_power(hubd_t *hubd, usb_port_t port);
547 static void hubd_free_usba_device(hubd_t *hubd, usba_device_t *usba_device);
549 static int hubd_can_suspend(hubd_t *hubd);
550 static void hubd_restore_device_state(dev_info_t *dip, hubd_t *hubd);
551 static int hubd_setdevaddr(hubd_t *hubd, usb_port_t port);
552 static void hubd_setdevconfig(hubd_t *hubd, usb_port_t port);
554 static int hubd_register_events(hubd_t *hubd);
555 static void hubd_do_callback(hubd_t *hubd, dev_info_t *dip,
557 static void hubd_run_callbacks(hubd_t *hubd, usba_event_t type);
558 static void hubd_post_event(hubd_t *hubd, usb_port_t port, usba_event_t type);
559 static void hubd_create_pm_components(dev_info_t *dip, hubd_t *hubd);
565 static int hubd_cpr_suspend(hubd_t *hubd);
568 static int hubd_check_same_device(hubd_t *hubd, usb_port_t port);
570 static int hubd_init_power_budget(hubd_t *hubd);
599 * hubd_get_soft_state() returns the hubd soft state
626 hubd_pm_busy_component(hubd_t *hubd, dev_info_t *dip, int component)
628 if (hubd->h_hubpm != NULL) {
629 hubd->h_hubpm->hubp_busy_pm++;
630 mutex_exit(HUBD_MUTEX(hubd));
632 mutex_enter(HUBD_MUTEX(hubd));
633 hubd->h_hubpm->hubp_busy_pm--;
634 mutex_exit(HUBD_MUTEX(hubd));
636 mutex_enter(HUBD_MUTEX(hubd));
637 USB_DPRINTF_L4(DPRINT_MASK_PM, hubd->h_log_handle,
638 "hubd_pm_busy_component: %d", hubd->h_hubpm->hubp_busy_pm);
645 hubd_pm_idle_component(hubd_t *hubd, dev_info_t *dip, int component)
647 if (hubd->h_hubpm != NULL) {
648 mutex_exit(HUBD_MUTEX(hubd));
650 mutex_enter(HUBD_MUTEX(hubd));
651 ASSERT(hubd->h_hubpm->hubp_busy_pm > 0);
652 hubd->h_hubpm->hubp_busy_pm--;
653 mutex_exit(HUBD_MUTEX(hubd));
655 mutex_enter(HUBD_MUTEX(hubd));
656 USB_DPRINTF_L4(DPRINT_MASK_PM, hubd->h_log_handle,
657 "hubd_pm_idle_component: %d", hubd->h_hubpm->hubp_busy_pm);
666 hubd_set_child_pwrlvl(hubd_t *hubd, usb_port_t port, uint8_t power)
672 USB_DPRINTF_L4(DPRINT_MASK_PM, hubd->h_log_handle,
676 mutex_enter(HUBD_MUTEX(hubd));
677 hubpm = hubd->h_hubpm;
680 for (portno = 1; portno <= hubd->h_hub_descr.bNbrPorts; portno++) {
685 pwr = hubd->h_hubpm->hubp_child_pwrstate[port];
686 hubd->h_hubpm->hubp_child_pwrstate[port] = power;
689 USB_DPRINTF_L4(DPRINT_MASK_PM, hubd->h_log_handle,
695 (void) hubd_pm_busy_component(hubd, hubd->h_dip, 0);
698 (void) hubd_pm_idle_component(hubd, hubd->h_dip, 0);
700 mutex_exit(HUBD_MUTEX(hubd));
708 hubd_child_dip2port(hubd_t *hubd, dev_info_t *dip)
712 mutex_enter(HUBD_MUTEX(hubd));
713 for (port = 1; port <= hubd->h_hub_descr.bNbrPorts; port++) {
714 if (hubd->h_children_dips[port] == dip) {
719 ASSERT(port <= hubd->h_hub_descr.bNbrPorts);
720 mutex_exit(HUBD_MUTEX(hubd));
731 hubd_can_suspend(hubd_t *hubd)
737 hubpm = hubd->h_hubpm;
739 if (DEVI_IS_DETACHING(hubd->h_dip)) {
755 (port <= hubd->h_hub_descr.bNbrPorts); port++) {
759 USB_DPRINTF_L4(DPRINT_MASK_PM, hubd->h_log_handle,
770 hubd_resume_port(hubd_t *hubd, usb_port_t port)
779 mutex_enter(HUBD_MUTEX(hubd));
781 USB_DPRINTF_L4(DPRINT_MASK_PM, hubd->h_log_handle,
783 hubd->h_dev_state, usb_str_dev_state(hubd->h_dev_state));
785 switch (hubd->h_dev_state) {
791 if ((hubd->h_port_state[port] & PORT_STATUS_PSS) == 0) {
795 USB_DPRINTF_L2(DPRINT_MASK_PM, hubd->h_log_handle,
804 mutex_exit(HUBD_MUTEX(hubd));
805 if ((rval = usb_pipe_sync_ctrl_xfer(hubd->h_dip,
806 hubd->h_default_pipe,
813 USB_DPRINTF_L2(DPRINT_MASK_PM, hubd->h_log_handle,
818 mutex_enter(HUBD_MUTEX(hubd));
821 (void) hubd_determine_port_status(hubd, port,
828 * When hubd's connect event callback posts a connect
834 if (((hubd->h_port_state[port] & PORT_STATUS_CCS) == 0) ||
835 ((hubd->h_port_state[port] & PORT_STATUS_PSS) == 0)) {
842 USB_DPRINTF_L2(DPRINT_MASK_PM, hubd->h_log_handle,
850 hubd->h_hotplug_thread++;
851 hubd_stop_polling(hubd);
855 mutex_exit(HUBD_MUTEX(hubd));
856 rval = usb_pipe_sync_ctrl_xfer(hubd->h_dip,
857 hubd->h_default_pipe,
864 mutex_enter(HUBD_MUTEX(hubd));
867 hubd->h_log_handle,
878 mutex_exit(HUBD_MUTEX(hubd));
880 mutex_enter(HUBD_MUTEX(hubd));
881 (void) hubd_determine_port_status(hubd, port,
894 hubd->h_hotplug_thread--;
895 hubd_start_polling(hubd, 0);
906 USB_DPRINTF_L2(DPRINT_MASK_PM, hubd->h_log_handle,
911 mutex_exit(HUBD_MUTEX(hubd));
921 hubd_suspend_port(hubd_t *hubd, usb_port_t port)
930 USB_DPRINTF_L4(DPRINT_MASK_PM, hubd->h_log_handle,
933 mutex_enter(HUBD_MUTEX(hubd));
935 switch (hubd->h_dev_state) {
938 * When hubd's connect event callback posts a connect
950 hubd->h_hotplug_thread++;
951 hubd_stop_polling(hubd);
960 mutex_exit(HUBD_MUTEX(hubd));
961 if ((rval = usb_pipe_sync_ctrl_xfer(hubd->h_dip,
962 hubd->h_default_pipe,
971 hubd->h_log_handle,
984 mutex_enter(HUBD_MUTEX(hubd));
985 (void) hubd_determine_port_status(hubd, port,
994 hubd->h_log_handle,
1000 hubd->h_hotplug_thread--;
1001 hubd_start_polling(hubd, 0);
1014 USB_DPRINTF_L2(DPRINT_MASK_PM, hubd->h_log_handle,
1019 mutex_exit(HUBD_MUTEX(hubd));
1029 hubd_post_attach(hubd_t *hubd, usb_port_t port, struct attachspec *as)
1033 USB_DPRINTF_L4(DPRINT_MASK_ATTA, hubd->h_log_handle,
1045 mutex_enter(HUBD_MUTEX(hubd));
1046 dip = hubd->h_children_dips[port];
1047 mutex_exit(HUBD_MUTEX(hubd));
1049 hubd_set_child_pwrlvl(hubd, port, USB_DEV_OS_FULL_PWR);
1056 hubd_post_detach(hubd_t *hubd, usb_port_t port, struct detachspec *ds)
1058 USB_DPRINTF_L4(DPRINT_MASK_ATTA, hubd->h_log_handle,
1065 mutex_enter(HUBD_MUTEX(hubd));
1067 usba_device_t *usba_device = hubd->h_usba_devices[port];
1068 dev_info_t *pdip = hubd->h_dip;
1069 mutex_exit(HUBD_MUTEX(hubd));
1078 hubd_set_child_pwrlvl(hubd, port, USB_DEV_OS_PWR_OFF);
1085 mutex_exit(HUBD_MUTEX(hubd));
1097 hubd_post_power(hubd_t *hubd, usb_port_t port, pm_bp_child_pwrchg_t *bpc,
1102 USB_DPRINTF_L4(DPRINT_MASK_PM, hubd->h_log_handle,
1108 hubd_set_child_pwrlvl(hubd, port, bpc->bpc_nlevel);
1113 retval = hubd_suspend_port(hubd, port);
1117 retval = hubd_resume_port(hubd, port);
1122 hubd_set_child_pwrlvl(hubd, port, bpc->bpc_olevel);
1130 retval = hubd_suspend_port(hubd, port);
1152 hubd_t *hubd;
1157 hubd = hubd_get_soft_state(dip);
1159 mutex_enter(HUBD_MUTEX(hubd));
1162 hubd->h_bus_ctls++;
1163 mutex_exit(HUBD_MUTEX(hubd));
1165 USB_DPRINTF_L3(DPRINT_MASK_HUBDI, hubd->h_log_handle,
1173 port = hubd_child_dip2port(hubd, rdip);
1181 ndi_devi_enter(hubd->h_dip, &circ);
1185 USB_DPRINTF_L4(DPRINT_MASK_PM, hubd->h_log_handle,
1189 mutex_enter(HUBD_MUTEX(hubd));
1190 hubd->h_port_state[port] |= HUBD_CHILD_ATTACHING;
1193 (void) hubd_pm_busy_component(hubd, dip, 0);
1194 mutex_exit(HUBD_MUTEX(hubd));
1202 rval = hubd_resume_port(hubd, port);
1209 USB_DPRINTF_L4(DPRINT_MASK_PM, hubd->h_log_handle,
1213 mutex_enter(HUBD_MUTEX(hubd));
1214 hubd->h_port_state[port] &= ~HUBD_CHILD_ATTACHING;
1215 mutex_exit(HUBD_MUTEX(hubd));
1217 hubd_post_attach(hubd, port, (struct attachspec *)arg);
1219 mutex_enter(HUBD_MUTEX(hubd));
1222 (void) hubd_pm_idle_component(hubd, dip, 0);
1223 mutex_exit(HUBD_MUTEX(hubd));
1225 ndi_devi_exit(hubd->h_dip, circ);
1230 port = hubd_child_dip2port(hubd, rdip);
1238 ndi_devi_enter(hubd->h_dip, &circ);
1242 USB_DPRINTF_L4(DPRINT_MASK_PM, hubd->h_log_handle,
1246 mutex_enter(HUBD_MUTEX(hubd));
1247 hubd->h_port_state[port] |= HUBD_CHILD_DETACHING;
1250 (void) hubd_pm_busy_component(hubd, dip, 0);
1252 mutex_exit(HUBD_MUTEX(hubd));
1257 USB_DPRINTF_L4(DPRINT_MASK_PM, hubd->h_log_handle,
1261 mutex_enter(HUBD_MUTEX(hubd));
1262 hubd->h_port_state[port] &= ~HUBD_CHILD_DETACHING;
1263 mutex_exit(HUBD_MUTEX(hubd));
1266 hubd_post_detach(hubd, port, (struct detachspec *)arg);
1268 mutex_enter(HUBD_MUTEX(hubd));
1269 (void) hubd_pm_idle_component(hubd, dip, 0);
1270 mutex_exit(HUBD_MUTEX(hubd));
1274 ndi_devi_exit(hubd->h_dip, circ);
1282 mutex_enter(HUBD_MUTEX(hubd));
1283 hubd->h_bus_ctls--;
1284 ASSERT(hubd->h_bus_ctls >= 0);
1285 mutex_exit(HUBD_MUTEX(hubd));
1296 hubd_config_one(hubd_t *hubd, int port)
1299 dev_info_t *hdip = hubd->h_dip;
1300 dev_info_t *rh_dip = hubd->h_usba_device->usb_root_hub_dip;
1304 USB_DPRINTF_L4(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
1319 mutex_enter(HUBD_MUTEX(hubd));
1321 hubd_pm_busy_component(hubd, hubd->h_dip, 0);
1323 if (!hubd->h_children_dips[port]) {
1325 (void) hubd_determine_port_status(hubd, port,
1329 online_child |= (hubd_handle_port_connect(hubd,
1337 mutex_exit(HUBD_MUTEX(hubd));
1344 USB_DPRINTF_L3(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
1347 (void) ndi_devi_online(hubd->h_dip, 0);
1350 mutex_enter(HUBD_MUTEX(hubd));
1352 (void) hubd_pm_idle_component(hubd, hubd->h_dip, 0);
1354 USB_DPRINTF_L4(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
1357 mutex_exit(HUBD_MUTEX(hubd));
1371 hubd_t *hubd = hubd_get_soft_state(dip);
1375 USB_DPRINTF_L4(DPRINT_MASK_PM, hubd->h_log_handle,
1387 USB_DPRINTF_L2(DPRINT_MASK_PM, hubd->h_log_handle,
1399 found = hubd_config_one(hubd, port);
1406 ndi_devi_enter(hubd->h_dip, &circ);
1408 ndi_devi_exit(hubd->h_dip, circ);
1418 hubd_t *hubd = hubd_get_soft_state(dip);
1424 USB_DPRINTF_L4(DPRINT_MASK_PM, hubd->h_log_handle,
1441 mutex_enter(HUBD_MUTEX(hubd));
1442 for (port = 1; port <= hubd->h_hub_descr.bNbrPorts; port++) {
1443 hubd->h_port_state[port] |= HUBD_CHILD_ZAP;
1445 mutex_exit(HUBD_MUTEX(hubd));
1456 mutex_enter(HUBD_MUTEX(hubd));
1458 hubd->h_children_dips[port] = cdip;
1459 hubd->h_port_state[port] &= ~HUBD_CHILD_ZAP;
1460 mutex_exit(HUBD_MUTEX(hubd));
1464 mutex_enter(HUBD_MUTEX(hubd));
1465 for (port = 1; port <= hubd->h_hub_descr.bNbrPorts; port++) {
1466 if (hubd->h_port_state[port] & HUBD_CHILD_ZAP) {
1468 hubd_free_usba_device(hubd, hubd->h_usba_devices[port]);
1469 hubd->h_children_dips[port] = NULL;
1470 hubd->h_port_state[port] &= ~HUBD_CHILD_ZAP;
1473 mutex_exit(HUBD_MUTEX(hubd));
1477 USB_DPRINTF_L4(DPRINT_MASK_PM, hubd->h_log_handle,
1489 hubd_t *hubd;
1496 hubd = hubd_get_soft_state(dip);
1498 USB_DPRINTF_L4(DPRINT_MASK_HUBDI, hubd->h_log_handle,
1504 mutex_enter(HUBD_MUTEX(hubd));
1505 hubd->h_bus_pwr++;
1506 mutex_exit(HUBD_MUTEX(hubd));
1510 port = hubd_child_dip2port(hubd, bpc->bpc_dip);
1511 USB_DPRINTF_L3(DPRINT_MASK_HUBDI, hubd->h_log_handle,
1516 mutex_enter(HUBD_MUTEX(hubd));
1522 hubd_pm_busy_component(hubd, dip, 0);
1528 if ((hubd->h_dev_state == USB_DEV_PWRED_DOWN) &&
1529 hubd->h_hubpm->hubp_wakeup_enabled) {
1530 mutex_exit(HUBD_MUTEX(hubd));
1542 mutex_enter(HUBD_MUTEX(hubd));
1543 hubd_pm_idle_component(hubd, dip, 0);
1544 mutex_exit(HUBD_MUTEX(hubd));
1548 mutex_enter(HUBD_MUTEX(hubd));
1552 hubd->h_port_state[port] |= HUBD_CHILD_PWRLVL_CHNG;
1553 mutex_exit(HUBD_MUTEX(hubd));
1561 rval = hubd_resume_port(hubd, port);
1566 mutex_enter(HUBD_MUTEX(hubd));
1567 hubd->h_port_state[port] &=
1569 hubd_pm_idle_component(hubd, dip, 0);
1570 mutex_exit(HUBD_MUTEX(hubd));
1578 port = hubd_child_dip2port(hubd, bpc->bpc_dip);
1579 USB_DPRINTF_L3(DPRINT_MASK_HUBDI, hubd->h_log_handle,
1583 mutex_enter(HUBD_MUTEX(hubd));
1584 hubd->h_port_state[port] &= ~HUBD_CHILD_PWRLVL_CHNG;
1585 mutex_exit(HUBD_MUTEX(hubd));
1588 rval = hubd_post_power(hubd, port, bpc, *(int *)result);
1594 mutex_enter(HUBD_MUTEX(hubd));
1600 hubd_pm_idle_component(hubd, dip, 0);
1602 mutex_exit(HUBD_MUTEX(hubd));
1611 mutex_enter(HUBD_MUTEX(hubd));
1612 hubd->h_bus_pwr--;
1613 mutex_exit(HUBD_MUTEX(hubd));
1623 hubd_pwrlvl0(hubd_t *hubd)
1628 if (hubd->h_hotplug_thread || hubd->h_hubpm->hubp_busy_pm ||
1629 (hubd_can_suspend(hubd) == USB_FAILURE)) {
1634 switch (hubd->h_dev_state) {
1636 hubpm = hubd->h_hubpm;
1643 hubd->h_dev_state = USB_DEV_PWRED_DOWN;
1650 if (usba_is_root_hub(hubd->h_dip)) {
1652 USB_DPRINTF_L2(DPRINT_MASK_PM, hubd->h_log_handle,
1655 hubd_stop_polling(hubd);
1659 (void) usb_set_device_pwrlvl3(hubd->h_dip);
1676 hubd_pwrlvl1(hubd_t *hubd)
1679 (void) usb_set_device_pwrlvl2(hubd->h_dip);
1687 hubd_pwrlvl2(hubd_t *hubd)
1690 (void) usb_set_device_pwrlvl1(hubd->h_dip);
1697 hubd_pwrlvl3(hubd_t *hubd)
1702 USB_DPRINTF_L2(DPRINT_MASK_PM, hubd->h_log_handle, "hubd_pwrlvl3");
1704 hubpm = hubd->h_hubpm;
1705 switch (hubd->h_dev_state) {
1708 if (usba_is_root_hub(hubd->h_dip)) {
1711 hubd->h_log_handle,
1715 rval = usb_set_device_pwrlvl0(hubd->h_dip);
1717 hubd->h_dev_state = USB_DEV_ONLINE;
1720 hubd_start_polling(hubd, 0);
1739 USB_DPRINTF_L2(DPRINT_MASK_PM, hubd->h_log_handle,
1740 "hubd_pwrlvl3: Illegal dev_state=%d", hubd->h_dev_state);
1752 hubd_t *hubd;
1757 hubd = hubd_get_soft_state(dip);
1758 USB_DPRINTF_L3(DPRINT_MASK_HUBDI, hubd->h_log_handle,
1763 mutex_enter(HUBD_MUTEX(hubd));
1764 hubpm = hubd->h_hubpm;
1768 USB_DPRINTF_L2(DPRINT_MASK_HUBDI, hubd->h_log_handle,
1771 mutex_exit(HUBD_MUTEX(hubd));
1780 retval = hubd_pwrlvl0(hubd);
1784 retval = hubd_pwrlvl1(hubd);
1788 retval = hubd_pwrlvl2(hubd);
1792 retval = hubd_pwrlvl3(hubd);
1796 mutex_exit(HUBD_MUTEX(hubd));
1819 hubd_t *hubd = NULL;
1850 hubd = hubd_get_soft_state(dip);
1873 hubd = hubd_get_soft_state(dip);
1874 if (hubd == NULL) {
1879 hubd->h_log_handle = usb_alloc_log_hdl(dip, log_name, &hubd_errlevel,
1882 hubd->h_usba_device = child_ud = usba_get_usba_device(dip);
1883 hubd->h_dip = dip;
1884 hubd->h_instance = instance;
1896 USB_DPRINTF_L0(DPRINT_MASK_ATTA, hubd->h_log_handle,
1901 hubd->h_pipe_policy.pp_max_async_reqs = 1;
1905 USB_DPRINTF_L2(DPRINT_MASK_ATTA, hubd->h_log_handle,
1911 if (usb_get_dev_data(dip, &hubd->h_dev_data,
1913 USB_DPRINTF_L2(DPRINT_MASK_ATTA, hubd->h_log_handle,
1919 if ((ep_data = usb_lookup_ep_data(dip, hubd->h_dev_data,
1920 hubd->h_dev_data->dev_curr_if, 0, 0,
1922 USB_DPRINTF_L2(DPRINT_MASK_ATTA, hubd->h_log_handle,
1928 hubd->h_ep1_descr = ep_data->ep_descr;
1929 hubd->h_default_pipe = hubd->h_dev_data->dev_default_ph;
1931 mutex_init(HUBD_MUTEX(hubd), NULL, MUTEX_DRIVER,
1932 hubd->h_dev_data->dev_iblock_cookie);
1933 cv_init(&hubd->h_cv_reset_port, NULL, CV_DRIVER, NULL);
1934 cv_init(&hubd->h_cv_hotplug_dev, NULL, CV_DRIVER, NULL);
1936 hubd->h_init_state |= HUBD_LOCKS_DONE;
1938 usb_free_descr_tree(dip, hubd->h_dev_data);
1945 USB_DPRINTF_L2(DPRINT_MASK_ATTA, hubd->h_log_handle,
1950 mutex_enter(HUBD_MUTEX(hubd));
1951 hubd->h_init_state |= HUBD_HUBDI_REGISTERED;
1952 hubd->h_dev_state = USB_DEV_ONLINE;
1953 mutex_exit(HUBD_MUTEX(hubd));
1956 hubd_create_pm_components(dip, hubd);
1964 (void) ndi_event_alloc_hdl(dip, 0, &hubd->h_ndi_event_hdl, NDI_SLEEP);
1967 if (ndi_event_bind_set(hubd->h_ndi_event_hdl, &hubd_ndi_events,
1969 USB_DPRINTF_L3(DPRINT_MASK_ATTA, hubd->h_log_handle,
1976 if (hubd_register_events(hubd) != USB_SUCCESS) {
1977 USB_DPRINTF_L2(DPRINT_MASK_ATTA, hubd->h_log_handle,
1983 mutex_enter(HUBD_MUTEX(hubd));
1984 hubd->h_init_state |= HUBD_EVENTS_REGISTERED;
1986 if ((hubd_get_hub_descriptor(hubd)) != USB_SUCCESS) {
1987 mutex_exit(HUBD_MUTEX(hubd));
1995 hubd->h_ignore_pwr_budget = B_TRUE;
1997 hubd->h_ignore_pwr_budget = B_FALSE;
2000 if (hubd_init_power_budget(hubd) != USB_SUCCESS) {
2001 USB_DPRINTF_L2(DPRINT_MASK_ATTA, hubd->h_log_handle,
2003 mutex_exit(HUBD_MUTEX(hubd));
2010 if (hubd_check_ports(hubd) != USB_SUCCESS) {
2011 USB_DPRINTF_L2(DPRINT_MASK_ATTA, hubd->h_log_handle,
2013 mutex_exit(HUBD_MUTEX(hubd));
2021 hubd->h_ancestry_str = (char *)kmem_zalloc(HUBD_APID_NAMELEN, KM_SLEEP);
2022 hubd_get_ancestry_str(hubd);
2024 USB_DPRINTF_L4(DPRINT_MASK_ATTA, hubd->h_log_handle,
2025 "#ports=0x%x", hubd->h_hub_descr.bNbrPorts);
2027 for (i = 1; i <= hubd->h_hub_descr.bNbrPorts; i++) {
2031 hubd->h_ancestry_str, i);
2032 USB_DPRINTF_L4(DPRINT_MASK_ATTA, hubd->h_log_handle,
2037 USB_DPRINTF_L2(DPRINT_MASK_ATTA, hubd->h_log_handle,
2040 mutex_exit(HUBD_MUTEX(hubd));
2046 ports_count = hubd->h_hub_descr.bNbrPorts;
2047 mutex_exit(HUBD_MUTEX(hubd));
2050 if (ddi_create_minor_node(dip, "hubd", S_IFCHR,
2053 USB_DPRINTF_L2(DPRINT_MASK_ATTA, hubd->h_log_handle,
2059 mutex_enter(HUBD_MUTEX(hubd));
2060 hubd->h_init_state |= HUBD_MINOR_NODE_CREATED;
2061 mutex_exit(HUBD_MUTEX(hubd));
2065 USB_DPRINTF_L2(DPRINT_MASK_ATTA, hubd->h_log_handle,
2078 hubd->h_cleanup_enabled = B_TRUE;
2079 mutex_enter(HUBD_MUTEX(hubd));
2080 hubd_pm_idle_component(hubd, dip, 0);
2081 mutex_exit(HUBD_MUTEX(hubd));
2095 mutex_enter(HUBD_MUTEX(hubd));
2096 hubd_pm_idle_component(hubd, dip, 0);
2097 mutex_exit(HUBD_MUTEX(hubd));
2099 if (hubd) {
2100 rval = hubd_cleanup(dip, hubd);
2114 hubd_t *hubd = hubd_get_soft_state(dip);
2117 USB_DPRINTF_L4(DPRINT_MASK_ATTA, hubd->h_log_handle,
2122 rval = hubd_cleanup(dip, hubd);
2126 rval = hubd_cpr_suspend(hubd);
2140 hubd_setdevaddr(hubd_t *hubd, usb_port_t port)
2152 USB_DPRINTF_L4(DPRINT_MASK_ATTA, hubd->h_log_handle,
2155 ASSERT(mutex_owned(HUBD_MUTEX(hubd)));
2157 child_dip = hubd->h_children_dips[port];
2158 address = hubd->h_usba_devices[port]->usb_addr;
2159 usba_device = hubd->h_usba_devices[port];
2162 mutex_exit(HUBD_MUTEX(hubd));
2166 mutex_enter(HUBD_MUTEX(hubd));
2177 mutex_exit(HUBD_MUTEX(hubd));
2186 USB_DPRINTF_L2(DPRINT_MASK_ATTA, hubd->h_log_handle,
2201 USB_DPRINTF_L2(DPRINT_MASK_ATTA, hubd->h_log_handle,
2221 mutex_enter(HUBD_MUTEX(hubd));
2234 hubd_setdevconfig(hubd_t *hubd, usb_port_t port)
2244 USB_DPRINTF_L4(DPRINT_MASK_ATTA, hubd->h_log_handle,
2247 ASSERT(mutex_owned(HUBD_MUTEX(hubd)));
2249 child_dip = hubd->h_children_dips[port];
2250 usba_device = hubd->h_usba_devices[port];
2251 config_value = hubd->h_usba_devices[port]->usb_cfg_value;
2252 mutex_exit(HUBD_MUTEX(hubd));
2268 USB_DPRINTF_L2(DPRINT_MASK_ATTA, hubd->h_log_handle,
2280 USB_DPRINTF_L2(DPRINT_MASK_ATTA, hubd->h_log_handle,
2283 mutex_enter(HUBD_MUTEX(hubd));
2293 hubd_t *hubd;
2294 major_t hub_major = ddi_name_to_major("hubd");
2322 hubd = hubd_get_soft_state(dip);
2323 if (hubd == NULL) {
2333 mutex_enter(HUBD_MUTEX(hubd));
2334 for (port = 1; port <= hubd->h_hub_descr.bNbrPorts; port++) {
2335 dev_info_t *cdip = hubd->h_children_dips[port];
2342 (void) hubd_delete_child(hubd, port, NDI_DEVI_REMOVE,
2345 mutex_exit(HUBD_MUTEX(hubd));
2348 if (hubd->h_cleanup_child != NULL) {
2349 if (hubd->h_cleanup_child(dip) != USB_SUCCESS) {
2499 hubd_restore_device_state(dev_info_t *dip, hubd_t *hubd)
2510 USB_DPRINTF_L4(DPRINT_MASK_ATTA, hubd->h_log_handle,
2513 mutex_enter(HUBD_MUTEX(hubd));
2514 hub_prev_state = hubd->h_dev_state;
2518 (void) hubd_pm_busy_component(hubd, dip, 0);
2519 mutex_exit(HUBD_MUTEX(hubd));
2524 (usb_check_same_device(dip, hubd->h_log_handle, USB_LOG_L0,
2529 mutex_enter(HUBD_MUTEX(hubd));
2530 hubd->h_dev_state = USB_DEV_DISCONNECTED;
2531 (void) hubd_pm_idle_component(hubd, dip, 0);
2532 mutex_exit(HUBD_MUTEX(hubd));
2539 mutex_enter(HUBD_MUTEX(hubd));
2541 rval = hubd_disable_all_port_power(hubd);
2543 USB_DPRINTF_L3(DPRINT_MASK_ATTA, hubd->h_log_handle,
2549 mutex_exit(HUBD_MUTEX(hubd));
2551 mutex_enter(HUBD_MUTEX(hubd));
2554 if (hubd_enable_all_port_power(hubd) != USB_SUCCESS) {
2555 USB_DPRINTF_L2(DPRINT_MASK_ATTA, hubd->h_log_handle,
2559 (void) hubd_disable_all_port_power(hubd);
2561 (void) hubd_pm_idle_component(hubd, dip, 0);
2562 mutex_exit(HUBD_MUTEX(hubd));
2572 mutex_exit(HUBD_MUTEX(hubd));
2574 mutex_enter(HUBD_MUTEX(hubd));
2576 hubd->h_dev_state = USB_DEV_HUB_STATE_RECOVER;
2578 for (port = 1; port <= hubd->h_hub_descr.bNbrPorts; port++) {
2579 USB_DPRINTF_L3(DPRINT_MASK_ATTA, hubd->h_log_handle,
2587 ch_dip = hubd->h_children_dips[port];
2590 (void) hubd_determine_port_status(hubd, port,
2601 (void) hubd_reset_port(hubd, port);
2604 (void) hubd_enable_port(hubd, port);
2607 mutex_exit(HUBD_MUTEX(hubd));
2610 mutex_enter(HUBD_MUTEX(hubd));
2613 rval = hubd_setdevaddr(hubd, port);
2618 hubd_setdevconfig(hubd, port);
2622 mutex_exit(HUBD_MUTEX(hubd));
2623 hubd_post_event(hubd, port,
2625 mutex_enter(HUBD_MUTEX(hubd));
2632 mutex_exit(HUBD_MUTEX(hubd));
2643 mutex_enter(HUBD_MUTEX(hubd));
2652 mutex_exit(HUBD_MUTEX(hubd));
2655 hubd->h_log_handle,
2663 mutex_enter(HUBD_MUTEX(hubd));
2667 (void) hubd_determine_port_status(hubd, port,
2679 (void) hubd_reset_port(hubd, port);
2681 (void) hubd_determine_port_status(hubd, port,
2692 (void) hubd_toggle_port(hubd, port);
2695 hubd->h_log_handle,
2707 if (hubd->h_hubpm->hubp_wakeup_enabled) {
2708 mutex_exit(HUBD_MUTEX(hubd));
2709 (void) usb_handle_remote_wakeup(hubd->h_dip,
2711 mutex_enter(HUBD_MUTEX(hubd));
2714 hubd->h_dev_state = USB_DEV_ONLINE;
2715 hubd_start_polling(hubd, 0);
2716 (void) hubd_pm_idle_component(hubd, dip, 0);
2717 mutex_exit(HUBD_MUTEX(hubd));
2723 * cleanup hubd and deallocate. this function is called for
2730 hubd_cleanup(dev_info_t *dip, hubd_t *hubd)
2738 USB_DPRINTF_L4(DPRINT_MASK_ATTA, hubd->h_log_handle,
2741 if ((hubd->h_init_state & HUBD_LOCKS_DONE) == 0) {
2748 mutex_enter(HUBD_MUTEX(hubd));
2752 dev_info_t *rh_dip = hubd->h_usba_device->usb_root_hub_dip;
2760 if (hubd->h_bus_ctls || hubd->h_bus_pwr ||
2761 hubd->h_hotplug_thread) {
2762 mutex_exit(HUBD_MUTEX(hubd));
2765 USB_DPRINTF_L2(DPRINT_MASK_ATTA, hubd->h_log_handle,
2779 if (hubd->h_cleanup_needed ||
2780 hubd->h_cleanup_active) {
2781 mutex_exit(HUBD_MUTEX(hubd));
2785 hubd->h_log_handle,
2794 old_dev_state = hubd->h_dev_state;
2795 hubd->h_dev_state = USB_DEV_DISCONNECTED;
2797 USB_DPRINTF_L4(DPRINT_MASK_ATTA, hubd->h_log_handle,
2799 hubd_close_intr_pipe(hubd);
2801 ASSERT((hubd->h_bus_ctls || hubd->h_bus_pwr ||
2802 hubd->h_hotplug_thread) == 0);
2803 mutex_exit(HUBD_MUTEX(hubd));
2809 if (hubd->h_ndi_event_hdl) {
2811 rval = ndi_event_free_hdl(hubd->h_ndi_event_hdl);
2819 USB_DPRINTF_L2(DPRINT_MASK_ALL, hubd->h_log_handle,
2828 mutex_enter(HUBD_MUTEX(hubd));
2830 if (hubd->h_init_state & HUBD_CHILDREN_CREATED) {
2832 for (port = 1; port <= hubd->h_hub_descr.bNbrPorts; port++) {
2833 ASSERT(hubd->h_usba_devices[port] == NULL);
2834 ASSERT(hubd->h_children_dips[port] == NULL);
2837 kmem_free(hubd->h_children_dips, hubd->h_cd_list_length);
2838 kmem_free(hubd->h_usba_devices, hubd->h_cd_list_length);
2849 if (hubd->h_init_state & HUBD_EVENTS_REGISTERED) {
2850 mutex_exit(HUBD_MUTEX(hubd));
2852 hubd_unregister_cpr_callback(hubd);
2853 mutex_enter(HUBD_MUTEX(hubd));
2857 hubd->h_dev_state = old_dev_state;
2858 hubpm = hubd->h_hubpm;
2860 if ((hubpm) && (hubd->h_dev_state != USB_DEV_DISCONNECTED)) {
2861 (void) hubd_pm_busy_component(hubd, dip, 0);
2862 mutex_exit(HUBD_MUTEX(hubd));
2863 if (hubd->h_hubpm->hubp_wakeup_enabled) {
2870 if ((rval = usb_handle_remote_wakeup(hubd->h_dip,
2873 hubd->h_log_handle,
2879 (void) pm_lower_power(hubd->h_dip, 0, USB_DEV_OS_PWR_OFF);
2881 mutex_enter(HUBD_MUTEX(hubd));
2882 (void) hubd_pm_idle_component(hubd, dip, 0);
2892 mutex_exit(HUBD_MUTEX(hubd));
2894 USB_DPRINTF_L4(DPRINT_MASK_ATTA, hubd->h_log_handle,
2897 if (hubd->h_init_state & HUBD_HUBDI_REGISTERED) {
2902 if (hubd->h_init_state & HUBD_LOCKS_DONE) {
2903 mutex_destroy(HUBD_MUTEX(hubd));
2904 cv_destroy(&hubd->h_cv_reset_port);
2905 cv_destroy(&hubd->h_cv_hotplug_dev);
2910 if (hubd->h_init_state & HUBD_MINOR_NODE_CREATED) {
2915 usb_pipe_close(dip, hubd->h_default_pipe,
2920 if (hubd->h_ancestry_str) {
2921 kmem_free(hubd->h_ancestry_str, HUBD_APID_NAMELEN);
2924 usb_client_detach(dip, hubd->h_dev_data);
2926 usb_free_log_hdl(hubd->h_log_handle);
2946 hubd_determine_port_connection(hubd_t *hubd)
2954 ASSERT(mutex_owned(HUBD_MUTEX(hubd)));
2956 hub_descr = &hubd->h_hub_descr;
2960 (void) hubd_determine_port_status(hubd, port, &status,
2994 hubd_check_ports(hubd_t *hubd)
3000 ASSERT(mutex_owned(HUBD_MUTEX(hubd)));
3002 USB_DPRINTF_L4(DPRINT_MASK_PORT, hubd->h_log_handle,
3003 "hubd_check_ports: addr=0x%x", usb_get_addr(hubd->h_dip));
3008 if ((rval = hubd_disable_all_port_power(hubd)) != USB_SUCCESS) {
3011 (void) hubd_disable_all_port_power(hubd);
3020 mutex_exit(HUBD_MUTEX(hubd));
3022 mutex_enter(HUBD_MUTEX(hubd));
3027 if ((rval = hubd_enable_all_port_power(hubd)) != USB_SUCCESS) {
3029 (void) hubd_disable_all_port_power(hubd);
3035 mutex_exit(HUBD_MUTEX(hubd));
3037 mutex_enter(HUBD_MUTEX(hubd));
3044 hubd->h_cd_list_length =
3045 (sizeof (dev_info_t **)) * (hubd->h_hub_descr.bNbrPorts + 1);
3047 hubd->h_children_dips = (dev_info_t **)kmem_zalloc(
3048 hubd->h_cd_list_length, KM_SLEEP);
3049 hubd->h_usba_devices = (usba_device_t **)kmem_zalloc(
3050 hubd->h_cd_list_length, KM_SLEEP);
3052 hubd->h_init_state |= HUBD_CHILDREN_CREATED;
3054 mutex_exit(HUBD_MUTEX(hubd));
3057 mutex_enter(HUBD_MUTEX(hubd));
3059 if ((rval = hubd_open_intr_pipe(hubd)) != USB_SUCCESS) {
3065 hubd_start_polling(hubd, 0);
3077 port_change = hubd_determine_port_connection(hubd);
3080 hubd_pm_busy_component(hubd, hubd->h_dip, 0);
3082 arg->hubd = hubd;
3084 hubd->h_port_change |= port_change;
3086 USB_DPRINTF_L3(DPRINT_MASK_PORT, hubd->h_log_handle,
3088 hubd->h_port_change);
3090 if (usb_async_req(hubd->h_dip, hubd_hotplug_thread,
3092 hubd->h_hotplug_thread++;
3095 hubd_pm_idle_component(hubd, hubd->h_dip, 0);
3102 USB_DPRINTF_L4(DPRINT_MASK_ATTA, hubd->h_log_handle,
3113 hubd_get_hub_descriptor(hubd_t *hubd)
3115 usb_hub_descr_t *hub_descr = &hubd->h_hub_descr;
3123 USB_DPRINTF_L4(DPRINT_MASK_HUB, hubd->h_log_handle,
3126 if ((hubd->h_dev_data->dev_descr->idVendor == USB_HUB_INTEL_VID) &&
3127 (hubd->h_dev_data->dev_descr->idProduct == USB_HUB_INTEL_PID)) {
3131 ASSERT(mutex_owned(HUBD_MUTEX(hubd)));
3132 ASSERT(hubd->h_default_pipe != 0);
3135 mutex_exit(HUBD_MUTEX(hubd));
3137 if ((rval = usb_pipe_sync_ctrl_xfer(hubd->h_dip,
3138 hubd->h_default_pipe,
3146 USB_DPRINTF_L2(DPRINT_MASK_ATTA, hubd->h_log_handle,
3150 mutex_enter(HUBD_MUTEX(hubd));
3162 rval = usb_pipe_sync_ctrl_xfer(hubd->h_dip,
3163 hubd->h_default_pipe,
3177 USB_DPRINTF_L2(DPRINT_MASK_ATTA, hubd->h_log_handle,
3183 mutex_enter(HUBD_MUTEX(hubd));
3189 mutex_enter(HUBD_MUTEX(hubd));
3197 USB_DPRINTF_L2(DPRINT_MASK_ATTA, hubd->h_log_handle,
3207 USB_DPRINTF_L4(DPRINT_MASK_ATTA, hubd->h_log_handle,
3214 USB_DPRINTF_L0(DPRINT_MASK_ATTA, hubd->h_log_handle,
3230 hubd_get_hub_status_words(hubd_t *hubd, uint16_t *status)
3236 ASSERT(mutex_owned(HUBD_MUTEX(hubd)));
3238 mutex_exit(HUBD_MUTEX(hubd));
3240 if (usb_pipe_sync_ctrl_xfer(hubd->h_dip, hubd->h_default_pipe,
3248 USB_DPRINTF_L2(DPRINT_MASK_HUB, hubd->h_log_handle,
3256 mutex_enter(HUBD_MUTEX(hubd));
3261 mutex_enter(HUBD_MUTEX(hubd));
3266 USB_DPRINTF_L3(DPRINT_MASK_HUB, hubd->h_log_handle,
3281 hubd_open_intr_pipe(hubd_t *hubd)
3285 USB_DPRINTF_L4(DPRINT_MASK_HUB, hubd->h_log_handle,
3288 ASSERT(hubd->h_intr_pipe_state == HUBD_INTR_PIPE_IDLE);
3290 hubd->h_intr_pipe_state = HUBD_INTR_PIPE_OPENING;
3291 mutex_exit(HUBD_MUTEX(hubd));
3293 if ((rval = usb_pipe_open(hubd->h_dip,
3294 &hubd->h_ep1_descr, &hubd->h_pipe_policy,
3295 0, &hubd->h_ep1_ph)) != USB_SUCCESS) {
3296 USB_DPRINTF_L2(DPRINT_MASK_HUB, hubd->h_log_handle,
3299 mutex_enter(HUBD_MUTEX(hubd));
3300 hubd->h_intr_pipe_state = HUBD_INTR_PIPE_IDLE;
3305 mutex_enter(HUBD_MUTEX(hubd));
3306 hubd->h_intr_pipe_state = HUBD_INTR_PIPE_ACTIVE;
3308 USB_DPRINTF_L4(DPRINT_MASK_HUB, hubd->h_log_handle,
3309 "open intr pipe succeeded, ph=0x%p", (void *)hubd->h_ep1_ph);
3320 hubd_start_polling(hubd_t *hubd, int always)
3326 USB_DPRINTF_L4(DPRINT_MASK_HUB, hubd->h_log_handle,
3329 always, hubd->h_dev_state, hubd->h_intr_pipe_state,
3330 hubd->h_hotplug_thread, (void *)hubd->h_ep1_ph);
3337 ((hubd->h_dev_state == USB_DEV_ONLINE) &&
3338 (hubd->h_intr_pipe_state == HUBD_INTR_PIPE_ACTIVE) &&
3339 (hubd->h_hotplug_thread == 0) && hubd->h_ep1_ph)) {
3340 USB_DPRINTF_L4(DPRINT_MASK_HUB, hubd->h_log_handle,
3343 reqp = usb_alloc_intr_req(hubd->h_dip, 0, USB_FLAGS_SLEEP);
3345 reqp->intr_client_private = (usb_opaque_t)hubd;
3348 reqp->intr_len = hubd->h_ep1_descr.wMaxPacketSize;
3351 mutex_exit(HUBD_MUTEX(hubd));
3352 if ((rval = usb_pipe_intr_xfer(hubd->h_ep1_ph, reqp,
3354 USB_DPRINTF_L2(DPRINT_MASK_HUB, hubd->h_log_handle,
3359 rval = usb_pipe_get_state(hubd->h_ep1_ph, &pipe_state,
3362 USB_DPRINTF_L2(DPRINT_MASK_PORT, hubd->h_log_handle,
3365 USB_DPRINTF_L4(DPRINT_MASK_HUB, hubd->h_log_handle,
3368 mutex_enter(HUBD_MUTEX(hubd));
3378 hubd_stop_polling(hubd_t *hubd)
3383 if (hubd->h_ep1_ph) {
3384 USB_DPRINTF_L4(DPRINT_MASK_PORT, hubd->h_log_handle,
3386 hubd->h_intr_pipe_state = HUBD_INTR_PIPE_STOPPED;
3387 mutex_exit(HUBD_MUTEX(hubd));
3389 usb_pipe_stop_intr_polling(hubd->h_ep1_ph, USB_FLAGS_SLEEP);
3390 rval = usb_pipe_get_state(hubd->h_ep1_ph, &pipe_state,
3394 USB_DPRINTF_L2(DPRINT_MASK_PORT, hubd->h_log_handle,
3397 mutex_enter(HUBD_MUTEX(hubd));
3398 if (hubd->h_intr_pipe_state == HUBD_INTR_PIPE_STOPPED) {
3399 hubd->h_intr_pipe_state = HUBD_INTR_PIPE_ACTIVE;
3411 hubd_close_intr_pipe(hubd_t *hubd)
3413 USB_DPRINTF_L4(DPRINT_MASK_HUB, hubd->h_log_handle,
3420 hubd->h_intr_pipe_state = HUBD_INTR_PIPE_CLOSING;
3422 ASSERT(hubd->h_hotplug_thread == 0);
3424 if (hubd->h_ep1_ph) {
3425 mutex_exit(HUBD_MUTEX(hubd));
3426 usb_pipe_close(hubd->h_dip, hubd->h_ep1_ph, USB_FLAGS_SLEEP,
3428 mutex_enter(HUBD_MUTEX(hubd));
3429 hubd->h_ep1_ph = NULL;
3432 hubd->h_intr_pipe_state = HUBD_INTR_PIPE_IDLE;
3446 hubd_t *hubd = (hubd_t *)(reqp->intr_client_private);
3448 USB_DPRINTF_L2(DPRINT_MASK_CALLBACK, hubd->h_log_handle,
3456 mutex_enter(HUBD_MUTEX(hubd));
3457 (void) hubd_pm_busy_component(hubd, hubd->h_dip, 0);
3462 if ((hubd->h_intr_pipe_state == HUBD_INTR_PIPE_ACTIVE) &&
3463 (hubd->h_port_reset_wait == 0)) {
3464 hubd_start_polling(hubd, 0);
3480 (void) hubd_pm_idle_component(hubd, hubd->h_dip, 0);
3481 mutex_exit(HUBD_MUTEX(hubd));
3521 hubd_t *hubd = (hubd_t *)(reqp->intr_client_private);
3527 USB_DPRINTF_L4(DPRINT_MASK_HUB, hubd->h_log_handle,
3547 mutex_enter(HUBD_MUTEX(hubd));
3549 if ((hubd->h_dev_state == USB_DEV_SUSPENDED) ||
3550 (hubd->h_intr_pipe_state != HUBD_INTR_PIPE_ACTIVE)) {
3551 mutex_exit(HUBD_MUTEX(hubd));
3558 ASSERT(hubd->h_ep1_ph == pipe);
3579 hubd->h_port_change |= port_change &
3580 ~hubd->h_port_reset_wait;
3582 USB_DPRINTF_L3(DPRINT_MASK_CALLBACK, hubd->h_log_handle,
3584 hubd->h_port_change, hubd->h_port_reset_wait);
3587 if (hubd->h_port_reset_wait & port_change) {
3588 hubd->h_port_reset_wait = 0;
3589 cv_signal(&hubd->h_cv_reset_port);
3596 if ((hubd->h_dev_state == USB_DEV_ONLINE) &&
3597 (!DEVI_IS_ATTACHING(hubd->h_dip)) &&
3598 (!DEVI_IS_DETACHING(hubd->h_dip)) &&
3599 (hubd->h_port_change) &&
3600 (hubd->h_hotplug_thread == 0)) {
3601 USB_DPRINTF_L3(DPRINT_MASK_CALLBACK, hubd->h_log_handle,
3603 "dev_state=%d", hubd->h_dev_state);
3610 (void) hubd_pm_busy_component(hubd, hubd->h_dip, 0);
3612 arg->hubd = hubd;
3615 if (usb_async_req(hubd->h_dip,
3618 hubd->h_hotplug_thread++;
3622 (void) hubd_pm_idle_component(hubd,
3623 hubd->h_dip, 0);
3627 mutex_exit(HUBD_MUTEX(hubd));
3648 hubd_t *hubd = hd_arg->hubd;
3654 dev_info_t *hdip = hubd->h_dip;
3655 dev_info_t *rh_dip = hubd->h_usba_device->usb_root_hub_dip;
3662 USB_DPRINTF_L4(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
3684 mutex_enter(HUBD_MUTEX(hubd));
3685 if (hubd->h_bus_pwr || (hubd->h_hotplug_thread > 1)) {
3686 hubd->h_hotplug_thread--;
3689 hubd_pm_idle_component(hubd, hubd->h_dip, 0);
3690 mutex_exit(HUBD_MUTEX(hubd));
3692 USB_DPRINTF_L3(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
3698 mutex_exit(HUBD_MUTEX(hubd));
3702 mutex_enter(HUBD_MUTEX(hubd));
3706 if (hubd->h_dev_state == USB_DEV_PWRED_DOWN) {
3707 hubpm = hubd->h_hubpm;
3712 mutex_exit(HUBD_MUTEX(hubd));
3714 USB_DPRINTF_L4(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
3720 mutex_enter(HUBD_MUTEX(hubd));
3721 hubd->h_dev_state = USB_DEV_ONLINE;
3725 USB_DPRINTF_L4(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
3729 mutex_exit(HUBD_MUTEX(hubd));
3742 mutex_enter(HUBD_MUTEX(hubd));
3744 ASSERT(hubd->h_intr_pipe_state == HUBD_INTR_PIPE_ACTIVE);
3746 nports = hubd->h_hub_descr.bNbrPorts;
3748 hubd_stop_polling(hubd);
3750 while ((hubd->h_dev_state == USB_DEV_ONLINE) &&
3751 (hubd->h_port_change)) {
3756 if (hubd->h_port_change & HUB_CHANGE_STATUS) {
3757 USB_DPRINTF_L3(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
3764 hubd->h_port_change &= ~HUB_CHANGE_STATUS;
3771 (void) hubd_get_hub_status(hubd);
3780 (hubd->h_port_state[port] & PORT_STATUS_CCS) &&
3781 (hubd->h_children_dips[port]);
3783 USB_DPRINTF_L3(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
3786 port, port_mask, hubd->h_port_change,
3792 if ((hubd->h_port_change & port_mask) == 0) {
3796 hubd->h_port_change &= ~port_mask;
3799 (void) hubd_determine_port_status(hubd, port,
3802 USB_DPRINTF_L3(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
3810 hubd->h_log_handle,
3822 (hubd_recover_disabled_port(hubd,
3835 (hubd_handle_port_connect(hubd,
3846 child_dip = hubd->h_children_dips[port];
3848 mutex_exit(HUBD_MUTEX(hubd));
3864 hubd_post_event(hubd, port,
3866 mutex_enter(HUBD_MUTEX(hubd));
3874 hubd, port) == USB_SUCCESS);
3876 mutex_exit(HUBD_MUTEX(hubd));
3880 mutex_enter(HUBD_MUTEX(hubd));
3883 mutex_exit(HUBD_MUTEX(hubd));
3884 hubd_post_event(hubd, port,
3886 mutex_enter(HUBD_MUTEX(hubd));
3898 hubd->h_children_dips[port]) {
3903 dip = hubd->h_children_dips[port];
3922 hubd->h_port_state[port] |=
3925 mutex_exit(HUBD_MUTEX(hubd));
3933 mutex_enter(HUBD_MUTEX(hubd));
3943 hubd->h_log_handle,
3957 (void) hubd_enable_port_power(hubd,
3965 mutex_exit(HUBD_MUTEX(hubd));
3967 mutex_enter(HUBD_MUTEX(hubd));
3974 mutex_exit(HUBD_MUTEX(hubd));
3985 USB_DPRINTF_L3(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
3988 (void) ndi_devi_online(hubd->h_dip, 0);
3993 USB_DPRINTF_L3(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
3996 hubd_schedule_cleanup(hubd->h_usba_device->usb_root_hub_dip);
3999 mutex_enter(HUBD_MUTEX(hubd));
4003 old_state = hubd->h_dev_state;
4004 hubd->h_dev_state = USB_DEV_HUB_CHILD_PWRLVL;
4006 if (hubd->h_port_state[port] & HUBD_CHILD_RAISE_POWER) {
4007 dev_info_t *dip = hubd->h_children_dips[port];
4009 mutex_exit(HUBD_MUTEX(hubd));
4019 mutex_enter(HUBD_MUTEX(hubd));
4020 hubd->h_port_state[port] &=
4028 if (hubd->h_dev_state == USB_DEV_HUB_CHILD_PWRLVL) {
4029 hubd->h_dev_state = old_state;
4043 if (hubd->h_reset_port[port]) {
4049 hubd_start_polling(hubd, HUBD_ALWAYS_START_POLLING);
4061 hubd->h_hotplug_thread--;
4064 (void) hubd_pm_idle_component(hubd, hubd->h_dip, 0);
4066 cv_broadcast(&hubd->h_cv_hotplug_dev);
4068 USB_DPRINTF_L4(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
4071 mutex_exit(HUBD_MUTEX(hubd));
4084 hubd_handle_port_connect(hubd_t *hubd, usb_port_t port)
4098 usba_device = hubd->h_usba_device;
4122 mutex_exit(HUBD_MUTEX(hubd));
4124 mutex_enter(HUBD_MUTEX(hubd));
4129 for (retry = 0; (hubd->h_dev_state == USB_DEV_ONLINE) &&
4131 USB_DPRINTF_L4(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
4134 if ((rval = hubd_reset_port(hubd, port)) != USB_SUCCESS) {
4135 (void) hubd_determine_port_status(hubd,
4156 (void) hubd_enable_port(hubd, port);
4164 mutex_exit(HUBD_MUTEX(hubd));
4166 mutex_enter(HUBD_MUTEX(hubd));
4175 (void) hubd_enable_port(hubd, port);
4178 if ((rval = hubd_determine_port_status(hubd, port, &status,
4181 USB_DPRINTF_L2(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
4184 (void) hubd_disable_port(hubd, port);
4190 USB_DPRINTF_L0(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
4193 (void) hubd_disable_port(hubd, port);
4196 (void) hubd_determine_port_status(hubd,
4204 USB_DPRINTF_L2(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
4228 USB_DPRINTF_L3(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
4237 if (hubd->h_children_dips[port]) {
4239 rval = hubd_setdevaddr(hubd, port);
4247 mutex_exit(HUBD_MUTEX(hubd));
4250 mutex_enter(HUBD_MUTEX(hubd));
4258 if ((hubd->h_reset_port[port]) &&
4259 (hubd_check_same_device(hubd,
4270 hubd_setdevconfig(hubd, port);
4278 if (hubd->h_reset_port[port]) {
4287 mutex_exit(HUBD_MUTEX(hubd));
4288 hubd_post_event(hubd, port,
4290 mutex_enter(HUBD_MUTEX(hubd));
4307 rval = hubd_create_child(hubd->h_dip,
4308 hubd,
4309 hubd->h_usba_device,
4313 usba_update_hotplug_stats(hubd->h_dip,
4316 hubd->h_total_hotplug_success++;
4321 hubd->h_log_handle,
4336 USB_DPRINTF_L2(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
4339 (void) hubd_disable_port(hubd, port);
4341 mutex_exit(HUBD_MUTEX(hubd));
4343 mutex_enter(HUBD_MUTEX(hubd));
4346 USB_DPRINTF_L2(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
4363 hubd->h_log_handle,
4368 hubd->h_log_handle,
4372 (void) hubd_disable_port(hubd, port);
4373 usba_update_hotplug_stats(hubd->h_dip,
4375 hubd->h_total_hotplug_failure++;
4382 (void) hubd_disable_port(hubd, port);
4385 (void) hubd_determine_port_status(hubd,
4398 hubd_get_hub_status(hubd_t *hubd)
4413 USB_DPRINTF_L4(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
4416 ASSERT(mutex_owned(HUBD_MUTEX(hubd)));
4418 if ((hubd_get_hub_status_words(hubd, stword)) != USB_SUCCESS) {
4425 mutex_exit(HUBD_MUTEX(hubd));
4428 usb_cfg = usb_get_raw_cfg_data(hubd->h_dip, &cfg_length);
4436 USB_DPRINTF_L2(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
4439 mutex_enter(HUBD_MUTEX(hubd));
4464 hubd->h_log_handle,
4473 hubd->h_log_handle,
4482 USB_DPRINTF_L3(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
4485 if ((rval = usb_pipe_sync_ctrl_xfer(hubd->h_dip,
4486 hubd->h_default_pipe,
4495 hubd->h_log_handle,
4507 if (usba_is_root_hub(hubd->h_dip)) {
4515 hubd->h_log_handle,
4532 hubd->h_log_handle,
4541 USB_DPRINTF_L3(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
4544 if ((rval = usb_pipe_sync_ctrl_xfer(hubd->h_dip,
4545 hubd->h_default_pipe,
4554 hubd->h_log_handle,
4565 if (!usba_is_root_hub(hubd->h_dip)) {
4567 mutex_enter(HUBD_MUTEX(hubd));
4573 (void) hubd_determine_port_status(hubd, 1, &status,
4581 hub_descr = &hubd->h_hub_descr;
4586 (void) hubd_enable_port_power(hubd, port);
4589 mutex_exit(HUBD_MUTEX(hubd));
4599 mutex_enter(HUBD_MUTEX(hubd));
4609 hubd_reset_port(hubd_t *hubd, usb_port_t port)
4621 USB_DPRINTF_L4(DPRINT_MASK_PORT, hubd->h_log_handle,
4624 ASSERT(mutex_owned(HUBD_MUTEX(hubd)));
4626 hubd->h_port_reset_wait |= port_mask;
4628 mutex_exit(HUBD_MUTEX(hubd));
4630 if ((rval = usb_pipe_sync_ctrl_xfer(hubd->h_dip,
4631 hubd->h_default_pipe,
4639 USB_DPRINTF_L2(DPRINT_MASK_PORT, hubd->h_log_handle,
4643 mutex_enter(HUBD_MUTEX(hubd));
4648 mutex_enter(HUBD_MUTEX(hubd));
4650 USB_DPRINTF_L4(DPRINT_MASK_PORT, hubd->h_log_handle,
4662 hubd_start_polling(hubd, HUBD_ALWAYS_START_POLLING);
4668 if (hubd->h_port_reset_wait & port_mask) {
4669 rval = cv_reltimedwait(&hubd->h_cv_reset_port,
4670 &hubd->h_mutex, delta, TR_CLOCK_TICK);
4672 (hubd->h_port_reset_wait & port_mask)) {
4675 hubd->h_log_handle,
4678 hubd->h_port_reset_wait &= ~port_mask;
4680 hubd_stop_polling(hubd);
4686 USB_DPRINTF_L4(DPRINT_MASK_PORT, hubd->h_log_handle,
4689 hubd_stop_polling(hubd);
4694 mutex_exit(HUBD_MUTEX(hubd));
4695 if ((rval = usb_pipe_sync_ctrl_xfer(hubd->h_dip,
4696 hubd->h_default_pipe,
4705 hubd->h_log_handle,
4713 mutex_enter(HUBD_MUTEX(hubd));
4729 mutex_enter(HUBD_MUTEX(hubd));
4735 USB_DPRINTF_L3(DPRINT_MASK_PORT, hubd->h_log_handle,
4737 mutex_enter(HUBD_MUTEX(hubd));
4741 USB_DPRINTF_L3(DPRINT_MASK_PORT, hubd->h_log_handle,
4746 USB_DPRINTF_L3(DPRINT_MASK_PORT, hubd->h_log_handle,
4749 if (usb_pipe_sync_ctrl_xfer(hubd->h_dip,
4750 hubd->h_default_pipe,
4759 hubd->h_log_handle,
4765 mutex_enter(HUBD_MUTEX(hubd));
4784 hubd_enable_port(hubd_t *hubd, usb_port_t port)
4790 USB_DPRINTF_L4(DPRINT_MASK_PORT, hubd->h_log_handle,
4793 ASSERT(mutex_owned(HUBD_MUTEX(hubd)));
4795 mutex_exit(HUBD_MUTEX(hubd));
4798 if (!usba_is_root_hub(hubd->h_dip)) {
4799 mutex_enter(HUBD_MUTEX(hubd));
4804 if ((rval = usb_pipe_sync_ctrl_xfer(hubd->h_dip,
4805 hubd->h_default_pipe,
4813 USB_DPRINTF_L2(DPRINT_MASK_PORT, hubd->h_log_handle,
4818 mutex_enter(HUBD_MUTEX(hubd));
4820 USB_DPRINTF_L4(DPRINT_MASK_PORT, hubd->h_log_handle,
4831 hubd_disable_port(hubd_t *hubd, usb_port_t port)
4837 USB_DPRINTF_L4(DPRINT_MASK_PORT, hubd->h_log_handle,
4840 ASSERT(mutex_owned(HUBD_MUTEX(hubd)));
4842 mutex_exit(HUBD_MUTEX(hubd));
4844 if ((rval = usb_pipe_sync_ctrl_xfer(hubd->h_dip,
4845 hubd->h_default_pipe,
4853 USB_DPRINTF_L2(DPRINT_MASK_PORT, hubd->h_log_handle,
4856 mutex_enter(HUBD_MUTEX(hubd));
4861 USB_DPRINTF_L3(DPRINT_MASK_PORT, hubd->h_log_handle,
4864 if ((rval = usb_pipe_sync_ctrl_xfer(hubd->h_dip,
4865 hubd->h_default_pipe,
4874 hubd->h_log_handle,
4879 mutex_enter(HUBD_MUTEX(hubd));
4884 mutex_enter(HUBD_MUTEX(hubd));
4894 hubd_determine_port_status(hubd_t *hubd, usb_port_t port,
4902 USB_DPRINTF_L4(DPRINT_MASK_PORT, hubd->h_log_handle,
4904 hubd->h_port_state[port], ack_flag);
4906 ASSERT(mutex_owned(HUBD_MUTEX(hubd)));
4908 mutex_exit(HUBD_MUTEX(hubd));
4910 if ((rval = usb_pipe_sync_ctrl_xfer(hubd->h_dip,
4911 hubd->h_default_pipe,
4919 USB_DPRINTF_L2(DPRINT_MASK_PORT, hubd->h_log_handle,
4928 mutex_enter(HUBD_MUTEX(hubd));
4933 mutex_enter(HUBD_MUTEX(hubd));
4935 USB_DPRINTF_L2(DPRINT_MASK_PORT, hubd->h_log_handle,
4948 USB_DPRINTF_L3(DPRINT_MASK_PORT, hubd->h_log_handle,
4954 USB_DPRINTF_L3(DPRINT_MASK_PORT, hubd->h_log_handle,
4957 hubd->h_port_state[port] |= (PORT_STATUS_CCS & ack_flag);
4959 USB_DPRINTF_L3(DPRINT_MASK_PORT, hubd->h_log_handle,
4962 hubd->h_port_state[port] &= ~(PORT_STATUS_CCS & ack_flag);
4966 USB_DPRINTF_L3(DPRINT_MASK_PORT, hubd->h_log_handle,
4969 hubd->h_port_state[port] |= (PORT_STATUS_PES & ack_flag);
4971 USB_DPRINTF_L3(DPRINT_MASK_PORT, hubd->h_log_handle,
4974 hubd->h_port_state[port] &= ~(PORT_STATUS_PES & ack_flag);
4978 USB_DPRINTF_L3(DPRINT_MASK_PORT, hubd->h_log_handle,
4981 hubd->h_port_state[port] |= (PORT_STATUS_PSS & ack_flag);
4983 USB_DPRINTF_L3(DPRINT_MASK_PORT, hubd->h_log_handle,
4986 hubd->h_port_state[port] &= ~(PORT_STATUS_PSS & ack_flag);
4990 USB_DPRINTF_L3(DPRINT_MASK_PORT, hubd->h_log_handle,
4993 hubd->h_port_state[port] |= (PORT_CHANGE_PRSC & ack_flag);
4996 hubd->h_port_state[port] &= ~(PORT_CHANGE_PRSC & ack_flag);
5000 USB_DPRINTF_L2(DPRINT_MASK_PORT, hubd->h_log_handle,
5003 hubd->h_port_state[port] |= (PORT_STATUS_POCI & ack_flag);
5006 hubd->h_port_state[port] &= ~(PORT_STATUS_POCI & ack_flag);
5010 USB_DPRINTF_L3(DPRINT_MASK_PORT, hubd->h_log_handle,
5013 hubd->h_port_state[port] |= (PORT_STATUS_PRS & ack_flag);
5015 USB_DPRINTF_L3(DPRINT_MASK_PORT, hubd->h_log_handle,
5018 hubd->h_port_state[port] &= ~(PORT_STATUS_PRS & ack_flag);
5021 USB_DPRINTF_L3(DPRINT_MASK_PORT, hubd->h_log_handle,
5024 hubd->h_port_state[port] |= (PORT_STATUS_PPS & ack_flag);
5026 USB_DPRINTF_L3(DPRINT_MASK_PORT, hubd->h_log_handle,
5029 hubd->h_port_state[port] &= ~(PORT_STATUS_PPS & ack_flag);
5032 USB_DPRINTF_L3(DPRINT_MASK_PORT, hubd->h_log_handle,
5035 hubd->h_port_state[port] |= (PORT_STATUS_LSDA & ack_flag);
5037 hubd->h_port_state[port] &= ~(PORT_STATUS_LSDA & ack_flag);
5040 hubd->h_log_handle, "port%d "
5043 hubd->h_port_state[port] |=
5047 hubd->h_log_handle, "port%d "
5050 hubd->h_port_state[port] &=
5059 mutex_exit(HUBD_MUTEX(hubd));
5061 USB_DPRINTF_L3(DPRINT_MASK_PORT, hubd->h_log_handle,
5063 if ((rval = usb_pipe_sync_ctrl_xfer(hubd->h_dip,
5064 hubd->h_default_pipe,
5073 hubd->h_log_handle,
5080 USB_DPRINTF_L3(DPRINT_MASK_PORT, hubd->h_log_handle,
5082 if ((rval = usb_pipe_sync_ctrl_xfer(hubd->h_dip,
5083 hubd->h_default_pipe,
5092 hubd->h_log_handle,
5099 USB_DPRINTF_L3(DPRINT_MASK_PORT, hubd->h_log_handle,
5102 if ((rval = usb_pipe_sync_ctrl_xfer(hubd->h_dip,
5103 hubd->h_default_pipe,
5112 hubd->h_log_handle,
5119 USB_DPRINTF_L3(DPRINT_MASK_PORT, hubd->h_log_handle,
5122 if ((rval = usb_pipe_sync_ctrl_xfer(hubd->h_dip,
5123 hubd->h_default_pipe,
5132 hubd->h_log_handle,
5139 USB_DPRINTF_L3(DPRINT_MASK_PORT, hubd->h_log_handle,
5141 if ((rval = usb_pipe_sync_ctrl_xfer(hubd->h_dip,
5142 hubd->h_default_pipe,
5151 hubd->h_log_handle,
5157 mutex_enter(HUBD_MUTEX(hubd));
5160 USB_DPRINTF_L4(DPRINT_MASK_PORT, hubd->h_log_handle,
5161 "new port%d state 0x%x", port, hubd->h_port_state[port]);
5175 hubd_recover_disabled_port(hubd_t *hubd, usb_port_t port)
5182 (void) hubd_enable_port(hubd, port);
5185 (void) hubd_determine_port_status(hubd, port, &status, &change,
5189 USB_DPRINTF_L3(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
5193 mutex_exit(HUBD_MUTEX(hubd));
5194 hubd_post_event(hubd, port, USBA_EVENT_TAG_HOT_REMOVAL);
5195 mutex_enter(HUBD_MUTEX(hubd));
5198 rval = hubd_handle_port_connect(hubd, port);
5200 USB_DPRINTF_L3(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
5212 hubd_enable_all_port_power(hubd_t *hubd)
5221 USB_DPRINTF_L4(DPRINT_MASK_PORT, hubd->h_log_handle,
5224 ASSERT(mutex_owned(HUBD_MUTEX(hubd)));
5226 hub_descr = &hubd->h_hub_descr;
5244 USB_DPRINTF_L4(DPRINT_MASK_PORT, hubd->h_log_handle,
5258 hubd->h_log_handle,
5261 (void) hubd_enable_port_power(hubd, port);
5264 mutex_exit(HUBD_MUTEX(hubd));
5266 mutex_enter(HUBD_MUTEX(hubd));
5275 (void) hubd_determine_port_status(hubd, port,
5281 USB_DPRINTF_L2(DPRINT_MASK_PORT, hubd->h_log_handle,
5285 (void) hubd_enable_port_power(hubd, port);
5287 mutex_exit(HUBD_MUTEX(hubd));
5289 mutex_enter(HUBD_MUTEX(hubd));
5292 (void) hubd_determine_port_status(hubd, port,
5299 USB_DPRINTF_L2(DPRINT_MASK_PORT, hubd->h_log_handle,
5314 hubd_enable_port_power(hubd_t *hubd, usb_port_t port)
5320 USB_DPRINTF_L4(DPRINT_MASK_PORT, hubd->h_log_handle,
5323 ASSERT(mutex_owned(HUBD_MUTEX(hubd)));
5324 ASSERT(hubd->h_default_pipe != 0);
5326 mutex_exit(HUBD_MUTEX(hubd));
5328 if ((rval = usb_pipe_sync_ctrl_xfer(hubd->h_dip,
5329 hubd->h_default_pipe,
5336 USB_DPRINTF_L2(DPRINT_MASK_PORT, hubd->h_log_handle,
5339 mutex_enter(HUBD_MUTEX(hubd));
5343 mutex_enter(HUBD_MUTEX(hubd));
5344 hubd->h_port_state[port] |= PORT_STATUS_PPS;
5355 hubd_disable_all_port_power(hubd_t *hubd)
5359 USB_DPRINTF_L4(DPRINT_MASK_PORT, hubd->h_log_handle,
5362 ASSERT(mutex_owned(HUBD_MUTEX(hubd)));
5367 for (port = 1; port <= hubd->h_hub_descr.bNbrPorts; port++) {
5368 (void) hubd_disable_port_power(hubd, port);
5380 hubd_disable_port_power(hubd_t *hubd, usb_port_t port)
5386 USB_DPRINTF_L4(DPRINT_MASK_PORT, hubd->h_log_handle,
5389 ASSERT(mutex_owned(HUBD_MUTEX(hubd)));
5391 mutex_exit(HUBD_MUTEX(hubd));
5393 if ((rval = usb_pipe_sync_ctrl_xfer(hubd->h_dip,
5394 hubd->h_default_pipe,
5401 USB_DPRINTF_L2(DPRINT_MASK_PORT, hubd->h_log_handle,
5405 mutex_enter(HUBD_MUTEX(hubd));
5410 mutex_enter(HUBD_MUTEX(hubd));
5412 hubd->h_port_state[port] &= ~PORT_STATUS_PPS;
5424 hubd_select_device_configuration(hubd_t *hubd, usb_port_t port,
5451 USB_DPRINTF_L3(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
5464 USB_DPRINTF_L3(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
5479 USB_DPRINTF_L2(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
5500 hubd_get_this_config_cloud(hubd_t *hubd, dev_info_t *dip,
5512 USB_DPRINTF_L4(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
5539 USB_DPRINTF_L2(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
5559 hubd->h_log_handle,
5569 hubd->h_log_handle,
5597 hubd->h_log_handle,
5625 hubd->h_log_handle,
5649 hubd->h_log_handle,
5664 USB_DPRINTF_L2(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
5687 hubd_get_all_device_config_cloud(hubd_t *hubd, dev_info_t *dip,
5698 USB_DPRINTF_L4(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
5723 rval = hubd_get_this_config_cloud(hubd, dip, child_ud,
5739 hubd_ready_device(hubd_t *hubd, dev_info_t *child_dip, usba_device_t *child_ud,
5749 USB_DPRINTF_L4(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
5823 hubd_t *hubd,
5848 USB_DPRINTF_L4(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
5851 ASSERT(mutex_owned(HUBD_MUTEX(hubd)));
5852 ASSERT(hubd->h_usba_devices[port] == NULL);
5854 mutex_exit(HUBD_MUTEX(hubd));
5870 USB_DPRINTF_L2(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
5879 parent_ud = hubd->h_usba_device;
5917 USB_DPRINTF_L2(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
5926 USB_DPRINTF_L4(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
5950 USB_DPRINTF_L4(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
5963 USB_DPRINTF_L2(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
5980 USB_DPRINTF_L4(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
5987 USB_DPRINTF_L2(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
5994 USB_DPRINTF_L2(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
6010 USB_DPRINTF_L2(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
6019 USB_DPRINTF_L3(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
6048 USB_DPRINTF_L2(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
6059 USB_DPRINTF_L3(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
6075 hubd->h_log_handle,
6100 hubd->h_log_handle,
6115 USB_DPRINTF_L4(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
6126 USB_DPRINTF_L2(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
6145 USB_DPRINTF_L2(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
6169 rval = hubd_get_all_device_config_cloud(hubd, child_dip, child_ud);
6171 USB_DPRINTF_L2(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
6178 user_conf_index = hubd_select_device_configuration(hubd, port,
6184 USB_DPRINTF_L2(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
6234 hubd->h_log_handle,
6272 child_dip = hubd_ready_device(hubd, child_dip,
6279 mutex_enter(HUBD_MUTEX(hubd));
6280 hubd->h_children_dips[port] = child_dip;
6281 mutex_exit(HUBD_MUTEX(hubd));
6295 child_dip = hubd_ready_device(hubd, child_dip,
6302 mutex_enter(HUBD_MUTEX(hubd));
6303 hubd->h_children_dips[port] = child_dip;
6304 mutex_exit(HUBD_MUTEX(hubd));
6340 child_dip = hubd_ready_device(hubd, child_dip,
6342 mutex_enter(HUBD_MUTEX(hubd));
6343 hubd->h_children_dips[port] = child_dip;
6344 mutex_exit(HUBD_MUTEX(hubd));
6355 child_dip = hubd_ready_device(hubd, child_dip,
6362 mutex_enter(HUBD_MUTEX(hubd));
6363 hubd->h_children_dips[port] = child_dip;
6364 mutex_exit(HUBD_MUTEX(hubd));
6371 mutex_enter(HUBD_MUTEX(hubd));
6372 if (hubd->h_usba_devices[port] == NULL) {
6373 hubd->h_usba_devices[port] = usba_get_usba_device(child_dip);
6375 ASSERT(hubd->h_usba_devices[port] ==
6383 USB_DPRINTF_L3(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
6386 mutex_enter(HUBD_MUTEX(hubd));
6387 hubd->h_children_dips[port] = NULL;
6388 mutex_exit(HUBD_MUTEX(hubd));
6403 USB_DPRINTF_L2(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
6415 mutex_enter(HUBD_MUTEX(hubd));
6416 if (hubd->h_usba_devices[port] == NULL) {
6417 mutex_exit(HUBD_MUTEX(hubd));
6420 hubd_free_usba_device(hubd, hubd->h_usba_devices[port]);
6421 mutex_exit(HUBD_MUTEX(hubd));
6425 mutex_enter(HUBD_MUTEX(hubd));
6438 hubd_delete_child(hubd_t *hubd, usb_port_t port, uint_t flag, boolean_t retry)
6444 child_dip = hubd->h_children_dips[port];
6445 usba_device = hubd->h_usba_devices[port];
6447 USB_DPRINTF_L4(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
6451 mutex_exit(HUBD_MUTEX(hubd));
6453 USB_DPRINTF_L2(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
6459 usba_hubdi_incr_power_budget(hubd->h_dip, usba_device);
6470 mutex_enter(HUBD_MUTEX(hubd));
6471 if (hubd->h_children_dips[port] == child_dip) {
6473 hubd->h_usba_devices[port];
6474 hubd->h_children_dips[port] = NULL;
6476 mutex_exit(HUBD_MUTEX(hubd));
6483 mutex_enter(HUBD_MUTEX(hubd));
6484 hubd->h_usba_devices[port] = NULL;
6487 mutex_exit(HUBD_MUTEX(hubd));
6495 mutex_enter(HUBD_MUTEX(hubd));
6507 hubd_free_usba_device(hubd_t *hubd, usba_device_t *usba_device)
6509 USB_DPRINTF_L4(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
6510 "hubd_free_usba_device: hubd=0x%p, usba_device=0x%p",
6511 (void *)hubd, (void *)usba_device);
6515 dev_info_t *dip = hubd->h_children_dips[port];
6524 hubd->h_usba_devices[port] = NULL;
6526 mutex_exit(HUBD_MUTEX(hubd));
6528 mutex_enter(HUBD_MUTEX(hubd));
6544 hubd_t *hubd = (hubd_t *)hubd_get_soft_state(dip);
6546 USB_DPRINTF_L3(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
6549 USB_DPRINTF_L3(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
6555 return (ndi_event_retrieve_cookie(hubd->h_ndi_event_hdl,
6569 hubd_t *hubd = (hubd_t *)hubd_get_soft_state(dip);
6570 usb_port_t port = hubd_child_dip2port(hubd, rdip);
6572 USB_DPRINTF_L3(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
6576 USB_DPRINTF_L3(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
6580 ndi_event_cookie_to_name(hubd->h_ndi_event_hdl, cookie));
6583 switch (ndi_event_cookie_to_tag(hubd->h_ndi_event_hdl, cookie)) {
6585 mutex_enter(HUBD_MUTEX(hubd));
6586 hubd->h_child_events[port] |= HUBD_CHILD_EVENT_DISCONNECT;
6587 mutex_exit(HUBD_MUTEX(hubd));
6591 mutex_enter(HUBD_MUTEX(hubd));
6592 hubd->h_child_events[port] |= HUBD_CHILD_EVENT_PRESUSPEND;
6593 mutex_exit(HUBD_MUTEX(hubd));
6602 return (ndi_event_add_callback(hubd->h_ndi_event_hdl,
6610 hubd_t *hubd = (hubd_t *)hubd_get_soft_state(dip);
6613 USB_DPRINTF_L3(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
6617 USB_DPRINTF_L3(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
6622 ndi_event_cookie_to_name(hubd->h_ndi_event_hdl,
6626 return (ndi_event_remove_callback(hubd->h_ndi_event_hdl, cb_id));
6637 hubd_do_callback(hubd_t *hubd, dev_info_t *cdip, ddi_eventcookie_t cookie)
6639 USB_DPRINTF_L4(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
6642 (void) ndi_event_do_callback(hubd->h_ndi_event_hdl, cdip, cookie, NULL);
6651 hubd_run_callbacks(hubd_t *hubd, usba_event_t type)
6655 USB_DPRINTF_L4(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
6658 mutex_enter(HUBD_MUTEX(hubd));
6659 for (port = 1; port <= hubd->h_hub_descr.bNbrPorts; port++) {
6665 if (hubd->h_children_dips[port]) {
6666 mutex_exit(HUBD_MUTEX(hubd));
6667 hubd_post_event(hubd, port, type);
6668 mutex_enter(HUBD_MUTEX(hubd));
6671 mutex_exit(HUBD_MUTEX(hubd));
6680 hubd_post_event(hubd_t *hubd, usb_port_t port, usba_event_t type)
6687 USB_DPRINTF_L3(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
6689 ndi_event_tag_to_name(hubd->h_ndi_event_hdl, type));
6691 cookie = ndi_event_tag_to_cookie(hubd->h_ndi_event_hdl, type);
6692 rm_cookie = ndi_event_tag_to_cookie(hubd->h_ndi_event_hdl,
6694 suspend_cookie = ndi_event_tag_to_cookie(hubd->h_ndi_event_hdl,
6703 mutex_enter(HUBD_MUTEX(hubd));
6704 dip = hubd->h_children_dips[port];
6705 usba_device = hubd->h_usba_devices[port];
6706 mutex_exit(HUBD_MUTEX(hubd));
6711 mutex_enter(HUBD_MUTEX(hubd));
6712 hubd->h_child_events[port] &= ~HUBD_CHILD_EVENT_DISCONNECT;
6713 mutex_exit(HUBD_MUTEX(hubd));
6715 hubd_do_callback(hubd, dip, cookie);
6729 mutex_enter(HUBD_MUTEX(hubd));
6730 hubd->h_child_events[port] &= ~HUBD_CHILD_EVENT_PRESUSPEND;
6731 mutex_exit(HUBD_MUTEX(hubd));
6733 hubd_do_callback(hubd, dip, cookie);
6745 mutex_enter(HUBD_MUTEX(hubd));
6746 if (hubd->h_child_events[port] & HUBD_CHILD_EVENT_DISCONNECT) {
6748 hubd->h_child_events[port] &=
6750 mutex_exit(HUBD_MUTEX(hubd));
6751 hubd_do_callback(hubd, dip, rm_cookie);
6753 mutex_enter(HUBD_MUTEX(hubd));
6755 mutex_exit(HUBD_MUTEX(hubd));
6768 hubd->h_log_handle,
6772 hubd_do_callback(hubd, dip, cookie);
6780 mutex_enter(HUBD_MUTEX(hubd));
6781 hubd->h_child_events[port] |= HUBD_CHILD_EVENT_DISCONNECT;
6782 mutex_exit(HUBD_MUTEX(hubd));
6790 mutex_enter(HUBD_MUTEX(hubd));
6791 if (hubd->h_child_events[port] & HUBD_CHILD_EVENT_PRESUSPEND) {
6793 hubd->h_port_state[port] &=
6795 mutex_exit(HUBD_MUTEX(hubd));
6796 hubd_do_callback(hubd, dip, suspend_cookie);
6797 mutex_enter(HUBD_MUTEX(hubd));
6799 mutex_exit(HUBD_MUTEX(hubd));
6810 hubd_do_callback(hubd, dip, cookie);
6817 mutex_enter(HUBD_MUTEX(hubd));
6818 hubd->h_child_events[port] |= HUBD_CHILD_EVENT_PRESUSPEND;
6819 mutex_exit(HUBD_MUTEX(hubd));
6831 hubd_t *hubd = (hubd_t *)hubd_get_soft_state(dip);
6837 USB_DPRINTF_L4(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
6842 mutex_enter(HUBD_MUTEX(hubd));
6843 switch (hubd->h_dev_state) {
6846 hubd->h_dev_state = USB_DEV_DISCONNECTED;
6848 hubd_stop_polling(hubd);
6853 mutex_exit(HUBD_MUTEX(hubd));
6854 hubd_run_callbacks(hubd, tag);
6855 mutex_enter(HUBD_MUTEX(hubd));
6858 nports = hubd->h_hub_descr.bNbrPorts;
6860 usba_dev = hubd->h_usba_devices[port];
6862 mutex_exit(HUBD_MUTEX(hubd));
6864 mutex_enter(HUBD_MUTEX(hubd));
6871 USB_DPRINTF_L2(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
6876 USB_DPRINTF_L2(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
6878 hubd->h_dev_state);
6882 mutex_exit(HUBD_MUTEX(hubd));
6911 hubd_t *hubd = (hubd_t *)hubd_get_soft_state(dip);
6913 USB_DPRINTF_L4(DPRINT_MASK_EVENTS, hubd->h_log_handle,
6917 mutex_enter(HUBD_MUTEX(hubd));
6918 hubd->h_hotplug_thread++;
6919 hubd_stop_polling(hubd);
6922 (void) hubd_pm_busy_component(hubd, hubd->h_dip, 0);
6923 mutex_exit(HUBD_MUTEX(hubd));
6926 hubd_run_callbacks(hubd, USBA_EVENT_TAG_PRE_SUSPEND);
6941 hubd_t *hubd = (hubd_t *)hubd_get_soft_state(dip);
6943 USB_DPRINTF_L4(DPRINT_MASK_EVENTS, hubd->h_log_handle,
6947 hubd_run_callbacks(hubd, USBA_EVENT_TAG_POST_RESUME);
6950 mutex_enter(HUBD_MUTEX(hubd));
6953 (void) hubd_pm_idle_component(hubd, hubd->h_dip, 0);
6956 hubd->h_hotplug_thread--;
6959 hubd_start_polling(hubd, 0);
6960 mutex_exit(HUBD_MUTEX(hubd));
6971 hubd_cpr_suspend(hubd_t *hubd)
6978 USB_DPRINTF_L4(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
6982 mutex_enter(HUBD_MUTEX(hubd));
6983 hubd_pm_busy_component(hubd, hubd->h_dip, 0);
6984 mutex_exit(HUBD_MUTEX(hubd));
6987 (void) pm_raise_power(hubd->h_dip, 0, USB_DEV_OS_FULL_PWR);
6988 mutex_enter(HUBD_MUTEX(hubd));
6990 switch (hubd->h_dev_state) {
6995 nports = hubd->h_hub_descr.bNbrPorts;
6997 usba_dev = hubd->h_usba_devices[port];
7005 USB_DPRINTF_L2(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
7015 if ((hubd->h_hotplug_thread > 1) ||
7016 (hubd->h_cleanup_active == B_TRUE)) {
7018 hubd->h_log_handle,
7026 hubd_stop_polling(hubd);
7030 usba_dev = hubd->h_usba_devices[port];
7032 mutex_exit(HUBD_MUTEX(hubd));
7034 if (hubd_suspend_port(hubd, port)) {
7037 hubd->h_log_handle,
7041 mutex_enter(HUBD_MUTEX(hubd));
7045 hubd->h_dev_state = USB_DEV_SUSPENDED;
7051 if (usba_is_root_hub(hubd->h_dip)) {
7052 mutex_exit(HUBD_MUTEX(hubd));
7054 usba_get_usba_device(hubd->h_dip));
7055 mutex_enter(HUBD_MUTEX(hubd));
7063 USB_DPRINTF_L2(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
7065 hubd->h_dev_state);
7070 hubd_pm_idle_component(hubd, hubd->h_dip, 0);
7071 mutex_exit(HUBD_MUTEX(hubd));
7103 hubd_t *hubd = (hubd_t *)hubd_get_soft_state(dip);
7105 USB_DPRINTF_L3(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
7109 hubd_restore_device_state(dip, hubd);
7119 hubd_register_events(hubd_t *hubd)
7123 if (usba_is_root_hub(hubd->h_dip)) {
7124 hubd_register_cpr_callback(hubd);
7126 rval = usb_register_event_cbs(hubd->h_dip, &hubd_events, 0);
7134 * hubd cpr callback related functions
7146 hubd_t *hubd = cpr_cb->statep;
7149 USB_DPRINTF_L4(DPRINT_MASK_EVENTS, hubd->h_log_handle,
7154 USB_DPRINTF_L3(DPRINT_MASK_EVENTS, hubd->h_log_handle,
7157 mutex_enter(HUBD_MUTEX(hubd));
7160 hubd->h_cleanup_enabled = B_FALSE;
7163 while ((hubd->h_cleanup_active == B_TRUE) && (retry++ < 3)) {
7164 mutex_exit(HUBD_MUTEX(hubd));
7167 USB_DPRINTF_L2(DPRINT_MASK_EVENTS, hubd->h_log_handle,
7170 mutex_enter(HUBD_MUTEX(hubd));
7173 mutex_exit(HUBD_MUTEX(hubd));
7176 (void) hubd_pre_suspend_event_cb(hubd->h_dip);
7180 USB_DPRINTF_L3(DPRINT_MASK_EVENTS, hubd->h_log_handle,
7184 (void) hubd_post_resume_event_cb(hubd->h_dip);
7187 mutex_enter(HUBD_MUTEX(hubd));
7188 hubd->h_cleanup_enabled = B_TRUE;
7189 mutex_exit(HUBD_MUTEX(hubd));
7191 hubd_schedule_cleanup(hubd->h_usba_device->usb_root_hub_dip);
7204 hubd_register_cpr_callback(hubd_t *hubd)
7206 USB_DPRINTF_L4(DPRINT_MASK_EVENTS, hubd->h_log_handle,
7209 mutex_enter(HUBD_MUTEX(hubd));
7210 hubd->h_cpr_cb =
7212 mutex_exit(HUBD_MUTEX(hubd));
7213 mutex_init(&hubd->h_cpr_cb->lockp, NULL, MUTEX_DRIVER,
7214 hubd->h_dev_data->dev_iblock_cookie);
7215 hubd->h_cpr_cb->statep = hubd;
7216 hubd->h_cpr_cb->cpr.cc_lockp = &hubd->h_cpr_cb->lockp;
7217 hubd->h_cpr_cb->cpr.cc_id = callb_add(hubd_cpr_post_user_callb,
7218 (void *)hubd->h_cpr_cb, CB_CL_CPR_POST_USER, "hubd");
7224 hubd_unregister_cpr_callback(hubd_t *hubd)
7226 USB_DPRINTF_L4(DPRINT_MASK_EVENTS, hubd->h_log_handle,
7229 if (hubd->h_cpr_cb) {
7230 (void) callb_delete(hubd->h_cpr_cb->cpr.cc_id);
7231 mutex_destroy(&hubd->h_cpr_cb->lockp);
7232 mutex_enter(HUBD_MUTEX(hubd));
7233 kmem_free(hubd->h_cpr_cb, sizeof (hubd_cpr_t));
7234 mutex_exit(HUBD_MUTEX(hubd));
7245 hubd_create_pm_components(dev_info_t *dip, hubd_t *hubd)
7249 USB_DPRINTF_L4(DPRINT_MASK_PM, hubd->h_log_handle,
7255 hubd->h_hubpm = hubpm;
7256 hubpm->hubp_hubd = hubd;
7277 USB_DPRINTF_L2(DPRINT_MASK_PM, hubd->h_log_handle,
7283 mutex_enter(HUBD_MUTEX(hubd));
7288 hubd_pm_busy_component(hubd, dip, 0);
7289 mutex_exit(HUBD_MUTEX(hubd));
7297 USB_DPRINTF_L4(DPRINT_MASK_PM, hubd->h_log_handle,
7310 hubd_t *hubd;
7315 hubd = hubd_get_soft_state(dip);
7316 if (hubd == NULL) {
7320 USB_DPRINTF_L4(DPRINT_MASK_CBOPS, hubd->h_log_handle,
7323 mutex_enter(HUBD_MUTEX(hubd));
7324 if ((flags & FEXCL) && (hubd->h_softstate & HUBD_SS_ISOPEN)) {
7325 mutex_exit(HUBD_MUTEX(hubd));
7330 hubd->h_softstate |= HUBD_SS_ISOPEN;
7331 mutex_exit(HUBD_MUTEX(hubd));
7333 USB_DPRINTF_L4(DPRINT_MASK_CBOPS, hubd->h_log_handle, "opened");
7344 hubd_t *hubd;
7350 hubd = hubd_get_soft_state(dip);
7352 if (hubd == NULL) {
7356 USB_DPRINTF_L4(DPRINT_MASK_CBOPS, hubd->h_log_handle, "hubd_close:");
7358 mutex_enter(HUBD_MUTEX(hubd));
7359 hubd->h_softstate &= ~HUBD_SS_ISOPEN;
7360 mutex_exit(HUBD_MUTEX(hubd));
7362 USB_DPRINTF_L4(DPRINT_MASK_CBOPS, hubd->h_log_handle, "closed");
7378 hubd_t *hubd;
7387 if ((hubd = hubd_get_soft_state(self)) == NULL) {
7392 rh_dip = hubd->h_usba_device->usb_root_hub_dip;
7394 USB_DPRINTF_L4(DPRINT_MASK_CBOPS, hubd->h_log_handle,
7411 mutex_enter(HUBD_MUTEX(hubd));
7417 if (hubd->h_dev_state == USB_DEV_DISCONNECTED) {
7418 USB_DPRINTF_L2(DPRINT_MASK_ATTA, hubd->h_log_handle,
7419 "hubd: already gone");
7420 mutex_exit(HUBD_MUTEX(hubd));
7430 if ((port = hubd_get_port_num(hubd, dcp)) == 0) {
7431 USB_DPRINTF_L2(DPRINT_MASK_ATTA, hubd->h_log_handle,
7432 "hubd: bad port");
7433 mutex_exit(HUBD_MUTEX(hubd));
7446 mutex_exit(HUBD_MUTEX(hubd));
7455 if (hubd->h_dev_state == USB_DEV_SUSPENDED) {
7456 mutex_exit(HUBD_MUTEX(hubd));
7464 if (hubd->h_reset_port[port]) {
7465 USB_DPRINTF_L2(DPRINT_MASK_CBOPS, hubd->h_log_handle,
7467 mutex_exit(HUBD_MUTEX(hubd));
7475 hubd_pm_busy_component(hubd, hubd->h_dip, 0);
7476 mutex_exit(HUBD_MUTEX(hubd));
7479 (void) pm_raise_power(hubd->h_dip, 0, USB_DEV_OS_FULL_PWR);
7483 ndi_devi_enter(hubd->h_dip, &circ);
7485 mutex_enter(HUBD_MUTEX(hubd));
7487 hubd->h_hotplug_thread++;
7490 if (hubd->h_ep1_ph) {
7491 mutex_exit(HUBD_MUTEX(hubd));
7492 (void) usb_pipe_get_state(hubd->h_ep1_ph, &prev_pipe_state,
7494 mutex_enter(HUBD_MUTEX(hubd));
7497 hubd_stop_polling(hubd);
7503 if (hubd_delete_child(hubd, port,
7510 if (hubd_delete_child(hubd, port,
7518 if (hubd_toggle_port(hubd, port) != USB_SUCCESS) {
7524 (void) hubd_handle_port_connect(hubd, port);
7525 child_dip = hubd_get_child_dip(hubd, port);
7526 mutex_exit(HUBD_MUTEX(hubd));
7528 ndi_devi_exit(hubd->h_dip, circ);
7541 ndi_devi_enter(hubd->h_dip, &circ);
7543 mutex_enter(HUBD_MUTEX(hubd));
7547 switch (hubd_cfgadm_state(hubd, port)) {
7586 USB_DPRINTF_L4(DPRINT_MASK_CBOPS, hubd->h_log_handle,
7632 USB_DPRINTF_L3(DPRINT_MASK_CBOPS, hubd->h_log_handle,
7658 hubd->h_log_handle,
7668 if ((child_dip = hubd_get_child_dip(hubd,
7678 hubd->h_log_handle,
7690 hubd->h_log_handle,
7705 USB_DPRINTF_L4(DPRINT_MASK_CBOPS, hubd->h_log_handle,
7709 if ((child_dip = hubd_get_child_dip(hubd, ioc.port)) ==
7739 hubd->h_log_handle,
7756 hubd->h_log_handle,
7765 hubd->h_log_handle,
7774 hubd->h_log_handle,
7784 hubd->h_log_handle,
7799 if ((child_dip = hubd_get_child_dip(hubd, ioc.port)) ==
7812 USB_DPRINTF_L4(DPRINT_MASK_CBOPS, hubd->h_log_handle,
7819 hubd->h_log_handle,
7828 hubd->h_log_handle,
7838 hubd->h_log_handle,
7860 USB_DPRINTF_L4(DPRINT_MASK_CBOPS, hubd->h_log_handle,
7868 if ((child_dip = hubd_get_child_dip(hubd, ioc.port)) ==
7884 hubd->h_log_handle,
7893 hubd->h_log_handle,
7902 hubd->h_log_handle,
7916 USB_DPRINTF_L4(DPRINT_MASK_CBOPS, hubd->h_log_handle,
7920 if ((child_dip = hubd_get_child_dip(hubd, ioc.port)) ==
7933 USB_DPRINTF_L4(DPRINT_MASK_CBOPS, hubd->h_log_handle,
7941 hubd->h_log_handle,
7948 hubd->h_log_handle,
7954 hubd->h_log_handle,
7965 USB_DPRINTF_L3(DPRINT_MASK_CBOPS, hubd->h_log_handle,
7970 hubd->h_log_handle,
7992 hubd->h_hotplug_thread--;
7994 if ((hubd->h_dev_state == USB_DEV_ONLINE) &&
7995 hubd->h_ep1_ph && (prev_pipe_state == USB_PIPE_STATE_ACTIVE)) {
7996 hubd_start_polling(hubd, 0);
7998 mutex_exit(HUBD_MUTEX(hubd));
8000 ndi_devi_exit(hubd->h_dip, circ);
8004 mutex_enter(HUBD_MUTEX(hubd));
8005 hubd_pm_idle_component(hubd, hubd->h_dip, 0);
8006 mutex_exit(HUBD_MUTEX(hubd));
8027 hubd_get_ancestry_str(hubd_t *hubd)
8034 USB_DPRINTF_L4(DPRINT_MASK_ATTA, hubd->h_log_handle,
8035 "hubd_get_ancestry_str: hubd=0x%p", (void *)hubd);
8037 ASSERT(mutex_owned(HUBD_MUTEX(hubd)));
8047 if (usba_is_root_hub(hubd->h_dip)) {
8048 hubd->h_ancestry_str[0] = '\0';
8050 port = hubd->h_usba_device->usb_port;
8051 mutex_exit(HUBD_MUTEX(hubd));
8053 pdip = ddi_get_parent(hubd->h_dip);
8070 mutex_enter(HUBD_MUTEX(hubd));
8071 (void) strcpy(hubd->h_ancestry_str, ap_name);
8072 (void) strcat(hubd->h_ancestry_str, ".");
8079 hubd_get_port_num(hubd_t *hubd, struct devctl_iocdata *dcp)
8083 ASSERT(mutex_owned(HUBD_MUTEX(hubd)));
8087 USB_DPRINTF_L2(DPRINT_MASK_CBOPS, hubd->h_log_handle,
8092 USB_DPRINTF_L4(DPRINT_MASK_CBOPS, hubd->h_log_handle,
8093 "hubd_get_port_num: hubd=0x%p, port=%d", (void *)hubd, port);
8101 hubd_get_child_dip(hubd_t *hubd, usb_port_t port)
8103 dev_info_t *child_dip = hubd->h_children_dips[port];
8105 USB_DPRINTF_L4(DPRINT_MASK_CBOPS, hubd->h_log_handle,
8106 "hubd_get_child_dip: hubd=0x%p, port=%d", (void *)hubd, port);
8108 ASSERT(mutex_owned(HUBD_MUTEX(hubd)));
8127 hubd_cfgadm_state(hubd_t *hubd, usb_port_t port)
8130 dev_info_t *child_dip = hubd_get_child_dip(hubd, port);
8133 if (hubd->h_port_state[port] & PORT_STATUS_CCS) {
8155 if (hubd->h_port_state[port] & PORT_STATUS_CCS) {
8164 USB_DPRINTF_L4(DPRINT_MASK_CBOPS, hubd->h_log_handle,
8165 "hubd_cfgadm_state: hubd=0x%p, port=%d state=0x%x",
8166 (void *)hubd, port, state);
8176 hubd_toggle_port(hubd_t *hubd, usb_port_t port)
8184 USB_DPRINTF_L4(DPRINT_MASK_CBOPS, hubd->h_log_handle,
8185 "hubd_toggle_port: hubd=0x%p, port=%d", (void *)hubd, port);
8187 if ((hubd_disable_port_power(hubd, port)) != USB_SUCCESS) {
8196 mutex_exit(HUBD_MUTEX(hubd));
8198 mutex_enter(HUBD_MUTEX(hubd));
8200 hub_descr = &hubd->h_hub_descr;
8218 USB_DPRINTF_L3(DPRINT_MASK_PORT, hubd->h_log_handle,
8225 (void) hubd_enable_port_power(hubd, port);
8227 mutex_exit(HUBD_MUTEX(hubd));
8229 mutex_enter(HUBD_MUTEX(hubd));
8232 (void) hubd_determine_port_status(hubd, port,
8245 USB_DPRINTF_L2(DPRINT_MASK_PORT, hubd->h_log_handle,
8258 * Init power budget variables in hubd structure. According
8270 hubd_init_power_budget(hubd_t *hubd)
8279 if (hubd->h_ignore_pwr_budget) {
8284 USB_DPRINTF_L4(DPRINT_MASK_HUB, hubd->h_log_handle,
8287 ASSERT(mutex_owned(HUBD_MUTEX(hubd)));
8288 ASSERT(hubd->h_default_pipe != 0);
8289 mutex_exit(HUBD_MUTEX(hubd));
8292 if ((usb_get_status(hubd->h_dip, hubd->h_default_pipe,
8295 mutex_enter(HUBD_MUTEX(hubd));
8300 hubd_ud = usba_get_usba_device(hubd->h_dip);
8306 USB_DPRINTF_L2(DPRINT_MASK_HUB, hubd->h_log_handle,
8308 mutex_enter(HUBD_MUTEX(hubd));
8313 mutex_enter(HUBD_MUTEX(hubd));
8315 hubd->h_local_pwr_capable = (cfg_descr.bmAttributes &
8318 if (hubd->h_local_pwr_capable) {
8319 USB_DPRINTF_L3(DPRINT_MASK_HUB, hubd->h_log_handle,
8323 hubd->h_local_pwr_on = (status &
8324 USB_DEV_SLF_PWRD_STATUS) && hubd->h_local_pwr_capable;
8326 if (hubd->h_local_pwr_on) {
8327 USB_DPRINTF_L3(DPRINT_MASK_HUB, hubd->h_log_handle,
8330 hubd->h_pwr_limit = (USB_PWR_UNIT_LOAD *
8333 hubd->h_pwr_limit = (USB_PWR_UNIT_LOAD *
8336 hubd->h_pwr_left = (USB_PWR_UNIT_LOAD *
8339 ASSERT(!usba_is_root_hub(hubd->h_dip));
8341 if (!usba_is_root_hub(hubd->h_dip)) {
8346 mutex_exit(HUBD_MUTEX(hubd));
8348 pdip = ddi_get_parent(hubd->h_dip);
8356 hubd->h_log_handle,
8361 mutex_enter(HUBD_MUTEX(hubd));
8368 mutex_enter(HUBD_MUTEX(hubd));
8370 USB_DPRINTF_L3(DPRINT_MASK_HUB, hubd->h_log_handle,
8373 USB_DPRINTF_L3(DPRINT_MASK_HUB, hubd->h_log_handle,
8382 hubd->h_pwr_left -=
8383 hubd->h_hub_descr.bHubContrCurrent /
8385 if (hubd->h_pwr_left < 0) {
8386 USB_DPRINTF_L2(DPRINT_MASK_HUB, hubd->h_log_handle,
8387 "hubd->h_pwr_left is less than bHubContrCurrent, "
8410 hubd_t *hubd;
8412 if ((hubd = hubd_get_soft_state(dip)) == NULL) {
8417 if (hubd->h_ignore_pwr_budget) {
8422 USB_DPRINTF_L4(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
8427 mutex_enter(HUBD_MUTEX(hubd));
8428 pwr_limit = hubd->h_pwr_limit;
8429 if (hubd->h_local_pwr_on == B_FALSE) {
8430 pwr_left = hubd->h_pwr_left;
8433 mutex_exit(HUBD_MUTEX(hubd));
8435 USB_DPRINTF_L3(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
8444 USB_DPRINTF_L2(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
8452 USB_DPRINTF_L3(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
8459 USB_DPRINTF_L1(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
8485 hubd_t *hubd = hubd_get_soft_state(dip);
8487 ASSERT(hubd != NULL);
8489 if (hubd->h_ignore_pwr_budget) {
8494 USB_DPRINTF_L4(DPRINT_MASK_ATTA, hubd->h_log_handle,
8498 mutex_enter(HUBD_MUTEX(hubd));
8499 if (hubd->h_local_pwr_on == B_TRUE) {
8500 USB_DPRINTF_L3(DPRINT_MASK_ATTA, hubd->h_log_handle,
8503 mutex_exit(HUBD_MUTEX(hubd));
8507 mutex_exit(HUBD_MUTEX(hubd));
8518 mutex_enter(HUBD_MUTEX(hubd));
8519 hubd->h_pwr_left += pwr_value;
8521 USB_DPRINTF_L3(DPRINT_MASK_ATTA, hubd->h_log_handle,
8524 hubd->h_pwr_left * USB_CFG_DESCR_PWR_UNIT,
8527 mutex_exit(HUBD_MUTEX(hubd));
8546 hubd_t *hubd = hubd_get_soft_state(dip);
8548 ASSERT(hubd != NULL);
8550 if (hubd->h_ignore_pwr_budget) {
8555 USB_DPRINTF_L4(DPRINT_MASK_ATTA, hubd->h_log_handle,
8559 mutex_enter(HUBD_MUTEX(hubd));
8560 if (hubd->h_local_pwr_on == B_TRUE) {
8561 USB_DPRINTF_L3(DPRINT_MASK_ATTA, hubd->h_log_handle,
8564 mutex_exit(HUBD_MUTEX(hubd));
8568 mutex_exit(HUBD_MUTEX(hubd));
8583 mutex_enter(HUBD_MUTEX(hubd));
8585 hubd->h_pwr_left -= pwr_value;
8586 ASSERT(hubd->h_pwr_left >= 0);
8588 USB_DPRINTF_L3(DPRINT_MASK_ATTA, hubd->h_log_handle,
8591 hubd->h_pwr_left * USB_CFG_DESCR_PWR_UNIT,
8594 mutex_exit(HUBD_MUTEX(hubd));
8606 hubd_wait_for_hotplug_exit(hubd_t *hubd)
8611 ASSERT(mutex_owned(HUBD_MUTEX(hubd)));
8613 if (hubd->h_hotplug_thread) {
8614 USB_DPRINTF_L3(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
8615 "waiting for hubd hotplug thread exit");
8616 rval = cv_reltimedwait(&hubd->h_cv_hotplug_dev,
8617 &hubd->h_mutex, until, TR_CLOCK_TICK);
8619 if ((rval <= 0) && (hubd->h_hotplug_thread)) {
8640 hubd_t *hubd = hd_arg->hubd;
8644 dev_info_t *hdip = hubd->h_dip;
8645 dev_info_t *rh_dip = hubd->h_usba_device->usb_root_hub_dip;
8653 USB_DPRINTF_L4(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
8658 mutex_enter(HUBD_MUTEX(hubd));
8660 child_dip = hubd->h_children_dips[reset_port];
8667 if (hubd->h_bus_pwr) {
8668 USB_DPRINTF_L0(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
8676 if (hubd_wait_for_hotplug_exit(hubd) == USB_FAILURE) {
8679 hubd->h_log_handle, "Time out when resetting the device"
8686 hubd->h_hotplug_thread++;
8690 (hubd->h_dev_state == USB_DEV_PWRED_DOWN)) {
8691 hubpm = hubd->h_hubpm;
8696 mutex_exit(HUBD_MUTEX(hubd));
8698 USB_DPRINTF_L3(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
8704 mutex_enter(HUBD_MUTEX(hubd));
8705 hubd->h_dev_state = USB_DEV_ONLINE;
8708 mutex_exit(HUBD_MUTEX(hubd));
8720 mutex_enter(HUBD_MUTEX(hubd));
8726 if (hubd->h_children_dips[reset_port]) {
8727 mutex_exit(HUBD_MUTEX(hubd));
8729 hubd_post_event(hubd, reset_port, USBA_EVENT_TAG_HOT_REMOVAL);
8750 mutex_enter(HUBD_MUTEX(hubd));
8751 rval = hubd_delete_child(hubd, reset_port,
8753 mutex_exit(HUBD_MUTEX(hubd));
8765 mutex_enter(HUBD_MUTEX(hubd));
8768 if ((rval != USB_SUCCESS) && (hubd_delete_child(hubd,
8770 USB_DPRINTF_L0(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
8776 mutex_exit(HUBD_MUTEX(hubd));
8778 hubd_post_event(hubd, reset_port,
8780 mutex_enter(HUBD_MUTEX(hubd));
8782 (void) hubd_determine_port_status(hubd, reset_port,
8785 /* Reset the parent hubd port and create new child */
8787 online_child |= (hubd_handle_port_connect(hubd,
8794 mutex_exit(HUBD_MUTEX(hubd));
8805 USB_DPRINTF_L3(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
8808 (void) ndi_devi_online(hubd->h_dip, 0);
8811 mutex_enter(HUBD_MUTEX(hubd));
8814 hubd->h_hotplug_thread--;
8816 hubd_start_polling(hubd, 0);
8819 (void) hubd_pm_idle_component(hubd, hubd->h_dip, 0);
8821 USB_DPRINTF_L4(DPRINT_MASK_HOTPLUG, hubd->h_log_handle,
8822 "hubd_reset_thread: exit, %d", hubd->h_hotplug_thread);
8824 hubd->h_reset_port[reset_port] = B_FALSE;
8826 mutex_exit(HUBD_MUTEX(hubd));
8838 hubd_check_same_device(hubd_t *hubd, usb_port_t port)
8840 dev_info_t *dip = hubd->h_children_dips[port];
8844 ASSERT(mutex_owned(HUBD_MUTEX(hubd)));
8846 mutex_exit(HUBD_MUTEX(hubd));
8856 hubd->h_log_handle, USB_LOG_L0,
8862 mutex_enter(HUBD_MUTEX(hubd));
8874 hubd_t *hubd;
8912 if ((hubd = hubd_get_soft_state(hdip)) == NULL) {
8919 mutex_enter(HUBD_MUTEX(hubd));
8922 if ((hubd->h_dev_state == USB_DEV_DISCONNECTED) ||
8923 (hubd->h_dev_state == USB_DEV_SUSPENDED)) {
8924 USB_DPRINTF_L2(DPRINT_MASK_ATTA, hubd->h_log_handle,
8927 hubd->h_dev_state, (void *)dip);
8928 mutex_exit(HUBD_MUTEX(hubd));
8933 mutex_exit(HUBD_MUTEX(hubd));
8935 port = hubd_child_dip2port(hubd, dip);
8937 mutex_enter(HUBD_MUTEX(hubd));
8939 if (hubd->h_reset_port[port]) {
8940 USB_DPRINTF_L2(DPRINT_MASK_ATTA, hubd->h_log_handle,
8942 mutex_exit(HUBD_MUTEX(hubd));
8953 usba_device = hubd->h_usba_devices[port];
8954 mutex_exit(HUBD_MUTEX(hubd));
8957 USB_DPRINTF_L2(DPRINT_MASK_ATTA, hubd->h_log_handle,
8970 USB_DPRINTF_L2(DPRINT_MASK_ATTA, hubd->h_log_handle,
8976 mutex_enter(HUBD_MUTEX(hubd));
8980 if (hubd->h_port_state[port] & HUBD_CHILD_DETACHING) {
8981 USB_DPRINTF_L2(DPRINT_MASK_ATTA, hubd->h_log_handle,
8984 mutex_exit(HUBD_MUTEX(hubd));
8989 hubd->h_reset_port[port] = B_TRUE;
8990 hdip = hubd->h_dip;
8991 mutex_exit(HUBD_MUTEX(hubd));
8996 mutex_enter(HUBD_MUTEX(hubd));
8997 hubd_pm_busy_component(hubd, hdip, 0);
8998 mutex_exit(HUBD_MUTEX(hubd));
9001 mutex_enter(HUBD_MUTEX(hubd));
9003 hubd->h_hotplug_thread++;
9006 if (hubd->h_ep1_ph) {
9007 mutex_exit(HUBD_MUTEX(hubd));
9008 (void) usb_pipe_get_state(hubd->h_ep1_ph, &prev_pipe_state,
9010 mutex_enter(HUBD_MUTEX(hubd));
9013 hubd_stop_polling(hubd);
9019 mutex_exit(HUBD_MUTEX(hubd));
9022 arg->hubd = hubd;
9024 mutex_enter(HUBD_MUTEX(hubd));
9028 hubd->h_hotplug_thread--;
9029 mutex_exit(HUBD_MUTEX(hubd));
9033 USB_DPRINTF_L2(DPRINT_MASK_ATTA, hubd->h_log_handle,
9048 if ((rval = hubd_handle_port_connect(hubd, port))
9050 mutex_exit(HUBD_MUTEX(hubd));
9053 mutex_enter(HUBD_MUTEX(hubd));
9056 hubd->h_log_handle, "failed to reopen "
9064 (void) hubd_disable_port(hubd, port);
9075 hubd->h_hotplug_thread--;
9077 if ((hubd->h_dev_state == USB_DEV_ONLINE) && hubd->h_ep1_ph &&
9079 hubd_start_polling(hubd, 0);
9082 hubd_pm_idle_component(hubd, hdip, 0);
9085 hubd->h_reset_port[port] = B_FALSE;
9087 mutex_exit(HUBD_MUTEX(hubd));