summaryrefslogtreecommitdiff
path: root/usr/src/uts/sun4
diff options
context:
space:
mode:
authorDaniel Ice <Daniel.Ice@Sun.COM>2010-03-01 20:56:35 -0800
committerDaniel Ice <Daniel.Ice@Sun.COM>2010-03-01 20:56:35 -0800
commit1a92841dfcb7cefb80e556d16000896fa3238091 (patch)
tree9d25ee9c50f2d546839976821bbc6121aa2c20ac /usr/src/uts/sun4
parentee97b7343f7aa60136a15b8f0258b30fb0d252c0 (diff)
downloadillumos-joyent-1a92841dfcb7cefb80e556d16000896fa3238091.tar.gz
6858637 System panics by accessing freed intr_vec_t when detaching the device.
6915092 race condition in px_add_intx_intr() may result in INO timeout for multi-pil configuration
Diffstat (limited to 'usr/src/uts/sun4')
-rw-r--r--usr/src/uts/sun4/io/px/px_ib.c19
-rw-r--r--usr/src/uts/sun4/io/px/px_intr.c44
2 files changed, 53 insertions, 10 deletions
diff --git a/usr/src/uts/sun4/io/px/px_ib.c b/usr/src/uts/sun4/io/px/px_ib.c
index 9355a15741..90fec6ae2c 100644
--- a/usr/src/uts/sun4/io/px/px_ib.c
+++ b/usr/src/uts/sun4/io/px/px_ib.c
@@ -699,14 +699,6 @@ px_ib_ino_rem_intr(px_t *px_p, px_ino_pil_t *ipil_p, px_ih_t *ih_p)
/* Disable the interrupt */
PX_INTR_DISABLE(px_p->px_dip, sysino);
- if (ipil_p->ipil_ih_size == 1) {
- if (ih_lst != ih_p)
- goto not_found;
-
- /* No need to set head/tail as ino_p will be freed */
- goto reset;
- }
-
/* Busy wait on pending interrupt */
for (start_time = gethrtime(); !panicstr &&
((ret = px_lib_intr_getstate(dip, sysino, &intr_state))
@@ -727,7 +719,8 @@ px_ib_ino_rem_intr(px_t *px_p, px_ino_pil_t *ipil_p, px_ih_t *ih_p)
* because of jabber we need to clear the pending state in case the
* jabber has gone away.
*/
- if (ino_p->ino_unclaimed_intrs > px_unclaimed_intr_max) {
+ if (ret == DDI_SUCCESS &&
+ ino_p->ino_unclaimed_intrs > px_unclaimed_intr_max) {
cmn_err(CE_WARN, "%s%d: px_ib_ino_rem_intr: "
"ino 0x%x has been unblocked",
ddi_driver_name(dip), ddi_get_instance(dip), ino);
@@ -743,6 +736,14 @@ px_ib_ino_rem_intr(px_t *px_p, px_ino_pil_t *ipil_p, px_ih_t *ih_p)
return (ret);
}
+ if (ipil_p->ipil_ih_size == 1) {
+ if (ih_lst != ih_p)
+ goto not_found;
+
+ /* No need to set head/tail as ino_p will be freed */
+ goto reset;
+ }
+
/* Search the link list for ih_p */
for (i = 0; (i < ipil_p->ipil_ih_size) &&
(ih_lst->ih_next != ih_p); i++, ih_lst = ih_lst->ih_next)
diff --git a/usr/src/uts/sun4/io/px/px_intr.c b/usr/src/uts/sun4/io/px/px_intr.c
index 4248faf4e4..50999acc39 100644
--- a/usr/src/uts/sun4/io/px/px_intr.c
+++ b/usr/src/uts/sun4/io/px/px_intr.c
@@ -952,6 +952,7 @@ px_add_intx_intr(dev_info_t *dip, dev_info_t *rdip,
px_ino_pil_t *ipil_p, *ipil_list;
int32_t weight;
int ret = DDI_SUCCESS;
+ cpuid_t curr_cpu;
ino = hdlp->ih_vector;
@@ -968,7 +969,7 @@ px_add_intx_intr(dev_info_t *dip, dev_info_t *rdip,
ino_p = px_ib_locate_ino(ib_p, ino);
ipil_list = ino_p ? ino_p->ino_ipil_p : NULL;
- /* Sharing ino */
+ /* Sharing the INO using a PIL that already exists */
if (ino_p && (ipil_p = px_ib_ino_locate_ipil(ino_p, hdlp->ih_pri))) {
if (px_ib_intr_locate_ih(ipil_p, rdip, hdlp->ih_inum, 0, 0)) {
DBG(DBG_A_INTX, dip, "px_add_intx_intr: "
@@ -988,6 +989,44 @@ px_add_intx_intr(dev_info_t *dip, dev_info_t *rdip,
goto ino_done;
}
+ /* Sharing the INO using a new PIL */
+ if (ipil_list != NULL) {
+ intr_state_t intr_state;
+ hrtime_t start_time;
+
+ /*
+ * disable INO to avoid lopil race condition with
+ * px_intx_intr
+ */
+
+ if ((ret = px_lib_intr_gettarget(dip, ino_p->ino_sysino,
+ &curr_cpu)) != DDI_SUCCESS) {
+ DBG(DBG_IB, dip,
+ "px_add_intx_intr px_intr_gettarget() failed\n");
+
+ goto fail1;
+ }
+
+ /* Disable the interrupt */
+ PX_INTR_DISABLE(dip, ino_p->ino_sysino);
+
+ /* Busy wait on pending interrupt */
+ for (start_time = gethrtime(); !panicstr &&
+ ((ret = px_lib_intr_getstate(dip, ino_p->ino_sysino,
+ &intr_state)) == DDI_SUCCESS) &&
+ (intr_state == INTR_DELIVERED_STATE); /* */) {
+ if (gethrtime() - start_time > px_intrpend_timeout) {
+ cmn_err(CE_WARN, "%s%d: px_add_intx_intr: "
+ "pending sysino 0x%lx(ino 0x%x) timeout",
+ ddi_driver_name(dip), ddi_get_instance(dip),
+ ino_p->ino_sysino, ino_p->ino_ino);
+
+ ret = DDI_FAILURE;
+ goto fail1;
+ }
+ }
+ }
+
if (hdlp->ih_pri == 0)
hdlp->ih_pri = pci_class_to_pil(rdip);
@@ -1025,6 +1064,9 @@ px_add_intx_intr(dev_info_t *dip, dev_info_t *rdip,
/* Enable interrupt */
px_ib_intr_enable(px_p, ino_p->ino_cpuid, ino);
+ } else {
+ /* Re-enable interrupt */
+ PX_INTR_ENABLE(dip, ino_p->ino_sysino, curr_cpu);
}
ino_done: