Print this page
Add xhci_quiesce to support fast reboot.
   1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright (c) 2017, Joyent, Inc.

  14  */
  15 
  16 /*
  17  * Extensible Host Controller Interface (xHCI) USB Driver
  18  *
  19  * The xhci driver is an HCI driver for USB that bridges the gap between client
  20  * device drivers and implements the actual way that we talk to devices. The
  21  * xhci specification provides access to USB 3.x capable devices, as well as all
  22  * prior generations. Like other host controllers, it both provides the way to
  23  * talk to devices and also is treated like a hub (often called the root hub).
  24  *
  25  * This driver is part of the USBA (USB Architecture). It implements the HCDI
  26  * (host controller device interface) end of USBA. These entry points are used
  27  * by the USBA on behalf of client device drivers to access their devices. The
  28  * driver also provides notifications to deal with hot plug events, which are
  29  * quite common in USB.
  30  *
  31  * ----------------
  32  * USB Introduction
  33  * ----------------


 996                 roff = xhcip->xhci_regs_runoff;
 997                 break;
 998         case XHCI_R_DOOR:
 999                 roff = xhcip->xhci_regs_dooroff;
1000                 break;
1001         default:
1002                 panic("called %s with bad reg type: %d", __func__, rtt);
1003         }
1004         ASSERT(roff != PCI_EINVAL32);
1005         addr = roff + off + (uintptr_t)xhcip->xhci_regs_base;
1006 
1007         ddi_put64(xhcip->xhci_regs_handle, (void *)addr, val);
1008 }
1009 
1010 int
1011 xhci_check_regs_acc(xhci_t *xhcip)
1012 {
1013         ddi_fm_error_t de;
1014 
1015         /*
1016          * Treat the case where we can't check as fine so we can treat the code
1017          * more simply.
1018          */
1019         if (!DDI_FM_ACC_ERR_CAP(xhcip->xhci_fm_caps))
1020                 return (DDI_FM_OK);
1021 
1022         ddi_fm_acc_err_get(xhcip->xhci_regs_handle, &de, DDI_FME_VERSION);
1023         ddi_fm_acc_err_clear(xhcip->xhci_regs_handle, DDI_FME_VERSION);
1024         return (de.fme_status);
1025 }
1026 
1027 /*
1028  * As a leaf PCIe driver, we just post the ereport and continue on.
1029  */
1030 /* ARGSUSED */
1031 static int
1032 xhci_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, const void *impl_data)
1033 {
1034         pci_ereport_post(dip, err, NULL);
1035         return (err->fme_status);
1036 }
1037 
1038 static void
1039 xhci_fm_fini(xhci_t *xhcip)


1954                 xhcip->xhci_regs_handle = NULL;
1955         }
1956 
1957         if (xhcip->xhci_seq & XHCI_ATTACH_PCI_CONFIG) {
1958                 pci_config_teardown(&xhcip->xhci_cfg_handle);
1959                 xhcip->xhci_cfg_handle = NULL;
1960         }
1961 
1962         if (xhcip->xhci_seq & XHCI_ATTACH_FM) {
1963                 xhci_fm_fini(xhcip);
1964                 xhcip->xhci_fm_caps = 0;
1965         }
1966 
1967         inst = ddi_get_instance(xhcip->xhci_dip);
1968         xhcip->xhci_dip = NULL;
1969         ddi_soft_state_free(xhci_soft_state, inst);
1970 
1971         return (DDI_SUCCESS);
1972 }
1973 












1974 static int
1975 xhci_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1976 {
1977         int ret, inst, route;
1978         xhci_t *xhcip;
1979 
1980         if (cmd != DDI_ATTACH)
1981                 return (DDI_FAILURE);
1982 
1983         inst = ddi_get_instance(dip);
1984         if (ddi_soft_state_zalloc(xhci_soft_state, inst) != 0)
1985                 return (DDI_FAILURE);
1986         xhcip = ddi_get_soft_state(xhci_soft_state, ddi_get_instance(dip));
1987         xhcip->xhci_dip = dip;
1988 
1989         xhcip->xhci_regs_capoff = PCI_EINVAL32;
1990         xhcip->xhci_regs_operoff = PCI_EINVAL32;
1991         xhcip->xhci_regs_runoff = PCI_EINVAL32;
1992         xhcip->xhci_regs_dooroff = PCI_EINVAL32;
1993 


2166         ddi_prop_op,            /* cb_prop_op */
2167         NULL,                   /* cb_stream */
2168         D_MP | D_HOTPLUG,       /* cb_flag */
2169         CB_REV,                 /* cb_rev */
2170         nodev,                  /* cb_aread */
2171         nodev                   /* cb_awrite */
2172 };
2173 
2174 static struct dev_ops xhci_dev_ops = {
2175         DEVO_REV,                       /* devo_rev */
2176         0,                              /* devo_refcnt */
2177         xhci_getinfo,                   /* devo_getinfo */
2178         nulldev,                        /* devo_identify */
2179         nulldev,                        /* devo_probe */
2180         xhci_attach,                    /* devo_attach */
2181         xhci_detach,                    /* devo_detach */
2182         nodev,                          /* devo_reset */
2183         &xhci_cb_ops,                       /* devo_cb_ops */
2184         &usba_hubdi_busops,         /* devo_bus_ops */
2185         usba_hubdi_root_hub_power,      /* devo_power */
2186         ddi_quiesce_not_supported       /* devo_quiesce */
2187 };
2188 
2189 static struct modldrv xhci_modldrv = {
2190         &mod_driverops,
2191         "USB xHCI Driver",
2192         &xhci_dev_ops
2193 };
2194 
2195 static struct modlinkage xhci_modlinkage = {
2196         MODREV_1,
2197         &xhci_modldrv,
2198         NULL
2199 };
2200 
2201 int
2202 _init(void)
2203 {
2204         int ret;
2205 
2206         if ((ret = ddi_soft_state_init(&xhci_soft_state, sizeof (xhci_t),


   1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright (c) 2017, Joyent, Inc.
  14  * Copyright (c) 2018, Western Digital Corporation.
  15  */
  16 
  17 /*
  18  * Extensible Host Controller Interface (xHCI) USB Driver
  19  *
  20  * The xhci driver is an HCI driver for USB that bridges the gap between client
  21  * device drivers and implements the actual way that we talk to devices. The
  22  * xhci specification provides access to USB 3.x capable devices, as well as all
  23  * prior generations. Like other host controllers, it both provides the way to
  24  * talk to devices and also is treated like a hub (often called the root hub).
  25  *
  26  * This driver is part of the USBA (USB Architecture). It implements the HCDI
  27  * (host controller device interface) end of USBA. These entry points are used
  28  * by the USBA on behalf of client device drivers to access their devices. The
  29  * driver also provides notifications to deal with hot plug events, which are
  30  * quite common in USB.
  31  *
  32  * ----------------
  33  * USB Introduction
  34  * ----------------


 997                 roff = xhcip->xhci_regs_runoff;
 998                 break;
 999         case XHCI_R_DOOR:
1000                 roff = xhcip->xhci_regs_dooroff;
1001                 break;
1002         default:
1003                 panic("called %s with bad reg type: %d", __func__, rtt);
1004         }
1005         ASSERT(roff != PCI_EINVAL32);
1006         addr = roff + off + (uintptr_t)xhcip->xhci_regs_base;
1007 
1008         ddi_put64(xhcip->xhci_regs_handle, (void *)addr, val);
1009 }
1010 
1011 int
1012 xhci_check_regs_acc(xhci_t *xhcip)
1013 {
1014         ddi_fm_error_t de;
1015 
1016         /*
1017          * Treat cases where we can't check as fine so we can treat the code
1018          * more simply.
1019          */
1020         if (quiesce_active || !DDI_FM_ACC_ERR_CAP(xhcip->xhci_fm_caps))
1021                 return (DDI_FM_OK);
1022 
1023         ddi_fm_acc_err_get(xhcip->xhci_regs_handle, &de, DDI_FME_VERSION);
1024         ddi_fm_acc_err_clear(xhcip->xhci_regs_handle, DDI_FME_VERSION);
1025         return (de.fme_status);
1026 }
1027 
1028 /*
1029  * As a leaf PCIe driver, we just post the ereport and continue on.
1030  */
1031 /* ARGSUSED */
1032 static int
1033 xhci_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, const void *impl_data)
1034 {
1035         pci_ereport_post(dip, err, NULL);
1036         return (err->fme_status);
1037 }
1038 
1039 static void
1040 xhci_fm_fini(xhci_t *xhcip)


1955                 xhcip->xhci_regs_handle = NULL;
1956         }
1957 
1958         if (xhcip->xhci_seq & XHCI_ATTACH_PCI_CONFIG) {
1959                 pci_config_teardown(&xhcip->xhci_cfg_handle);
1960                 xhcip->xhci_cfg_handle = NULL;
1961         }
1962 
1963         if (xhcip->xhci_seq & XHCI_ATTACH_FM) {
1964                 xhci_fm_fini(xhcip);
1965                 xhcip->xhci_fm_caps = 0;
1966         }
1967 
1968         inst = ddi_get_instance(xhcip->xhci_dip);
1969         xhcip->xhci_dip = NULL;
1970         ddi_soft_state_free(xhci_soft_state, inst);
1971 
1972         return (DDI_SUCCESS);
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 
1987 static int
1988 xhci_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1989 {
1990         int ret, inst, route;
1991         xhci_t *xhcip;
1992 
1993         if (cmd != DDI_ATTACH)
1994                 return (DDI_FAILURE);
1995 
1996         inst = ddi_get_instance(dip);
1997         if (ddi_soft_state_zalloc(xhci_soft_state, inst) != 0)
1998                 return (DDI_FAILURE);
1999         xhcip = ddi_get_soft_state(xhci_soft_state, ddi_get_instance(dip));
2000         xhcip->xhci_dip = dip;
2001 
2002         xhcip->xhci_regs_capoff = PCI_EINVAL32;
2003         xhcip->xhci_regs_operoff = PCI_EINVAL32;
2004         xhcip->xhci_regs_runoff = PCI_EINVAL32;
2005         xhcip->xhci_regs_dooroff = PCI_EINVAL32;
2006 


2179         ddi_prop_op,            /* cb_prop_op */
2180         NULL,                   /* cb_stream */
2181         D_MP | D_HOTPLUG,       /* cb_flag */
2182         CB_REV,                 /* cb_rev */
2183         nodev,                  /* cb_aread */
2184         nodev                   /* cb_awrite */
2185 };
2186 
2187 static struct dev_ops xhci_dev_ops = {
2188         DEVO_REV,                       /* devo_rev */
2189         0,                              /* devo_refcnt */
2190         xhci_getinfo,                   /* devo_getinfo */
2191         nulldev,                        /* devo_identify */
2192         nulldev,                        /* devo_probe */
2193         xhci_attach,                    /* devo_attach */
2194         xhci_detach,                    /* devo_detach */
2195         nodev,                          /* devo_reset */
2196         &xhci_cb_ops,                       /* devo_cb_ops */
2197         &usba_hubdi_busops,         /* devo_bus_ops */
2198         usba_hubdi_root_hub_power,      /* devo_power */
2199         xhci_quiesce                    /* devo_quiesce */
2200 };
2201 
2202 static struct modldrv xhci_modldrv = {
2203         &mod_driverops,
2204         "USB xHCI Driver",
2205         &xhci_dev_ops
2206 };
2207 
2208 static struct modlinkage xhci_modlinkage = {
2209         MODREV_1,
2210         &xhci_modldrv,
2211         NULL
2212 };
2213 
2214 int
2215 _init(void)
2216 {
2217         int ret;
2218 
2219         if ((ret = ddi_soft_state_init(&xhci_soft_state, sizeof (xhci_t),