Mercurial > illumos > illumos-gate
changeset 2588:6ca5ef0f409c onnv_47
6453554 px driver MSI handler can cause eq_over
6454481 Freeing MSI/MSI-X interrupts is not ok
6459301 i_ddi_intr_devi_fini should check for interrupts in use
author | egillett |
---|---|
date | Mon, 21 Aug 2006 21:16:28 -0700 |
parents | 93d8b810a71d |
children | bab6bd68d0e5 |
files | usr/src/uts/common/os/ddi_intr.c usr/src/uts/common/os/ddi_intr_impl.c usr/src/uts/sun4/io/px/px.c usr/src/uts/sun4/io/px/px_intr.c usr/src/uts/sun4/io/px/px_lib.h usr/src/uts/sun4/io/px/px_msiq.c usr/src/uts/sun4/io/px/px_msiq.h usr/src/uts/sun4u/io/px/px_lib4u.c usr/src/uts/sun4v/io/px/px_lib4v.c |
diffstat | 9 files changed, 92 insertions(+), 65 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/os/ddi_intr.c Mon Aug 21 20:11:18 2006 -0700 +++ b/usr/src/uts/common/os/ddi_intr.c Mon Aug 21 21:16:28 2006 -0700 @@ -375,6 +375,9 @@ return (DDI_EINVAL); } + /* Set the number of interrupts to free */ + hdlp->ih_scratch1 = 1; + ret = i_ddi_intr_ops(hdlp->ih_dip, hdlp->ih_dip, DDI_INTROP_FREE, hdlp, NULL); @@ -387,14 +390,11 @@ i_ddi_intr_set_current_nintrs(hdlp->ih_dip, i_ddi_intr_get_current_nintrs(hdlp->ih_dip) - 1); - if (i_ddi_intr_get_current_nintrs(hdlp->ih_dip) == 0) { - i_ddi_intr_devi_fini(hdlp->ih_dip); - } else { - if (hdlp->ih_type & DDI_INTR_TYPE_FIXED) - i_ddi_set_intr_handle(hdlp->ih_dip, - hdlp->ih_inum, NULL); - } + if (hdlp->ih_type & DDI_INTR_TYPE_FIXED) + i_ddi_set_intr_handle(hdlp->ih_dip, + hdlp->ih_inum, NULL); + i_ddi_intr_devi_fini(hdlp->ih_dip); i_ddi_free_intr_phdl(hdlp); } rw_destroy(&hdlp->ih_rwlock);
--- a/usr/src/uts/common/os/ddi_intr_impl.c Mon Aug 21 20:11:18 2006 -0700 +++ b/usr/src/uts/common/os/ddi_intr_impl.c Mon Aug 21 21:16:28 2006 -0700 @@ -69,7 +69,8 @@ DDI_INTR_APIDBG((CE_CONT, "i_ddi_intr_devi_fini: dip %p\n", (void *)dip)); - if (DEVI(dip)->devi_intr_p == NULL) + if ((DEVI(dip)->devi_intr_p == NULL) || + i_ddi_intr_get_current_nintrs(dip)) return; /*
--- a/usr/src/uts/sun4/io/px/px.c Mon Aug 21 20:11:18 2006 -0700 +++ b/usr/src/uts/sun4/io/px/px.c Mon Aug 21 21:16:28 2006 -0700 @@ -394,6 +394,7 @@ break; } + px_msiq_resume(px_p); px_lib_resume(dip); (void) pcie_pwr_resume(dip); px_p->px_state = PX_ATTACHED;
--- a/usr/src/uts/sun4/io/px/px_intr.c Mon Aug 21 20:11:18 2006 -0700 +++ b/usr/src/uts/sun4/io/px/px_intr.c Mon Aug 21 21:16:28 2006 -0700 @@ -232,41 +232,48 @@ px_msiq_t *msiq_p = ino_p->ino_msiq_p; dev_info_t *dip = px_p->px_dip; msiq_rec_t msiq_rec, *msiq_rec_p = &msiq_rec; - msiqhead_t curr_msiq_rec_cnt, new_msiq_rec_cnt; + msiqhead_t new_head_index = msiq_p->msiq_curr_head_idx; + msiqhead_t *curr_head_p; + msiqtail_t curr_tail_index; msgcode_t msg_code; px_ih_t *ih_p; int i, ret; + ushort_t msiq_recs2process; DBG(DBG_MSIQ_INTR, dip, "px_msiq_intr: msiq_id =%x ino=%x pil=%x " "ih_size=%x ih_lst=%x\n", msiq_p->msiq_id, ino_p->ino_ino, ino_p->ino_pil, ino_p->ino_ih_size, ino_p->ino_ih_head); - /* Read current MSIQ head index */ - px_lib_msiq_gethead(dip, msiq_p->msiq_id, &curr_msiq_rec_cnt); - msiq_p->msiq_curr = (uint64_t)((caddr_t)msiq_p->msiq_base + - curr_msiq_rec_cnt * sizeof (msiq_rec_t)); - new_msiq_rec_cnt = curr_msiq_rec_cnt; + /* Read current MSIQ tail index */ + px_lib_msiq_gettail(dip, msiq_p->msiq_id, &curr_tail_index); - /* Read next MSIQ record */ - px_lib_get_msiq_rec(dip, msiq_p, msiq_rec_p); + if (curr_tail_index < new_head_index) + curr_tail_index += msiq_state_p->msiq_rec_cnt; /* - * Process current MSIQ record as long as record type - * field is non-zero. + * Calculate the number of recs to process by taking the difference + * between the head and tail pointers. For all records we always + * verify that we have a valid record type before we do any processing. + * If triggered, we should always have at least 1 valid record. */ - while (msiq_rec_p->msiq_rec_type) { + msiq_recs2process = curr_tail_index - new_head_index; + + DBG(DBG_MSIQ_INTR, dip, "px_msiq_intr: curr_head %x " + "rec2process %x\n", new_head_index, msiq_recs2process); + + curr_head_p = (msiqhead_t *)((caddr_t)msiq_p->msiq_base_p + + new_head_index * sizeof (msiq_rec_t)); + + for (i = 0; i < msiq_recs2process; i++) { + /* Read MSIQ record */ + px_lib_get_msiq_rec(dip, curr_head_p, msiq_rec_p); + DBG(DBG_MSIQ_INTR, dip, "px_msiq_intr: MSIQ RECORD, " "msiq_rec_type 0x%llx msiq_rec_rid 0x%llx\n", msiq_rec_p->msiq_rec_type, msiq_rec_p->msiq_rec_rid); - /* Get the pointer next EQ record */ - msiq_p->msiq_curr = (uint64_t) - ((caddr_t)msiq_p->msiq_curr + sizeof (msiq_rec_t)); - - /* Check for overflow condition */ - if (msiq_p->msiq_curr >= (uint64_t)((caddr_t)msiq_p->msiq_base + - msiq_state_p->msiq_rec_cnt * sizeof (msiq_rec_t))) - msiq_p->msiq_curr = msiq_p->msiq_base; + if (!msiq_rec_p->msiq_rec_type) + break; /* Check MSIQ record type */ switch (msiq_rec_p->msiq_rec_type) { @@ -343,34 +350,41 @@ DTRACE_PROBE4(interrupt__complete, dev_info_t, dip, void *, handler, caddr_t, arg1, int, ret); + + new_head_index++; } else { DBG(DBG_MSIQ_INTR, dip, "px_msiq_intr:" - "Not found matching MSIQ record\n"); + "No matching MSIQ record found\n"); + } +next_rec: + /* Get the pointer next EQ record */ + curr_head_p = (msiqhead_t *) + ((caddr_t)curr_head_p + sizeof (msiq_rec_t)); - /* px_spurintr(ino_p); */ - ino_p->ino_unclaimed++; - } - -next_rec: - new_msiq_rec_cnt++; + /* Check for overflow condition */ + if (curr_head_p >= (msiqhead_t *)((caddr_t)msiq_p->msiq_base_p + + msiq_state_p->msiq_rec_cnt * sizeof (msiq_rec_t))) + curr_head_p = (msiqhead_t *)msiq_p->msiq_base_p; /* Zero out msiq_rec_type field */ msiq_rec_p->msiq_rec_type = 0; - - /* Read next MSIQ record */ - px_lib_get_msiq_rec(dip, msiq_p, msiq_rec_p); } - DBG(DBG_MSIQ_INTR, dip, "px_msiq_intr: No of MSIQ recs processed %x\n", - (new_msiq_rec_cnt - curr_msiq_rec_cnt)); + DBG(DBG_MSIQ_INTR, dip, "px_msiq_intr: # of MSIQ recs processed %x\n", + (new_head_index - msiq_p->msiq_curr_head_idx)); + + if (new_head_index <= msiq_p->msiq_curr_head_idx) { + if (px_unclaimed_intr_block) { + return (px_spurintr(ino_p)); + } + } /* Update MSIQ head index with no of MSIQ records processed */ - if (new_msiq_rec_cnt > curr_msiq_rec_cnt) { - if (new_msiq_rec_cnt >= msiq_state_p->msiq_rec_cnt) - new_msiq_rec_cnt -= msiq_state_p->msiq_rec_cnt; + if (new_head_index >= msiq_state_p->msiq_rec_cnt) + new_head_index -= msiq_state_p->msiq_rec_cnt; - px_lib_msiq_sethead(dip, msiq_p->msiq_id, new_msiq_rec_cnt); - } + msiq_p->msiq_curr_head_idx = new_head_index; + px_lib_msiq_sethead(dip, msiq_p->msiq_id, new_head_index); /* Clear the pending state */ if (px_lib_intr_setstate(dip, ino_p->ino_sysino,
--- a/usr/src/uts/sun4/io/px/px_lib.h Mon Aug 21 20:11:18 2006 -0700 +++ b/usr/src/uts/sun4/io/px/px_lib.h Mon Aug 21 21:16:28 2006 -0700 @@ -117,9 +117,8 @@ msiqhead_t msiq_head); extern int px_lib_msiq_gettail(dev_info_t *dip, msiqid_t msiq_id, msiqtail_t *msiq_tail); -extern void px_lib_get_msiq_rec(dev_info_t *dip, px_msiq_t *msiq_p, +extern void px_lib_get_msiq_rec(dev_info_t *dip, msiqhead_t *msiq_head_p, msiq_rec_t *msiq_rec_p); - /* * MSI Functions: */
--- a/usr/src/uts/sun4/io/px/px_msiq.c Mon Aug 21 20:11:18 2006 -0700 +++ b/usr/src/uts/sun4/io/px/px_msiq.c Mon Aug 21 21:16:28 2006 -0700 @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -95,10 +94,8 @@ 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 = (uint64_t) + msiq_state_p->msiq_p[i].msiq_base_p = (msiqhead_t *) ((caddr_t)msiq_addr + (i * msiq_size)); - msiq_state_p->msiq_p[i].msiq_curr = - msiq_state_p->msiq_p[i].msiq_base; } if ((ret = px_lib_msiq_init(px_p->px_dip)) != DDI_SUCCESS) @@ -129,6 +126,20 @@ } /* + * px_msiq_resume() + */ +void +px_msiq_resume(px_t *px_p) +{ + px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; + int i; + + for (i = 0; i < msiq_state_p->msiq_cnt; i++) + (void) px_lib_msiq_gethead(px_p->px_dip, i, + &msiq_state_p->msiq_p[i].msiq_curr_head_idx); +} + +/* * px_msiq_alloc() */ int @@ -196,9 +207,8 @@ 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_curr = - msiq_state_p->msiq_p[i].msiq_base; msiq_state_p->msiq_p[i].msiq_state = MSIQ_STATE_FREE; + msiq_state_p->msiq_p[i].msiq_curr_head_idx = 0; break; } }
--- a/usr/src/uts/sun4/io/px/px_msiq.h Mon Aug 21 20:11:18 2006 -0700 +++ b/usr/src/uts/sun4/io/px/px_msiq.h Mon Aug 21 21:16:28 2006 -0700 @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -39,8 +38,8 @@ struct px_msiq { msiqid_t msiq_id; /* MSIQ ID */ uint_t msiq_state; /* MSIQ alloc state */ - msiqhead_t msiq_base; /* MSIQ base pointer */ - msiqtail_t msiq_curr; /* MSIQ Curr pointer */ + msiqhead_t msiq_curr_head_idx; /* MSIQ current head */ + msiqhead_t *msiq_base_p; /* MSIQ base pointer */ }; #define MSIQ_STATE_FREE 0x1 @@ -90,6 +89,7 @@ extern int px_msiq_attach(px_t *px_p); extern void px_msiq_detach(px_t *px_p); +extern void px_msiq_resume(px_t *px_p); extern int px_msiq_alloc(px_t *px_p, msiq_rec_type_t rec_type, msiqid_t *msiq_id_p);
--- a/usr/src/uts/sun4u/io/px/px_lib4u.c Mon Aug 21 20:11:18 2006 -0700 +++ b/usr/src/uts/sun4u/io/px/px_lib4u.c Mon Aug 21 21:16:28 2006 -0700 @@ -922,9 +922,10 @@ /*ARGSUSED*/ void -px_lib_get_msiq_rec(dev_info_t *dip, px_msiq_t *msiq_p, msiq_rec_t *msiq_rec_p) +px_lib_get_msiq_rec(dev_info_t *dip, msiqhead_t *msiq_head_p, + msiq_rec_t *msiq_rec_p) { - eq_rec_t *eq_rec_p = (eq_rec_t *)msiq_p->msiq_curr; + eq_rec_t *eq_rec_p = (eq_rec_t *)msiq_head_p; DBG(DBG_LIB_MSIQ, dip, "px_lib_get_msiq_rec: dip 0x%p eq_rec_p 0x%p\n", dip, eq_rec_p);
--- a/usr/src/uts/sun4v/io/px/px_lib4v.c Mon Aug 21 20:11:18 2006 -0700 +++ b/usr/src/uts/sun4v/io/px/px_lib4v.c Mon Aug 21 21:16:28 2006 -0700 @@ -777,9 +777,10 @@ /*ARGSUSED*/ void -px_lib_get_msiq_rec(dev_info_t *dip, px_msiq_t *msiq_p, msiq_rec_t *msiq_rec_p) +px_lib_get_msiq_rec(dev_info_t *dip, msiqhead_t *msiq_head_p, + msiq_rec_t *msiq_rec_p) { - msiq_rec_t *curr_msiq_rec_p = (msiq_rec_t *)msiq_p->msiq_curr; + msiq_rec_t *curr_msiq_rec_p = (msiq_rec_t *)msiq_head_p; DBG(DBG_LIB_MSIQ, dip, "px_lib_get_msiq_rec: dip 0x%p\n", dip);