summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Rosenfeld <hans.rosenfeld@joyent.com>2018-03-13 16:36:36 +0100
committerHans Rosenfeld <hans.rosenfeld@joyent.com>2018-03-21 22:45:40 +0000
commitcbbb96d54a2a10694551e3a98692b9386cb21e13 (patch)
treef0c01360bcc2d937458741a176a0f2bda3a49915
parentc258591bb17c772b4c77a02cae64932aaa17bef4 (diff)
downloadillumos-joyent-cbbb96d54a2a10694551e3a98692b9386cb21e13.tar.gz
OS-6771 ppt device nodes sometimes disappear after module unloading
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com> Reviewed by: Patrick Mooney <patrick.mooney@joyent.com> Approved by: Jerry Jelinek <jerry.jelinek@joyent.com>
-rw-r--r--usr/src/cmd/devfsadm/i386/misc_link_i386.c15
-rw-r--r--usr/src/uts/i86pc/io/vmm/io/ppt.c88
2 files changed, 43 insertions, 60 deletions
diff --git a/usr/src/cmd/devfsadm/i386/misc_link_i386.c b/usr/src/cmd/devfsadm/i386/misc_link_i386.c
index fbb344cdf6..6b21eabe3b 100644
--- a/usr/src/cmd/devfsadm/i386/misc_link_i386.c
+++ b/usr/src/cmd/devfsadm/i386/misc_link_i386.c
@@ -46,6 +46,7 @@ static int kdmouse(di_minor_t minor, di_node_t node);
static int ipmi(di_minor_t minor, di_node_t node);
static int mc_node(di_minor_t minor, di_node_t node);
static int vmmctl(di_minor_t minor, di_node_t node);
+static int ppt(di_minor_t minor, di_node_t node);
static devfsadm_create_t misc_cbt[] = {
{ "vt00", "ddi_display", NULL,
@@ -92,7 +93,7 @@ static devfsadm_create_t misc_cbt[] = {
TYPE_EXACT | DRV_EXACT, ILEVEL_0, vmmctl,
},
{ "pseudo", "ddi_pseudo", "ppt",
- TYPE_EXACT | DRV_EXACT, ILEVEL_0, ln_minor_name,
+ TYPE_EXACT | DRV_EXACT, ILEVEL_0, ppt,
}
};
@@ -375,3 +376,15 @@ vmmctl(di_minor_t minor, di_node_t node)
(void) devfsadm_mklink("vmmctl", node, minor, 0);
return (DEVFSADM_CONTINUE);
}
+
+static int
+ppt(di_minor_t minor, di_node_t node)
+{
+ char linkpath[PATH_MAX];
+
+ (void) snprintf(linkpath, sizeof (linkpath), "ppt%d",
+ di_instance(node));
+
+ (void) devfsadm_mklink(linkpath, node, minor, 0);
+ return (DEVFSADM_CONTINUE);
+}
diff --git a/usr/src/uts/i86pc/io/vmm/io/ppt.c b/usr/src/uts/i86pc/io/vmm/io/ppt.c
index 5cc8156137..777d4129e0 100644
--- a/usr/src/uts/i86pc/io/vmm/io/ppt.c
+++ b/usr/src/uts/i86pc/io/vmm/io/ppt.c
@@ -57,7 +57,6 @@ __FBSDID("$FreeBSD$");
#include <sys/pci_cap.h>
#include <sys/ppt_dev.h>
#include <sys/mkdev.h>
-#include <sys/id_space.h>
#include "vmm_lapic.h"
#include "vmm_ktr.h"
@@ -101,7 +100,6 @@ struct pptdev {
dev_info_t *pptd_dip;
list_node_t pptd_node;
ddi_acc_handle_t pptd_cfg;
- dev_t pptd_dev;
struct pptbar pptd_bars[PCI_BASE_NUM];
struct vm *vm;
struct pptseg mmio[MAX_MMIOSEGS];
@@ -123,10 +121,12 @@ struct pptdev {
};
+static major_t ppt_major;
static void *ppt_state;
static kmutex_t pptdev_mtx;
static list_t pptdev_list;
-static id_space_t *pptdev_minors = NULL;
+
+#define PPT_MINOR_NAME "ppt"
static ddi_device_acc_attr_t ppt_attr = {
DDI_DEVICE_ATTR_V0,
@@ -385,42 +385,22 @@ ppt_bar_crawl(struct pptdev *ppt)
return (err);
}
-static struct pptdev *
-ppt_find_dev(dev_t dev)
-{
- struct pptdev *ppt;
-
- ASSERT(MUTEX_HELD(&pptdev_mtx));
-
- for (ppt = list_head(&pptdev_list); ppt != NULL;
- ppt = list_next(&pptdev_list, ppt)) {
- if (ppt->pptd_dev == dev) {
- return (ppt);
- }
- }
-
- return (NULL);
-}
-
static int
ppt_ddi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
struct pptdev *ppt = NULL;
char name[PPT_MAXNAMELEN];
- minor_t minor;
+ int inst;
if (cmd != DDI_ATTACH)
return (DDI_FAILURE);
- minor = id_alloc_nosleep(pptdev_minors);
- if (minor == -1) {
- return (DDI_FAILURE);
- }
+ inst = ddi_get_instance(dip);
- if (ddi_soft_state_zalloc(ppt_state, minor) != DDI_SUCCESS) {
+ if (ddi_soft_state_zalloc(ppt_state, inst) != DDI_SUCCESS) {
goto fail;
}
- VERIFY(ppt = ddi_get_soft_state(ppt_state, minor));
+ VERIFY(ppt = ddi_get_soft_state(ppt_state, inst));
ppt->pptd_dip = dip;
ddi_set_driver_private(dip, ppt);
@@ -431,16 +411,11 @@ ppt_ddi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
goto fail;
}
- if (snprintf(name, sizeof (name), "ppt%u", minor)
- >= PPT_MAXNAMELEN - 1) {
- goto fail;
- }
- if (ddi_create_minor_node(dip, name, S_IFCHR, minor,
+ if (ddi_create_minor_node(dip, PPT_MINOR_NAME, S_IFCHR, inst,
DDI_PSEUDO, 0) != DDI_SUCCESS) {
goto fail;
}
- ppt->pptd_dev = makedevice(ddi_driver_major(dip), minor);
mutex_enter(&pptdev_mtx);
list_insert_tail(&pptdev_list, ppt);
mutex_exit(&pptdev_mtx);
@@ -454,9 +429,8 @@ fail:
pci_config_teardown(&ppt->pptd_cfg);
}
ppt_bar_wipe(ppt);
- ddi_soft_state_free(ppt_state, minor);
+ ddi_soft_state_free(ppt_state, inst);
}
- id_free(pptdev_minors, minor);
return (DDI_FAILURE);
}
@@ -464,15 +438,15 @@ static int
ppt_ddi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
{
struct pptdev *ppt;
- minor_t minor;
+ int inst;
if (cmd != DDI_DETACH)
return (DDI_FAILURE);
ppt = ddi_get_driver_private(dip);
- minor = getminor(ppt->pptd_dev);
+ inst = ddi_get_instance(dip);
- ASSERT3P(ddi_get_soft_state(ppt_state, minor), ==, ppt);
+ ASSERT3P(ddi_get_soft_state(ppt_state, inst), ==, ppt);
mutex_enter(&pptdev_mtx);
if (ppt->vm != NULL) {
@@ -482,12 +456,11 @@ ppt_ddi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
list_remove(&pptdev_list, ppt);
mutex_exit(&pptdev_mtx);
- ddi_remove_minor_node(dip, NULL);
+ ddi_remove_minor_node(dip, PPT_MINOR_NAME);
ppt_bar_wipe(ppt);
pci_config_teardown(&ppt->pptd_cfg);
ddi_set_driver_private(dip, NULL);
- ddi_soft_state_free(ppt_state, minor);
- id_free(pptdev_minors, minor);
+ ddi_soft_state_free(ppt_state, inst);
return (DDI_SUCCESS);
}
@@ -496,22 +469,20 @@ static int
ppt_ddi_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
{
int error = DDI_FAILURE;
+ int inst = getminor((dev_t)arg);
switch (cmd) {
case DDI_INFO_DEVT2DEVINFO: {
- struct pptdev *ppt;
+ struct pptdev *ppt = ddi_get_soft_state(ppt_state, inst);
- mutex_enter(&pptdev_mtx);
- ppt = ppt_find_dev((dev_t)arg);
if (ppt != NULL) {
*result = (void *)ppt->pptd_dip;
error = DDI_SUCCESS;
}
- mutex_exit(&pptdev_mtx);
break;
}
case DDI_INFO_DEVT2INSTANCE: {
- *result = (void *)(uintptr_t)getminor((dev_t)arg);
+ *result = (void *)(uintptr_t)inst;
error = DDI_SUCCESS;
break;
}
@@ -572,7 +543,6 @@ _init(void)
mutex_init(&pptdev_mtx, NULL, MUTEX_DRIVER, NULL);
list_create(&pptdev_list, sizeof (struct pptdev),
offsetof(struct pptdev, pptd_node));
- pptdev_minors = id_space_create("ppt_minors", 0, MAXMIN32);
error = ddi_soft_state_init(&ppt_state, sizeof (struct pptdev), 0);
if (error) {
@@ -581,11 +551,10 @@ _init(void)
error = mod_install(&modlinkage);
+ ppt_major = ddi_name_to_major("ppt");
fail:
if (error) {
ddi_soft_state_fini(&ppt_state);
- id_space_destroy(pptdev_minors);
- pptdev_minors = NULL;
}
return (error);
}
@@ -598,9 +567,6 @@ _fini(void)
error = mod_remove(&modlinkage);
if (error)
return (error);
-
- id_space_destroy(pptdev_minors);
- pptdev_minors = NULL;
ddi_soft_state_fini(&ppt_state);
return (0);
@@ -770,14 +736,18 @@ ppt_findf(int fd)
}
va.va_mask = AT_RDEV;
- if (VOP_GETATTR(fp->f_vnode, &va, NO_FOLLOW, fp->f_cred, NULL) == 0) {
- ppt = ppt_find_dev(va.va_rdev);
- }
+ if (VOP_GETATTR(fp->f_vnode, &va, NO_FOLLOW, fp->f_cred, NULL) != 0 ||
+ getmajor(va.va_rdev) != ppt_major)
+ goto fail;
- if (ppt == NULL) {
- releasef(fd);
- }
- return (ppt);
+ ppt = ddi_get_soft_state(ppt_state, getminor(va.va_rdev));
+
+ if (ppt != NULL)
+ return (ppt);
+
+fail:
+ releasef(fd);
+ return (NULL);
}
static void