summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoregillett <none@none>2006-09-18 22:19:54 -0700
committeregillett <none@none>2006-09-18 22:19:54 -0700
commit950031854df8acd3acd298ff19ff10bc16e7eefd (patch)
tree92a0b35abe6a109c4b8639bd1efba4e56784c6df
parent0903b339f5e017fe3d097ff5b52694764d01f6b9 (diff)
downloadillumos-gate-onnv_49.tar.gz
6469461 Fix issues with multiple MSI-X interrupts on sparconnv_49
6472171 remove unnecessary shifting from px driver
-rw-r--r--usr/src/uts/common/io/pci_intr_lib.c69
-rw-r--r--usr/src/uts/common/sys/pci_intr_lib.h4
-rw-r--r--usr/src/uts/sun4/io/px/px_intr.c16
-rw-r--r--usr/src/uts/sun4/io/px/px_msiq.c8
-rw-r--r--usr/src/uts/sun4u/io/px/px_lib4u.c14
-rw-r--r--usr/src/uts/sun4v/io/px/px_lib4v.c8
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),