Hi, 2017-03-01 13:30 GMT+09:00 Kimihiro Nonaka <nona...@gmail.com>:
> 2017-03-01 3:21 GMT+09:00 Yorick Hardy <yorickha...@gmail.com>: > >> It is not obvious to me why the MSI changes were problematic. >> Do you have any ideas what went wrong? > > It seem necessary to implement pci_enable_msi() and pci_disable_msi(). > I tried again to write a new patch. > Could you try it? Updated the patch. Regards, -- Kimihiro Nonaka
diff --git a/sys/external/bsd/drm2/dist/drm/nouveau/core/subdev/mc/nouveau_subdev_mc_base.c b/sys/external/bsd/drm2/dist/drm/nouveau/core/subdev/mc/nouveau_subdev_mc_base.c index 860690054a7..31282f88f49 100644 --- a/sys/external/bsd/drm2/dist/drm/nouveau/core/subdev/mc/nouveau_subdev_mc_base.c +++ b/sys/external/bsd/drm2/dist/drm/nouveau/core/subdev/mc/nouveau_subdev_mc_base.c @@ -30,10 +30,13 @@ __KERNEL_RCSID(0, "$NetBSD: nouveau_subdev_mc_base.c,v 1.5 2015/10/22 23:17:08 j #include <subdev/mc.h> #include <core/option.h> -#if defined(__NetBSD__) && defined(__arm__) +#if defined(__NetBSD__) +#include <drm/drmP.h> +#if defined(__arm__) /* XXX nouveau platform kludge */ #include <arm/nvidia/tegra_intr.h> #endif +#endif /* __NetBSD__ */ static inline u32 nouveau_mc_intr_mask(struct nouveau_mc *pmc) @@ -114,7 +117,8 @@ _nouveau_mc_dtor(struct nouveau_object *object) struct nouveau_mc *pmc = (void *)object; #if defined(__NetBSD__) if (nv_device_is_pci(device)) { - pci_intr_disestablish(device->pdev->pd_pa.pa_pc, pmc->irq_cookie); + struct drm_device *dev = pci_get_drvdata(device->pdev); + (*dev->driver->bus->irq_uninstall)(dev, pmc->irq_cookie); #if defined(__arm__) } else { intr_disestablish(pmc->irq_cookie); @@ -175,16 +179,12 @@ nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine, #if defined(__NetBSD__) if (nv_device_is_pci(device)) { - const pci_chipset_tag_t pc = device->pdev->pd_pa.pa_pc; - pci_intr_handle_t ih; - - if (pci_intr_map(&device->pdev->pd_pa, &ih)) - return -EIO; - - pmc->irq_cookie = pci_intr_establish(pc, ih, IPL_VM, - &nouveau_mc_intr, pmc); - if (pmc->irq_cookie == NULL) - return -EIO; + struct drm_device *dev = pci_get_drvdata(device->pdev); + ret = (*dev->driver->bus->irq_install)(dev, nouveau_mc_intr, + IRQF_SHARED, "nouveau", pmc, + (struct drm_bus_irq_cookie **)&pmc->irq_cookie); + if (ret < 0) + return ret; #if defined (__arm__) } else { pmc->irq_cookie = intr_establish(TEGRA_INTR_GPU, diff --git a/sys/external/bsd/drm2/include/linux/pci.h b/sys/external/bsd/drm2/include/linux/pci.h index d7d153deb3d..d9c6eb38a8f 100644 --- a/sys/external/bsd/drm2/include/linux/pci.h +++ b/sys/external/bsd/drm2/include/linux/pci.h @@ -155,6 +155,7 @@ struct pci_dev { uint8_t revision; uint32_t class; bool msi_enabled; + pci_intr_handle_t *intr_handles; }; static inline device_t @@ -289,19 +290,28 @@ pci_write_config_byte(struct pci_dev *pdev, int reg, uint8_t value) return 0; } -/* - * XXX pci msi - */ static inline int pci_enable_msi(struct pci_dev *pdev) { - return -ENOSYS; + const struct pci_attach_args *const pa = &pdev->pd_pa; + + if (pci_msi_alloc_exact(pa, &pdev->intr_handles, 1)) + return -EINVAL; + + pdev->msi_enabled = 1; + return 0; } static inline void pci_disable_msi(struct pci_dev *pdev __unused) { - KASSERT(pdev->msi_enabled); + const struct pci_attach_args *const pa = &pdev->pd_pa; + + if (pdev->intr_handles != NULL) { + pci_intr_release(pa->pa_pc, pdev->intr_handles, 1); + pdev->intr_handles = NULL; + } + pdev->msi_enabled = 0; } static inline void diff --git a/sys/external/bsd/drm2/pci/drm_pci.c b/sys/external/bsd/drm2/pci/drm_pci.c index ddfa79f445f..caa1bd6694b 100644 --- a/sys/external/bsd/drm2/pci/drm_pci.c +++ b/sys/external/bsd/drm2/pci/drm_pci.c @@ -40,6 +40,11 @@ __KERNEL_RCSID(0, "$NetBSD: drm_pci.c,v 1.15 2017/02/27 23:52:05 nonaka Exp $"); #include <drm/drmP.h> +struct drm_bus_irq_cookie { + pci_intr_handle_t *intr_handles; + void *ih_cookie; +}; + static int drm_pci_get_irq(struct drm_device *); static int drm_pci_irq_install(struct drm_device *, irqreturn_t (*)(void *), int, const char *, void *, @@ -228,40 +233,48 @@ drm_pci_get_irq(struct drm_device *dev) static int drm_pci_irq_install(struct drm_device *dev, irqreturn_t (*handler)(void *), - int flags, const char *name, void *arg, - struct drm_bus_irq_cookie **cookiep) + int flags, const char *name, void *arg, struct drm_bus_irq_cookie **cookiep) { const struct pci_attach_args *const pa = drm_pci_attach_args(dev); - pci_intr_handle_t ih; const char *intrstr; - void *ih_cookie; char intrbuf[PCI_INTRSTR_LEN]; + struct drm_bus_irq_cookie *irq_cookie; + + irq_cookie = kmem_alloc(sizeof(*irq_cookie), KM_SLEEP); + if (irq_cookie == NULL) + return -ENOMEM; + + if (dev->pdev->msi_enabled) { + irq_cookie->intr_handles = dev->pdev->intr_handles; + dev->pdev->intr_handles = NULL; + } else { + if (pci_intx_alloc(pa, &irq_cookie->intr_handles)) + return -ENOENT; + } - if (pci_intr_map(pa, &ih)) - return -ENOENT; - - intrstr = pci_intr_string(pa->pa_pc, ih, intrbuf, sizeof(intrbuf)); - ih_cookie = pci_intr_establish(pa->pa_pc, ih, IPL_DRM, handler, arg); - if (ih_cookie == NULL) { + intrstr = pci_intr_string(pa->pa_pc, irq_cookie->intr_handles[0], + intrbuf, sizeof(intrbuf)); + irq_cookie->ih_cookie = pci_intr_establish_xname(pa->pa_pc, + irq_cookie->intr_handles[0], IPL_DRM, handler, arg, name); + if (irq_cookie->ih_cookie == NULL) { aprint_error_dev(dev->dev, - "couldn't establish interrupt at %s (%s)\n", - intrstr, name); + "couldn't establish interrupt at %s (%s)\n", intrstr, name); return -ENOENT; } - aprint_normal_dev(dev->dev, "interrupting at %s (%s)\n", - intrstr, name); - *cookiep = (struct drm_bus_irq_cookie *)ih_cookie; + aprint_normal_dev(dev->dev, "interrupting at %s (%s)\n", intrstr, name); + *cookiep = irq_cookie; return 0; } static void -drm_pci_irq_uninstall(struct drm_device *dev, - struct drm_bus_irq_cookie *cookie) +drm_pci_irq_uninstall(struct drm_device *dev, struct drm_bus_irq_cookie *cookie) { const struct pci_attach_args *pa = drm_pci_attach_args(dev); - pci_intr_disestablish(pa->pa_pc, (void *)cookie); + pci_intr_disestablish(pa->pa_pc, cookie->ih_cookie); + pci_intr_release(pa->pa_pc, cookie->intr_handles, 1); + kmem_free(cookie, sizeof(*cookie)); } static const char *