diff options
Diffstat (limited to 'usr/src/uts/i86pc/io/pciex/npe.c')
| -rw-r--r-- | usr/src/uts/i86pc/io/pciex/npe.c | 233 |
1 files changed, 153 insertions, 80 deletions
diff --git a/usr/src/uts/i86pc/io/pciex/npe.c b/usr/src/uts/i86pc/io/pciex/npe.c index 81485cf798..23b02640f5 100644 --- a/usr/src/uts/i86pc/io/pciex/npe.c +++ b/usr/src/uts/i86pc/io/pciex/npe.c @@ -30,6 +30,7 @@ #include <sys/conf.h> #include <sys/modctl.h> +#include <sys/file.h> #include <sys/pci_impl.h> #include <sys/pcie_impl.h> #include <sys/sysmacros.h> @@ -39,7 +40,7 @@ #include <sys/ddifm.h> #include <sys/ndifm.h> #include <sys/fm/util.h> -#include <sys/hotplug/pci/pcihp.h> +#include <sys/hotplug/pci/pcie_hp.h> #include <io/pci/pci_tools_ext.h> #include <io/pci/pci_common.h> #include <io/pciex/pcie_nvidia.h> @@ -96,33 +97,25 @@ struct bus_ops npe_bus_ops = { ddi_dma_mctl, npe_ctlops, ddi_bus_prop_op, - 0, /* (*bus_get_eventcookie)(); */ - 0, /* (*bus_add_eventcall)(); */ - 0, /* (*bus_remove_eventcall)(); */ - 0, /* (*bus_post_event)(); */ - 0, /* (*bus_intr_ctl)(); */ - 0, /* (*bus_config)(); */ - 0, /* (*bus_unconfig)(); */ - npe_fm_init, /* (*bus_fm_init)(); */ - NULL, /* (*bus_fm_fini)(); */ - NULL, /* (*bus_fm_access_enter)(); */ - NULL, /* (*bus_fm_access_exit)(); */ - NULL, /* (*bus_power)(); */ - npe_intr_ops /* (*bus_intr_op)(); */ + 0, /* (*bus_get_eventcookie)(); */ + 0, /* (*bus_add_eventcall)(); */ + 0, /* (*bus_remove_eventcall)(); */ + 0, /* (*bus_post_event)(); */ + 0, /* (*bus_intr_ctl)(); */ + 0, /* (*bus_config)(); */ + 0, /* (*bus_unconfig)(); */ + npe_fm_init, /* (*bus_fm_init)(); */ + NULL, /* (*bus_fm_fini)(); */ + NULL, /* (*bus_fm_access_enter)(); */ + NULL, /* (*bus_fm_access_exit)(); */ + NULL, /* (*bus_power)(); */ + npe_intr_ops, /* (*bus_intr_op)(); */ + pcie_hp_common_ops /* (*bus_hp_op)(); */ }; -/* - * One goal here is to leverage off of the pcihp.c source without making - * changes to it. Call into it's cb_ops directly if needed, piggybacking - * anything else needed by the pci_tools.c module. Only pci_tools and pcihp - * will be using the PCI devctl node. - */ static int npe_open(dev_t *, int, int, cred_t *); static int npe_close(dev_t, int, int, cred_t *); static int npe_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); -static int npe_prop_op(dev_t, dev_info_t *, ddi_prop_op_t, int, char *, - caddr_t, int *); -static int npe_info(dev_info_t *, ddi_info_cmd_t, void *, void **); struct cb_ops npe_cb_ops = { npe_open, /* open */ @@ -137,7 +130,7 @@ struct cb_ops npe_cb_ops = { nodev, /* mmap */ nodev, /* segmap */ nochpoll, /* poll */ - npe_prop_op, /* cb_prop_op */ + pcie_prop_op, /* cb_prop_op */ NULL, /* streamtab */ D_NEW | D_MP | D_HOTPLUG, /* Driver compatibility flag */ CB_REV, /* rev */ @@ -151,6 +144,7 @@ struct cb_ops npe_cb_ops = { */ static int npe_attach(dev_info_t *devi, ddi_attach_cmd_t cmd); static int npe_detach(dev_info_t *devi, ddi_detach_cmd_t cmd); +static int npe_info(dev_info_t *, ddi_info_cmd_t, void *, void **); struct dev_ops npe_ops = { DEVO_REV, /* devo_rev */ @@ -190,9 +184,9 @@ extern int npe_restore_htconfig_children(dev_info_t *dip); * Module linkage information for the kernel. */ static struct modldrv modldrv = { - &mod_driverops, /* Type of module */ - "Host to PCIe nexus driver", - &npe_ops, /* driver ops */ + &mod_driverops, /* Type of module */ + "Host to PCIe nexus driver", /* Name of module */ + &npe_ops, /* driver ops */ }; static struct modlinkage modlinkage = { @@ -245,14 +239,39 @@ _info(struct modinfo *modinfop) /*ARGSUSED*/ static int +npe_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) +{ + minor_t minor = getminor((dev_t)arg); + int instance = PCI_MINOR_NUM_TO_INSTANCE(minor); + pci_state_t *pcip = ddi_get_soft_state(npe_statep, instance); + int ret = DDI_SUCCESS; + + switch (cmd) { + case DDI_INFO_DEVT2INSTANCE: + *result = (void *)(intptr_t)instance; + break; + case DDI_INFO_DEVT2DEVINFO: + if (pcip == NULL) { + ret = DDI_FAILURE; + break; + } + + *result = (void *)pcip->pci_dip; + break; + default: + ret = DDI_FAILURE; + break; + } + + return (ret); +} + +/*ARGSUSED*/ +static int npe_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) { - /* - * Use the minor number as constructed by pcihp, as the index value to - * ddi_soft_state_zalloc. - */ - int instance = ddi_get_instance(devi); - pci_state_t *pcip = NULL; + int instance = ddi_get_instance(devi); + pci_state_t *pcip = NULL; if (cmd == DDI_RESUME) { /* @@ -287,27 +306,16 @@ npe_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) return (DDI_FAILURE); pcip->pci_dip = devi; + pcip->pci_soft_state = PCI_SOFT_STATE_CLOSED; pcie_rc_init_bus(devi); - /* - * Initialize hotplug support on this bus. At minimum - * (for non hotplug bus) this would create ":devctl" minor - * node to support DEVCTL_DEVICE_* and DEVCTL_BUS_* ioctls - * to this bus. - */ - if (pcihp_init(devi) != DDI_SUCCESS) { - cmn_err(CE_WARN, "npe: Failed to setup hotplug framework"); - ddi_soft_state_free(npe_statep, instance); - return (DDI_FAILURE); - } + if (pcie_init(devi, NULL) != DDI_SUCCESS) + goto fail1; /* Second arg: initialize for pci_express root nexus */ - if (pcitool_init(devi, B_TRUE) != DDI_SUCCESS) { - (void) pcihp_uninit(devi); - ddi_soft_state_free(npe_statep, instance); - return (DDI_FAILURE); - } + if (pcitool_init(devi, B_TRUE) != DDI_SUCCESS) + goto fail2; pcip->pci_fmcap = DDI_FM_EREPORT_CAPABLE | DDI_FM_ERRCB_CAPABLE | DDI_FM_ACCCHK_CAPABLE | DDI_FM_DMACHK_CAPABLE; @@ -322,8 +330,16 @@ npe_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) npe_query_acpi_mcfg(devi); ddi_report_dev(devi); + return (DDI_SUCCESS); +fail2: + (void) pcie_uninit(devi); +fail1: + pcie_rc_fini_bus(devi); + ddi_soft_state_free(npe_statep, instance); + + return (DDI_FAILURE); } /*ARGSUSED*/ @@ -341,10 +357,8 @@ npe_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) /* Uninitialize pcitool support. */ pcitool_uninit(devi); - /* - * Uninitialize hotplug support on this bus. - */ - (void) pcihp_uninit(devi); + if (pcie_uninit(devi) != DDI_SUCCESS) + return (DDI_FAILURE); if (pcip->pci_fmcap & DDI_FM_ERRCB_CAPABLE) ddi_fm_handler_unregister(devi); @@ -961,53 +975,112 @@ npe_removechild(dev_info_t *dip) return (DDI_SUCCESS); } - -/* - * When retrofitting this module for pci_tools, functions such as open, close, - * and ioctl are now pulled into this module. Before this, the functions in - * the pcihp module were referenced directly. Now they are called or - * referenced through the pcihp cb_ops structure from functions in this module. - */ static int npe_open(dev_t *devp, int flags, int otyp, cred_t *credp) { - return ((pcihp_get_cb_ops())->cb_open(devp, flags, otyp, credp)); -} + minor_t minor = getminor(*devp); + int instance = PCI_MINOR_NUM_TO_INSTANCE(minor); + pci_state_t *pci_p = ddi_get_soft_state(npe_statep, instance); + int rv; -static int -npe_close(dev_t dev, int flags, int otyp, cred_t *credp) -{ - return ((pcihp_get_cb_ops())->cb_close(dev, flags, otyp, credp)); + /* + * Make sure the open is for the right file type. + */ + if (otyp != OTYP_CHR) + return (EINVAL); + + if (pci_p == NULL) + return (ENXIO); + + mutex_enter(&pci_p->pci_mutex); + switch (PCI_MINOR_NUM_TO_PCI_DEVNUM(minor)) { + case PCI_TOOL_REG_MINOR_NUM: + case PCI_TOOL_INTR_MINOR_NUM: + break; + default: + /* Handle devctl ioctls */ + rv = pcie_open(pci_p->pci_dip, devp, flags, otyp, credp); + mutex_exit(&pci_p->pci_mutex); + return (rv); + } + + /* Handle pcitool ioctls */ + if (flags & FEXCL) { + if (pci_p->pci_soft_state != PCI_SOFT_STATE_CLOSED) { + mutex_exit(&pci_p->pci_mutex); + cmn_err(CE_NOTE, "npe_open: busy"); + return (EBUSY); + } + pci_p->pci_soft_state = PCI_SOFT_STATE_OPEN_EXCL; + } else { + if (pci_p->pci_soft_state == PCI_SOFT_STATE_OPEN_EXCL) { + mutex_exit(&pci_p->pci_mutex); + cmn_err(CE_NOTE, "npe_open: busy"); + return (EBUSY); + } + pci_p->pci_soft_state = PCI_SOFT_STATE_OPEN; + } + mutex_exit(&pci_p->pci_mutex); + + return (0); } static int -npe_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp) +npe_close(dev_t dev, int flags, int otyp, cred_t *credp) { minor_t minor = getminor(dev); - int instance = PCIHP_AP_MINOR_NUM_TO_INSTANCE(minor); + int instance = PCI_MINOR_NUM_TO_INSTANCE(minor); pci_state_t *pci_p = ddi_get_soft_state(npe_statep, instance); - dev_info_t *dip; + int rv; if (pci_p == NULL) return (ENXIO); - dip = pci_p->pci_dip; + mutex_enter(&pci_p->pci_mutex); - return (pci_common_ioctl(dip, dev, cmd, arg, mode, credp, rvalp)); -} + switch (PCI_MINOR_NUM_TO_PCI_DEVNUM(minor)) { + case PCI_TOOL_REG_MINOR_NUM: + case PCI_TOOL_INTR_MINOR_NUM: + break; + default: + /* Handle devctl ioctls */ + rv = pcie_close(pci_p->pci_dip, dev, flags, otyp, credp); + mutex_exit(&pci_p->pci_mutex); + return (rv); + } -static int -npe_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, - int flags, char *name, caddr_t valuep, int *lengthp) -{ - return ((pcihp_get_cb_ops())->cb_prop_op(dev, dip, prop_op, flags, - name, valuep, lengthp)); + /* Handle pcitool ioctls */ + pci_p->pci_soft_state = PCI_SOFT_STATE_CLOSED; + mutex_exit(&pci_p->pci_mutex); + return (0); } static int -npe_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) +npe_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp) { - return (pcihp_info(dip, cmd, arg, result)); + minor_t minor = getminor(dev); + int instance = PCI_MINOR_NUM_TO_INSTANCE(minor); + pci_state_t *pci_p = ddi_get_soft_state(npe_statep, instance); + int ret = ENOTTY; + + if (pci_p == NULL) + return (ENXIO); + + switch (PCI_MINOR_NUM_TO_PCI_DEVNUM(minor)) { + case PCI_TOOL_REG_MINOR_NUM: + case PCI_TOOL_INTR_MINOR_NUM: + /* To handle pcitool related ioctls */ + ret = pci_common_ioctl(pci_p->pci_dip, dev, cmd, arg, mode, + credp, rvalp); + break; + default: + /* To handle devctl and hotplug related ioctls */ + ret = pcie_ioctl(pci_p->pci_dip, dev, cmd, arg, mode, credp, + rvalp); + break; + } + + return (ret); } /*ARGSUSED*/ |
