diff options
| author | Hans Rosenfeld <hans.rosenfeld@joyent.com> | 2018-03-13 16:36:36 +0100 |
|---|---|---|
| committer | Hans Rosenfeld <hans.rosenfeld@joyent.com> | 2018-03-21 22:45:40 +0000 |
| commit | cbbb96d54a2a10694551e3a98692b9386cb21e13 (patch) | |
| tree | f0c01360bcc2d937458741a176a0f2bda3a49915 | |
| parent | c258591bb17c772b4c77a02cae64932aaa17bef4 (diff) | |
| download | illumos-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.c | 15 | ||||
| -rw-r--r-- | usr/src/uts/i86pc/io/vmm/io/ppt.c | 88 |
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 |
