Print this page
xhci_Quiesce

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/io/usb/hcd/xhci/xhci.c
          +++ new/usr/src/uts/common/io/usb/hcd/xhci/xhci.c
↓ open down ↓ 1082 lines elided ↑ open up ↑
1083 1083  }
1084 1084  
1085 1085  static int
1086 1086  xhci_reg_poll(xhci_t *xhcip, xhci_reg_type_t rt, int reg, uint32_t mask,
1087 1087      uint32_t targ, uint_t tries, int delay_ms)
1088 1088  {
1089 1089          uint_t i;
1090 1090  
1091 1091          for (i = 0; i < tries; i++) {
1092 1092                  uint32_t val = xhci_get32(xhcip, rt, reg);
1093      -                if (xhci_check_regs_acc(xhcip) != DDI_FM_OK) {
     1093 +                if (!quiesce_active && xhci_check_regs_acc(xhcip)
     1094 +                    != DDI_FM_OK) {
1094 1095                          ddi_fm_service_impact(xhcip->xhci_dip,
1095 1096                              DDI_SERVICE_LOST);
1096 1097                          return (EIO);
1097 1098                  }
1098 1099  
1099 1100                  if ((val & mask) == targ)
1100 1101                          return (0);
1101 1102  
1102 1103                  delay(drv_usectohz(delay_ms * 1000));
1103 1104          }
↓ open down ↓ 462 lines elided ↑ open up ↑
1566 1567  
1567 1568          return (B_TRUE);
1568 1569  }
1569 1570  
1570 1571  static int
1571 1572  xhci_controller_stop(xhci_t *xhcip)
1572 1573  {
1573 1574          uint32_t cmdreg;
1574 1575  
1575 1576          cmdreg = xhci_get32(xhcip, XHCI_R_OPER, XHCI_USBCMD);
1576      -        if (xhci_check_regs_acc(xhcip) != DDI_FM_OK) {
     1577 +        if (!quiesce_active && xhci_check_regs_acc(xhcip) != DDI_FM_OK) {
1577 1578                  xhci_error(xhcip, "failed to read USB Command register: "
1578 1579                      "encountered fatal FM register error");
1579 1580                  ddi_fm_service_impact(xhcip->xhci_dip, DDI_SERVICE_LOST);
1580 1581                  return (EIO);
1581 1582          }
1582 1583  
1583 1584          cmdreg &= ~(XHCI_CMD_RS | XHCI_CMD_INTE);
1584 1585          xhci_put32(xhcip, XHCI_R_OPER, XHCI_USBCMD, cmdreg);
1585      -        if (xhci_check_regs_acc(xhcip) != DDI_FM_OK) {
     1586 +        if (!quiesce_active && xhci_check_regs_acc(xhcip) != DDI_FM_OK) {
1586 1587                  xhci_error(xhcip, "failed to write USB Command register: "
1587 1588                      "encountered fatal FM register error");
1588 1589                  ddi_fm_service_impact(xhcip->xhci_dip, DDI_SERVICE_LOST);
1589 1590                  return (EIO);
1590 1591          }
1591 1592  
1592 1593          /*
1593 1594           * Wait up to 50ms for this to occur. The specification says that this
1594 1595           * should stop within 16ms, but we give ourselves a bit more time just
1595 1596           * in case.
↓ open down ↓ 2 lines elided ↑ open up ↑
1598 1599              XHCI_STS_HCH, 50, 10));
1599 1600  }
1600 1601  
1601 1602  static int
1602 1603  xhci_controller_reset(xhci_t *xhcip)
1603 1604  {
1604 1605          int ret;
1605 1606          uint32_t cmdreg;
1606 1607  
1607 1608          cmdreg = xhci_get32(xhcip, XHCI_R_OPER, XHCI_USBCMD);
1608      -        if (xhci_check_regs_acc(xhcip) != DDI_FM_OK) {
     1609 +        if (!quiesce_active && xhci_check_regs_acc(xhcip) != DDI_FM_OK) {
1609 1610                  xhci_error(xhcip, "failed to read USB Command register for "
1610 1611                      "reset: encountered fatal FM register error");
1611 1612                  ddi_fm_service_impact(xhcip->xhci_dip, DDI_SERVICE_LOST);
1612 1613                  return (EIO);
1613 1614          }
1614 1615  
1615 1616          cmdreg |= XHCI_CMD_HCRST;
1616 1617          xhci_put32(xhcip, XHCI_R_OPER, XHCI_USBCMD, cmdreg);
1617      -        if (xhci_check_regs_acc(xhcip) != DDI_FM_OK) {
     1618 +        if (!quiesce_active && xhci_check_regs_acc(xhcip) != DDI_FM_OK) {
1618 1619                  xhci_error(xhcip, "failed to write USB Command register for "
1619 1620                      "reset: encountered fatal FM register error");
1620 1621                  ddi_fm_service_impact(xhcip->xhci_dip, DDI_SERVICE_LOST);
1621 1622                  return (EIO);
1622 1623          }
1623 1624  
1624 1625          /*
1625 1626           * Some controllers apparently don't want to be touched for at least 1ms
1626 1627           * after we initiate the reset. Therefore give all controllers this
1627 1628           * moment to breathe.
↓ open down ↓ 336 lines elided ↑ open up ↑
1964 1965                  xhcip->xhci_fm_caps = 0;
1965 1966          }
1966 1967  
1967 1968          inst = ddi_get_instance(xhcip->xhci_dip);
1968 1969          xhcip->xhci_dip = NULL;
1969 1970          ddi_soft_state_free(xhci_soft_state, inst);
1970 1971  
1971 1972          return (DDI_SUCCESS);
1972 1973  }
1973 1974  
     1975 +/* QUIESCE(9E) to support fast reboot */
     1976 +int
     1977 +xhci_quiesce(dev_info_t *dip)
     1978 +{
     1979 +        xhci_t *xhcip;
     1980 +
     1981 +        xhcip = ddi_get_soft_state(xhci_soft_state, ddi_get_instance(dip));
     1982 +
     1983 +        return (xhci_controller_stop(xhcip) == 0 &&
     1984 +            xhci_controller_reset(xhcip) == 0 ? DDI_SUCCESS : DDI_FAILURE);
     1985 +}
     1986 +
1974 1987  static int
1975 1988  xhci_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1976 1989  {
1977 1990          int ret, inst, route;
1978 1991          xhci_t *xhcip;
1979 1992  
1980 1993          if (cmd != DDI_ATTACH)
1981 1994                  return (DDI_FAILURE);
1982 1995  
1983 1996          inst = ddi_get_instance(dip);
↓ open down ↓ 192 lines elided ↑ open up ↑
2176 2189          0,                              /* devo_refcnt */
2177 2190          xhci_getinfo,                   /* devo_getinfo */
2178 2191          nulldev,                        /* devo_identify */
2179 2192          nulldev,                        /* devo_probe */
2180 2193          xhci_attach,                    /* devo_attach */
2181 2194          xhci_detach,                    /* devo_detach */
2182 2195          nodev,                          /* devo_reset */
2183 2196          &xhci_cb_ops,                   /* devo_cb_ops */
2184 2197          &usba_hubdi_busops,             /* devo_bus_ops */
2185 2198          usba_hubdi_root_hub_power,      /* devo_power */
2186      -        ddi_quiesce_not_supported       /* devo_quiesce */
     2199 +        xhci_quiesce                    /* devo_quiesce */
2187 2200  };
2188 2201  
2189 2202  static struct modldrv xhci_modldrv = {
2190 2203          &mod_driverops,
2191 2204          "USB xHCI Driver",
2192 2205          &xhci_dev_ops
2193 2206  };
2194 2207  
2195 2208  static struct modlinkage xhci_modlinkage = {
2196 2209          MODREV_1,
↓ open down ↓ 51 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX