diff options
-rw-r--r-- | usr/src/uts/common/io/pci_intr_lib.c | 69 | ||||
-rw-r--r-- | usr/src/uts/common/sys/pci_intr_lib.h | 4 | ||||
-rw-r--r-- | usr/src/uts/sun4/io/px/px_intr.c | 16 | ||||
-rw-r--r-- | usr/src/uts/sun4/io/px/px_msiq.c | 8 | ||||
-rw-r--r-- | usr/src/uts/sun4u/io/px/px_lib4u.c | 14 | ||||
-rw-r--r-- | usr/src/uts/sun4v/io/px/px_lib4v.c | 8 |
6 files changed, 50 insertions, 69 deletions
diff --git a/usr/src/uts/common/io/pci_intr_lib.c b/usr/src/uts/common/io/pci_intr_lib.c index e5e9b9a421..76019ca404 100644 --- a/usr/src/uts/common/io/pci_intr_lib.c +++ b/usr/src/uts/common/io/pci_intr_lib.c @@ -240,11 +240,11 @@ pci_msi_unconfigure(dev_info_t *rdip, int type, int inum) ushort_t msi_ctrl, caps_ptr; ddi_acc_handle_t h; - DDI_INTR_NEXDBG((CE_CONT, "pci_msi_unconfigure: rdip = 0x%p\n", - (void *)rdip)); + DDI_INTR_NEXDBG((CE_CONT, "pci_msi_unconfigure: rdip = 0x%p type 0x%x " + "inum 0x%x\n", (void *)rdip, type, inum)); if (pci_get_msi_ctrl(rdip, type, &msi_ctrl, &caps_ptr, &h) != - DDI_SUCCESS) + DDI_SUCCESS) return (DDI_FAILURE); if (type == DDI_INTR_TYPE_MSI) { @@ -278,7 +278,8 @@ pci_msi_unconfigure(dev_info_t *rdip, int type, int inum) ddi_put32(msix_p->msix_tbl_hdl, (uint32_t *)(off + PCI_MSIX_DATA_OFFSET), 0); - ddi_put64(msix_p->msix_tbl_hdl, (uint64_t *)off, 0); + ddi_put64(msix_p->msix_tbl_hdl, + (uint64_t *)(off + PCI_MSIX_LOWER_ADDR_OFFSET), 0); } pci_config_teardown(&h); @@ -322,15 +323,19 @@ pci_is_msi_enabled(dev_info_t *rdip, int type) * * This function sets the MSI_ENABLE bit in the capability structure * (for MSI) and MSIX_ENABLE bit in the MSI-X capability structure. + * + * NOTE: It is the nexus driver's responsibility to clear the MSI/X + * interrupt's mask bit in the MSI/X capability structure before the + * interrupt can be used. */ int -pci_msi_enable_mode(dev_info_t *rdip, int type, int inum) +pci_msi_enable_mode(dev_info_t *rdip, int type) { ushort_t caps_ptr, msi_ctrl; ddi_acc_handle_t cfg_hdle; - DDI_INTR_NEXDBG((CE_CONT, "pci_msi_enable_mode: rdip = 0x%p, " - "inum = 0x%x\n", (void *)rdip, inum)); + DDI_INTR_NEXDBG((CE_CONT, "pci_msi_enable_mode: rdip = 0x%p\n", + (void *)rdip)); if (pci_get_msi_ctrl(rdip, type, &msi_ctrl, &caps_ptr, &cfg_hdle) != DDI_SUCCESS) @@ -344,28 +349,12 @@ pci_msi_enable_mode(dev_info_t *rdip, int type, int inum) PCI_CAP_PUT16(cfg_hdle, NULL, caps_ptr, PCI_MSI_CTRL, msi_ctrl); } else if (type == DDI_INTR_TYPE_MSIX) { - uintptr_t off; - ddi_intr_msix_t *msix_p; - if (msi_ctrl & PCI_MSIX_ENABLE_BIT) goto finished; msi_ctrl |= PCI_MSIX_ENABLE_BIT; PCI_CAP_PUT16(cfg_hdle, NULL, caps_ptr, PCI_MSIX_CTRL, - msi_ctrl); - - msix_p = i_ddi_get_msix(rdip); - - /* Offset into the "inum"th entry in the MSI-X table */ - off = (uintptr_t)msix_p->msix_tbl_addr + (inum * - PCI_MSIX_VECTOR_SIZE) + PCI_MSIX_VECTOR_CTRL_OFFSET; - - /* Clear the Mask bit */ - ddi_put32(msix_p->msix_tbl_hdl, (uint32_t *)off, 0x0); - - DDI_INTR_NEXDBG((CE_CONT, "pci_msi_enable: " - "msix_vector_mask 0x%x\n", - ddi_get32(msix_p->msix_tbl_hdl, (uint32_t *)off))); + msi_ctrl); } finished: @@ -382,15 +371,27 @@ finished: * * This function resets the MSI_ENABLE bit in the capability structure * (for MSI) and MSIX_ENABLE bit in the MSI-X capability structure. + * + * NOTE: It is the nexus driver's responsibility to set the MSI/X + * interrupt's mask bit in the MSI/X capability structure before the + * interrupt can be disabled. */ int -pci_msi_disable_mode(dev_info_t *rdip, int type, int inum) +pci_msi_disable_mode(dev_info_t *rdip, int type, uint_t flags) { ushort_t caps_ptr, msi_ctrl; ddi_acc_handle_t cfg_hdle; DDI_INTR_NEXDBG((CE_CONT, "pci_msi_disable_mode: rdip = 0x%p " - "inum = 0x%x\n", (void *)rdip, inum)); + "flags = 0x%x\n", (void *)rdip, flags)); + + /* + * Do not turn off the master enable bit if other interrupts are + * still active. + */ + if ((flags != DDI_INTR_FLAG_BLOCK) && + ((i_ddi_intr_get_current_nintrs(rdip) - 1) > 0)) + return (DDI_SUCCESS); if (pci_get_msi_ctrl(rdip, type, &msi_ctrl, &caps_ptr, &cfg_hdle) != DDI_SUCCESS) @@ -403,20 +404,12 @@ pci_msi_disable_mode(dev_info_t *rdip, int type, int inum) msi_ctrl &= ~PCI_MSI_ENABLE_BIT; PCI_CAP_PUT16(cfg_hdle, NULL, caps_ptr, PCI_MSI_CTRL, msi_ctrl); } else if (type == DDI_INTR_TYPE_MSIX) { - uintptr_t off; - ddi_intr_msix_t *msix_p; - if (!(msi_ctrl & PCI_MSIX_ENABLE_BIT)) goto finished; - msix_p = i_ddi_get_msix(rdip); - - /* Offset into the "inum"th entry in the MSI-X table */ - off = (uintptr_t)msix_p->msix_tbl_addr + (inum * - PCI_MSIX_VECTOR_SIZE) + PCI_MSIX_VECTOR_CTRL_OFFSET; - - /* Set the Mask bit */ - ddi_put32(msix_p->msix_tbl_hdl, (uint32_t *)off, 0x1); + msi_ctrl &= ~PCI_MSIX_ENABLE_BIT; + PCI_CAP_PUT16(cfg_hdle, NULL, caps_ptr, PCI_MSIX_CTRL, + msi_ctrl); } finished: @@ -1107,7 +1100,7 @@ pci_intx_get_pending(dev_info_t *dip, int *pendingp) /* * pci_devclass_to_ipl: * translate from device class to ipl - * NOTE: This function is added here as pci_intx_get_ispec() + * NOTE: This function is added here as pci_intx_get_ispec() * calls this to figure out the priority. * It is moved over from x86 pci.c */ diff --git a/usr/src/uts/common/sys/pci_intr_lib.h b/usr/src/uts/common/sys/pci_intr_lib.h index 35d7e8b079..f1eea6488a 100644 --- a/usr/src/uts/common/sys/pci_intr_lib.h +++ b/usr/src/uts/common/sys/pci_intr_lib.h @@ -37,8 +37,8 @@ extern int pci_msi_configure(dev_info_t *rdip, int type, int count, int inum, uint64_t addr, uint64_t data); extern int pci_msi_unconfigure(dev_info_t *rdip, int type, int inum); extern int pci_is_msi_enabled(dev_info_t *rdip, int type); -extern int pci_msi_enable_mode(dev_info_t *rdip, int type, int inum); -extern int pci_msi_disable_mode(dev_info_t *rdip, int type, int inum); +extern int pci_msi_enable_mode(dev_info_t *rdip, int type); +extern int pci_msi_disable_mode(dev_info_t *rdip, int type, uint_t flags); extern int pci_msi_set_mask(dev_info_t *rdip, int type, int inum); extern int pci_msi_clr_mask(dev_info_t *rdip, int type, int inum); extern int pci_msi_get_pending(dev_info_t *rdip, int type, int inum, diff --git a/usr/src/uts/sun4/io/px/px_intr.c b/usr/src/uts/sun4/io/px/px_intr.c index 4530ebb22a..e0cd37a8c8 100644 --- a/usr/src/uts/sun4/io/px/px_intr.c +++ b/usr/src/uts/sun4/io/px/px_intr.c @@ -677,7 +677,7 @@ px_msix_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op, break; case DDI_INTROP_FREE: - (void) pci_msi_disable_mode(rdip, hdlp->ih_type, hdlp->ih_inum); + (void) pci_msi_disable_mode(rdip, hdlp->ih_type, NULL); (void) pci_msi_unconfigure(rdip, hdlp->ih_type, hdlp->ih_inum); if (hdlp->ih_type == DDI_INTR_TYPE_MSI) @@ -761,16 +761,18 @@ msi_free: PCI_MSI_VALID)) != DDI_SUCCESS) return (ret); - if (pci_is_msi_enabled(rdip, hdlp->ih_type) != DDI_SUCCESS) { + if ((pci_is_msi_enabled(rdip, hdlp->ih_type) != DDI_SUCCESS) || + (hdlp->ih_type == DDI_INTR_TYPE_MSIX)) { nintrs = i_ddi_intr_get_current_nintrs(hdlp->ih_dip); if ((ret = pci_msi_configure(rdip, hdlp->ih_type, nintrs, hdlp->ih_inum, msi_addr, - msi_num & ~(nintrs - 1))) != DDI_SUCCESS) + hdlp->ih_type == DDI_INTR_TYPE_MSIX ? + msi_num : msi_num & ~(nintrs - 1))) != DDI_SUCCESS) return (ret); - if ((ret = pci_msi_enable_mode(rdip, hdlp->ih_type, - hdlp->ih_inum)) != DDI_SUCCESS) + if ((ret = pci_msi_enable_mode(rdip, hdlp->ih_type)) + != DDI_SUCCESS) return (ret); } @@ -838,14 +840,14 @@ msi_free: return (ret); } - ret = pci_msi_enable_mode(rdip, hdlp->ih_type, hdlp->ih_inum); + ret = pci_msi_enable_mode(rdip, hdlp->ih_type); break; case DDI_INTROP_BLOCKDISABLE: nintrs = i_ddi_intr_get_current_nintrs(hdlp->ih_dip); msi_num = hdlp->ih_vector; if ((ret = pci_msi_disable_mode(rdip, hdlp->ih_type, - hdlp->ih_inum)) != DDI_SUCCESS) + hdlp->ih_cap & DDI_INTR_FLAG_BLOCK)) != DDI_SUCCESS) return (ret); for (i = 0; i < nintrs; i++, msi_num++) { diff --git a/usr/src/uts/sun4/io/px/px_msiq.c b/usr/src/uts/sun4/io/px/px_msiq.c index 2c27f30422..8150274c93 100644 --- a/usr/src/uts/sun4/io/px/px_msiq.c +++ b/usr/src/uts/sun4/io/px/px_msiq.c @@ -49,7 +49,6 @@ int px_msiq_attach(px_t *px_p) { px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; - caddr_t msiq_addr; size_t msiq_size; int i, ret = DDI_SUCCESS; @@ -81,21 +80,17 @@ px_msiq_attach(px_t *px_p) mutex_init(&msiq_state_p->msiq_mutex, NULL, MUTEX_DRIVER, NULL); msiq_state_p->msiq_p = kmem_zalloc(msiq_state_p->msiq_cnt * sizeof (px_msiq_t), KM_SLEEP); - msiq_size = msiq_state_p->msiq_rec_cnt * sizeof (msiq_rec_t); msiq_state_p->msiq_buf_p = kmem_zalloc(msiq_state_p->msiq_cnt * msiq_size, KM_SLEEP); - msiq_addr = (caddr_t)(((uint64_t)msiq_state_p->msiq_buf_p + - (MMU_PAGE_SIZE - 1)) >> MMU_PAGE_SHIFT << MMU_PAGE_SHIFT); - for (i = 0; i < msiq_state_p->msiq_cnt; i++) { msiq_state_p->msiq_p[i].msiq_id = msiq_state_p->msiq_1st_msiq_id + i; msiq_state_p->msiq_p[i].msiq_state = MSIQ_STATE_FREE; msiq_state_p->msiq_p[i].msiq_base_p = (msiqhead_t *) - ((caddr_t)msiq_addr + (i * msiq_size)); + ((caddr_t)msiq_state_p->msiq_buf_p + (i * msiq_size)); } if ((ret = px_lib_msiq_init(px_p->px_dip)) != DDI_SUCCESS) @@ -208,7 +203,6 @@ px_msiq_free(px_t *px_p, msiqid_t msiq_id) for (i = 0; i < msiq_state_p->msiq_cnt; i++) { if (msiq_state_p->msiq_p[i].msiq_id == msiq_id) { msiq_state_p->msiq_p[i].msiq_state = MSIQ_STATE_FREE; - msiq_state_p->msiq_p[i].msiq_curr_head_idx = 0; break; } } diff --git a/usr/src/uts/sun4u/io/px/px_lib4u.c b/usr/src/uts/sun4u/io/px/px_lib4u.c index 68d6caf1ed..65dda707c4 100644 --- a/usr/src/uts/sun4u/io/px/px_lib4u.c +++ b/usr/src/uts/sun4u/io/px/px_lib4u.c @@ -664,7 +664,6 @@ px_lib_msiq_init(dev_info_t *dip) px_t *px_p = DIP_TO_STATE(dip); pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p; px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; - caddr_t msiq_addr; px_dvma_addr_t pg_index; size_t size; int ret; @@ -680,9 +679,6 @@ px_lib_msiq_init(dev_info_t *dip) * entry. Note: The size of the mapping is assumed to be a multiple * of the page size. */ - msiq_addr = (caddr_t)(((uint64_t)msiq_state_p->msiq_buf_p + - (MMU_PAGE_SIZE - 1)) >> MMU_PAGE_SHIFT << MMU_PAGE_SHIFT); - size = msiq_state_p->msiq_cnt * msiq_state_p->msiq_rec_cnt * sizeof (msiq_rec_t); @@ -696,8 +692,8 @@ px_lib_msiq_init(dev_info_t *dip) MMU_BTOP((ulong_t)pxu_p->msiq_mapped_p)); if ((ret = px_lib_iommu_map(px_p->px_dip, PCI_TSBID(0, pg_index), - MMU_BTOP(size), PCI_MAP_ATTR_WRITE, (void *)msiq_addr, 0, - MMU_MAP_BUF)) != DDI_SUCCESS) { + MMU_BTOP(size), PCI_MAP_ATTR_WRITE, msiq_state_p->msiq_buf_p, + 0, MMU_MAP_BUF)) != DDI_SUCCESS) { DBG(DBG_LIB_MSIQ, dip, "hvio_msiq_init failed, ret 0x%lx\n", ret); @@ -749,16 +745,14 @@ px_lib_msiq_info(dev_info_t *dip, msiqid_t msiq_id, r_addr_t *ra_p, { px_t *px_p = DIP_TO_STATE(dip); px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; - uint64_t *msiq_addr; size_t msiq_size; DBG(DBG_LIB_MSIQ, dip, "px_msiq_info: dip 0x%p msiq_id 0x%x\n", dip, msiq_id); - msiq_addr = (uint64_t *)(((uint64_t)msiq_state_p->msiq_buf_p + - (MMU_PAGE_SIZE - 1)) >> MMU_PAGE_SHIFT << MMU_PAGE_SHIFT); msiq_size = msiq_state_p->msiq_rec_cnt * sizeof (msiq_rec_t); - ra_p = (r_addr_t *)((caddr_t)msiq_addr + (msiq_id * msiq_size)); + ra_p = (r_addr_t *)((caddr_t)msiq_state_p->msiq_buf_p + + (msiq_id * msiq_size)); *msiq_rec_cnt_p = msiq_state_p->msiq_rec_cnt; diff --git a/usr/src/uts/sun4v/io/px/px_lib4v.c b/usr/src/uts/sun4v/io/px/px_lib4v.c index d5aa1139be..15ffbb4f50 100644 --- a/usr/src/uts/sun4v/io/px/px_lib4v.c +++ b/usr/src/uts/sun4v/io/px/px_lib4v.c @@ -547,7 +547,7 @@ px_lib_msiq_init(dev_info_t *dip) { px_t *px_p = DIP_TO_STATE(dip); px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; - uint64_t *msiq_addr, ra; + r_addr_t ra; size_t msiq_size; uint_t rec_cnt; int i, err = DDI_SUCCESS; @@ -555,13 +555,11 @@ px_lib_msiq_init(dev_info_t *dip) DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_init: dip 0x%p\n", dip); - msiq_addr = (uint64_t *)(((uint64_t)msiq_state_p->msiq_buf_p + - (MMU_PAGE_SIZE - 1)) >> MMU_PAGE_SHIFT << MMU_PAGE_SHIFT); - msiq_size = msiq_state_p->msiq_rec_cnt * sizeof (msiq_rec_t); for (i = 0; i < msiq_state_p->msiq_cnt; i++) { - ra = (r_addr_t)va_to_pa((caddr_t)msiq_addr + (i * msiq_size)); + ra = (r_addr_t)va_to_pa((caddr_t)msiq_state_p->msiq_buf_p + + (i * msiq_size)); if ((ret = hvio_msiq_conf(DIP_TO_HANDLE(dip), (i + msiq_state_p->msiq_1st_msiq_id), |