summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/io/tphci.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/io/tphci.c')
-rw-r--r--usr/src/uts/common/io/tphci.c100
1 files changed, 63 insertions, 37 deletions
diff --git a/usr/src/uts/common/io/tphci.c b/usr/src/uts/common/io/tphci.c
index b9a3b43fb3..1aa9c4ebf1 100644
--- a/usr/src/uts/common/io/tphci.c
+++ b/usr/src/uts/common/io/tphci.c
@@ -39,7 +39,6 @@
#include <sys/sunddi.h>
#include <sys/sunndi.h>
#include <sys/sunmdi.h>
-#include <sys/mdi_impldefs.h>
#include <sys/disp.h>
/* cb_ops entry points */
@@ -483,18 +482,18 @@ tphci_bus_config(dev_info_t *parent, uint_t flags,
ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
{
_NOTE(ARGUNUSED(flags))
- char *cname, *paddr, *guid, *devnm;
- mdi_pathinfo_t *pip;
- int len;
+ char *cname, *paddr, *guid, *devnm;
+ mdi_pathinfo_t *pip;
+ int len, circ, rval;
switch (op) {
case BUS_CONFIG_ONE:
break;
case BUS_CONFIG_DRIVER: /* no direct children to configure */
case BUS_CONFIG_ALL:
- return (DDI_SUCCESS);
+ return (NDI_SUCCESS);
default:
- return (DDI_FAILURE);
+ return (NDI_FAILURE);
}
/* only implement BUS_CONFIG_ONE */
@@ -506,75 +505,102 @@ tphci_bus_config(dev_info_t *parent, uint_t flags,
cmn_err(CE_NOTE, "tphci_bus_config -- invalid device %s",
(char *)arg);
kmem_free(devnm, len);
- return (DDI_FAILURE);
+ return (NDI_FAILURE);
}
- if (mdi_pi_alloc(parent, cname, guid, paddr, 0, &pip)
- != MDI_SUCCESS) {
+ mdi_devi_enter(parent, &circ);
+ rval = mdi_pi_alloc(parent, cname, guid, paddr, 0, &pip);
+ kmem_free(devnm, len);
+ if (rval != MDI_SUCCESS) {
cmn_err(CE_NOTE, "tphci_bus_config -- mdi_pi_alloc failed");
- kmem_free(devnm, len);
- return (DDI_FAILURE);
+ mdi_devi_exit(parent, circ);
+ return (NDI_FAILURE);
}
- kmem_free(devnm, len);
- if (mdi_pi_online(pip, 0) != MDI_SUCCESS) {
+ /*
+ * Hold the path and exit the pHCI while calling mdi_pi_online
+ * to avoid deadlock with power management of pHCI.
+ */
+ mdi_hold_path(pip);
+ mdi_devi_exit_phci(parent, circ);
+ rval = mdi_pi_online(pip, 0);
+ mdi_devi_enter_phci(parent, &circ);
+ mdi_rele_path(pip);
+
+ if (rval != MDI_SUCCESS) {
cmn_err(CE_NOTE, "tphci_bus_config -- mdi_pi_online failed");
(void) mdi_pi_free(pip, 0);
- return (DDI_FAILURE);
+ mdi_devi_exit(parent, circ);
+ return (NDI_FAILURE);
}
if (childp) {
- *childp = MDI_PI(pip)->pi_client->ct_dip;
+ *childp = mdi_pi_get_client(pip);
ndi_hold_devi(*childp);
}
- return (DDI_SUCCESS);
+ mdi_devi_exit(parent, circ);
+
+ return (NDI_SUCCESS);
}
static int
tphci_bus_unconfig(dev_info_t *parent, uint_t flags,
ddi_bus_config_op_t op, void *arg)
{
- int rval, circ;
- mdi_pathinfo_t *pip;
- mdi_phci_t *ph;
- char *devnm, *cname, *caddr;
+ int rval = MDI_SUCCESS;
+ int circ;
+ mdi_pathinfo_t *pip, *next;
+ char *devnm, *cname, *caddr;
switch (op) {
case BUS_UNCONFIG_ONE:
devnm = (char *)arg;
i_ddi_parse_name(devnm, &cname, &caddr, NULL);
if (strcmp(cname, "tclient") != 0)
- return (DDI_SUCCESS); /* no such device */
+ return (NDI_SUCCESS); /* no such device */
+
+ mdi_devi_enter(parent, &circ);
pip = mdi_pi_find(parent, NULL, caddr);
- if (pip == NULL)
- return (DDI_SUCCESS);
- rval = mdi_pi_offline(pip, NDI_DEVI_REMOVE);
+ if (pip) {
+ mdi_hold_path(pip);
+ mdi_devi_exit_phci(parent, circ);
+ rval = mdi_pi_offline(pip, NDI_DEVI_REMOVE);
+ mdi_devi_enter_phci(parent, &circ);
+ mdi_rele_path(pip);
+
+ if (rval == MDI_SUCCESS)
+ (void) mdi_pi_free(pip, 0);
+ }
+ mdi_devi_exit(parent, circ);
return (rval == MDI_SUCCESS ? NDI_SUCCESS : NDI_FAILURE);
case BUS_UNCONFIG_ALL:
if (flags & NDI_AUTODETACH)
- return (DDI_FAILURE);
+ return (NDI_FAILURE);
- ph = DEVI(parent)->devi_mdi_xhci;
- ASSERT(ph != NULL);
+ mdi_devi_enter(parent, &circ);
+ next = mdi_get_next_client_path(parent, NULL);
+ while ((pip = next) != NULL) {
+ next = mdi_get_next_client_path(parent, pip);
- rval = MDI_SUCCESS;
- ndi_devi_enter(parent, &circ);
- pip = (mdi_pathinfo_t *)ph->ph_path_head;
- while (pip) {
+ mdi_hold_path(pip);
+ mdi_devi_exit_phci(parent, circ);
rval = mdi_pi_offline(pip, NDI_DEVI_REMOVE);
- if (rval != MDI_SUCCESS) {
+ mdi_devi_enter_phci(parent, &circ);
+ mdi_rele_path(pip);
+
+ if (rval != MDI_SUCCESS)
break;
- }
- pip = (mdi_pathinfo_t *)ph->ph_path_head;
+ (void) mdi_pi_free(pip, 0);
}
- ndi_devi_exit(parent, circ);
+ mdi_devi_exit(parent, circ);
return (rval == MDI_SUCCESS ? NDI_SUCCESS : NDI_FAILURE);
case BUS_UNCONFIG_DRIVER: /* nothing to do */
- return (DDI_SUCCESS);
+ return (NDI_SUCCESS);
+
default:
- return (DDI_FAILURE);
+ return (NDI_FAILURE);
}
/*NOTREACHED*/
}