summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarius <marius@FreeBSD.org>2007-06-16 23:46:41 +0000
committermarius <marius@FreeBSD.org>2007-06-16 23:46:41 +0000
commitc27e004e369394368708818d1dab95e1e1f31267 (patch)
tree00ee173f294abde3abdc57e22d5c734a80ec4c9e
parent5956b5bc21c96b25c05bcdb8b76e1fd590072f14 (diff)
downloadFreeBSD-src-c27e004e369394368708818d1dab95e1e1f31267.zip
FreeBSD-src-c27e004e369394368708818d1dab95e1e1f31267.tar.gz
- Use the newly introduced pcib_mtx spin lock to lock psycho_ce(),
allowing it to be a filter/"fast" handler. Locking the interrupt handlers with a spin lock is mainly a requirement in schizo(4) but as we ought to register the spin lock anyway it should not hurt to take advantage of it in psycho(4). - Pass both a driver_filter_t and a driver_intr_t argument to psycho_set_intr(), allowing to get rid of the FAST interrupt flag hack. - Don't register the over-temperature interrupt handler as filter/ "fast" handler so shutdown_nice() can acquire the process lock. - Use bus_{read,write}_8() instead of bus_space_{read,write}_8() in order to get rid of sc_bushandle and sc_bustag in the softc. - Correct the debug output for adjusting the subordinate bus number. - Remove the banal and outdated above psycho_filter_stub(). - Fix some white space nits.
-rw-r--r--sys/sparc64/pci/psycho.c108
-rw-r--r--sys/sparc64/pci/psychovar.h6
2 files changed, 54 insertions, 60 deletions
diff --git a/sys/sparc64/pci/psycho.c b/sys/sparc64/pci/psycho.c
index 195252f..4dcccef 100644
--- a/sys/sparc64/pci/psycho.c
+++ b/sys/sparc64/pci/psycho.c
@@ -46,8 +46,10 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <sys/kdb.h>
#include <sys/kernel.h>
+#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/module.h>
+#include <sys/mutex.h>
#include <sys/pcpu.h>
#include <sys/reboot.h>
@@ -78,8 +80,8 @@ __FBSDID("$FreeBSD$");
static const struct psycho_desc *psycho_find_desc(const struct psycho_desc *,
const char *);
static const struct psycho_desc *psycho_get_desc(device_t);
-static void psycho_set_intr(struct psycho_softc *, int, bus_addr_t, int,
- driver_filter_t);
+static void psycho_set_intr(struct psycho_softc *, int, bus_addr_t,
+ driver_filter_t, driver_intr_t);
static int psycho_find_intrmap(struct psycho_softc *, int, bus_addr_t *,
bus_addr_t *, u_long *);
static driver_filter_t psycho_filter_stub;
@@ -91,7 +93,7 @@ static driver_filter_t psycho_ue;
static driver_filter_t psycho_ce;
static driver_filter_t psycho_pci_bus;
static driver_filter_t psycho_powerfail;
-static driver_filter_t psycho_overtemp;
+static driver_intr_t psycho_overtemp;
#ifdef PSYCHO_MAP_WAKEUP
static driver_filter_t psycho_wakeup;
#endif
@@ -171,7 +173,7 @@ SLIST_HEAD(, psycho_softc) psycho_softcs =
struct psycho_clr {
struct psycho_softc *pci_sc;
bus_addr_t pci_clr; /* clear register */
- driver_filter_t *pci_filter;
+ driver_filter_t *pci_filter; /* filter to call */
driver_intr_t *pci_handler; /* handler to call */
void *pci_arg; /* argument for the handler */
void *pci_cookie; /* parent bus int. cookie */
@@ -182,9 +184,9 @@ struct psycho_clr {
};
#define PSYCHO_READ8(sc, off) \
- bus_space_read_8((sc)->sc_bustag, (sc)->sc_bushandle, (off))
+ bus_read_8((sc)->sc_mem_res, (off))
#define PSYCHO_WRITE8(sc, off, v) \
- bus_space_write_8((sc)->sc_bustag, (sc)->sc_bushandle, (off), (v))
+ bus_write_8((sc)->sc_mem_res, (off), (v))
#define PCICTL_READ8(sc, off) \
PSYCHO_READ8((sc), (sc)->sc_pcictl + (off))
#define PCICTL_WRITE8(sc, off, v) \
@@ -219,14 +221,6 @@ struct psycho_clr {
* providing two PCI buses.
*/
-#define FAST 0x66600000
-
-#ifdef DEBUGGER_ON_POWERFAIL
-#define PSYCHO_PWRFAIL_INT_FLAGS FAST
-#else
-#define PSYCHO_PWRFAIL_INT_FLAGS 0
-#endif
-
#define OFW_PCI_TYPE "pci"
struct psycho_desc {
@@ -346,8 +340,6 @@ psycho_attach(device_t dev)
RF_ACTIVE);
if (sc->sc_mem_res == NULL)
panic("%s: could not allocate registers", __func__);
- sc->sc_bustag = rman_get_bustag(sc->sc_mem_res);
- sc->sc_bushandle = rman_get_bushandle(sc->sc_mem_res);
/*
* Match other Psycho's that are already configured against
@@ -363,6 +355,17 @@ psycho_attach(device_t dev)
break;
}
}
+ if (osc == NULL) {
+ sc->sc_mtx = malloc(sizeof(*sc->sc_mtx), M_DEVBUF,
+ M_NOWAIT | M_ZERO);
+ if (sc->sc_mtx == NULL)
+ panic("%s: could not malloc mutex", __func__);
+ mtx_init(sc->sc_mtx, "pcib_mtx", NULL, MTX_SPIN);
+ } else {
+ if (mtx_initialized(osc->sc_mtx) == 0)
+ panic("%s: mutex not initialized", __func__);
+ sc->sc_mtx = osc->sc_mtx;
+ }
/* Clear PCI AFSR. */
PCICTL_WRITE8(sc, PCR_AFS, PCIAFSR_ERRMASK);
@@ -487,7 +490,7 @@ psycho_attach(device_t dev)
* interrupt but they are also only used for PCI bus A.
*/
psycho_set_intr(sc, 0, sc->sc_half == 0 ? PSR_PCIAERR_INT_MAP :
- PSR_PCIBERR_INT_MAP, FAST, psycho_pci_bus);
+ PSR_PCIBERR_INT_MAP, psycho_pci_bus, NULL);
/*
* If we're a Hummingbird/Sabre or the first of a pair of Psycho's to
@@ -503,10 +506,15 @@ psycho_attach(device_t dev)
* XXX Not all controllers have these, but installing them
* is better than trying to sort through this mess.
*/
- psycho_set_intr(sc, 1, PSR_UE_INT_MAP, FAST, psycho_ue);
- psycho_set_intr(sc, 2, PSR_CE_INT_MAP, 0, psycho_ce);
- psycho_set_intr(sc, 3, PSR_POWER_INT_MAP,
- PSYCHO_PWRFAIL_INT_FLAGS, psycho_powerfail);
+ psycho_set_intr(sc, 1, PSR_UE_INT_MAP, psycho_ue, NULL);
+ psycho_set_intr(sc, 2, PSR_CE_INT_MAP, psycho_ce, NULL);
+#ifdef DEBUGGER_ON_POWERFAIL
+ psycho_set_intr(sc, 3, PSR_POWER_INT_MAP, psycho_powerfail,
+ NULL);
+#else
+ psycho_set_intr(sc, 3, PSR_POWER_INT_MAP, NULL,
+ (driver_intr_t *)psycho_powerfail);
+#endif
/* Psycho-specific initialization */
if (sc->sc_mode == PSYCHO_MODE_PSYCHO) {
/*
@@ -518,20 +526,20 @@ psycho_attach(device_t dev)
* The spare hardware interrupt is used for the
* over-temperature interrupt.
*/
- psycho_set_intr(sc, 4, PSR_SPARE_INT_MAP, FAST,
- psycho_overtemp);
+ psycho_set_intr(sc, 4, PSR_SPARE_INT_MAP,
+ NULL, psycho_overtemp);
#ifdef PSYCHO_MAP_WAKEUP
/*
* psycho_wakeup() doesn't do anything useful right
* now.
*/
- psycho_set_intr(sc, 5, PSR_PWRMGT_INT_MAP, 0,
- psycho_wakeup);
+ psycho_set_intr(sc, 5, PSR_PWRMGT_INT_MAP,
+ psycho_wakeup, NULL);
#endif /* PSYCHO_MAP_WAKEUP */
/* Initialize the counter-timer. */
- sparc64_counter_init(sc->sc_bustag, sc->sc_bushandle,
- PSR_TC0);
+ sparc64_counter_init(rman_get_bustag(sc->sc_mem_res),
+ rman_get_bushandle(sc->sc_mem_res), PSR_TC0);
}
/*
@@ -655,32 +663,21 @@ psycho_attach(device_t dev)
}
static void
-psycho_set_intr(struct psycho_softc *sc, int index, bus_addr_t map, int iflags,
- driver_filter_t handler)
+psycho_set_intr(struct psycho_softc *sc, int index, bus_addr_t map,
+ driver_filter_t filt, driver_intr_t intr)
{
uint64_t mr;
- int res, rid;
+ int rid;
- res = EINVAL;
rid = index;
mr = PSYCHO_READ8(sc, map);
sc->sc_irq_res[index] = bus_alloc_resource_any(sc->sc_dev, SYS_RES_IRQ,
&rid, RF_ACTIVE);
- if (sc->sc_irq_res[index] != NULL &&
- rman_get_start(sc->sc_irq_res[index]) == INTVEC(mr)) {
- if (iflags & FAST) {
- iflags &= ~FAST;
- res = bus_setup_intr(sc->sc_dev, sc->sc_irq_res[index],
- INTR_TYPE_MISC | iflags, handler, NULL, sc,
- &sc->sc_ihand[index]);
- } else
- res = bus_setup_intr(sc->sc_dev, sc->sc_irq_res[index],
- INTR_TYPE_MISC | iflags, NULL,
- (driver_intr_t *)handler, sc,
- &sc->sc_ihand[index]);
- }
- if (res)
- panic("%s: failed to set up interrupt", __func__);
+ if (sc->sc_irq_res[index] == NULL ||
+ rman_get_start(sc->sc_irq_res[index]) != INTVEC(mr) ||
+ bus_setup_intr(sc->sc_dev, sc->sc_irq_res[index], INTR_TYPE_MISC,
+ filt, intr, sc, &sc->sc_ihand[index]) != 0)
+ panic("%s: failed to set up interrupt %d", __func__, index);
PSYCHO_WRITE8(sc, map, INTMAP_ENABLE(mr, PCPU_GET(mid)));
}
@@ -765,6 +762,7 @@ psycho_ce(void *arg)
struct psycho_softc *sc = arg;
uint64_t afar, afsr;
+ mtx_lock_spin(sc->sc_mtx);
afar = PSYCHO_READ8(sc, PSR_CE_AFA);
afsr = PSYCHO_READ8(sc, PSR_CE_AFS);
device_printf(sc->sc_dev, "correctable DMA error AFAR %#lx "
@@ -772,6 +770,7 @@ psycho_ce(void *arg)
/* Clear the error bits that we caught. */
PSYCHO_WRITE8(sc, PSR_CE_AFS, afsr & CEAFSR_ERRMASK);
PSYCHO_WRITE8(sc, PSR_CE_INT_CLR, 0);
+ mtx_unlock_spin(sc->sc_mtx);
return (FILTER_HANDLED);
}
@@ -792,7 +791,6 @@ psycho_pci_bus(void *arg)
static int
psycho_powerfail(void *arg)
{
-
#ifdef DEBUGGER_ON_POWERFAIL
struct psycho_softc *sc = arg;
@@ -805,13 +803,12 @@ psycho_powerfail(void *arg)
return (FILTER_HANDLED);
}
-static int
+static void
psycho_overtemp(void *arg)
{
printf("DANGER: OVER TEMPERATURE detected.\nShutting down NOW.\n");
shutdown_nice(RB_POWEROFF);
- return (FILTER_HANDLED);
}
#ifdef PSYCHO_MAP_WAKEUP
@@ -834,8 +831,8 @@ psycho_iommu_init(struct psycho_softc *sc, int tsbsize, uint32_t dvmabase)
struct iommu_state *is = sc->sc_is;
/* Punch in our copies. */
- is->is_bustag = sc->sc_bustag;
- is->is_bushandle = sc->sc_bushandle;
+ is->is_bustag = rman_get_bustag(sc->sc_mem_res);
+ is->is_bushandle = rman_get_bushandle(sc->sc_mem_res);
is->is_iommu = PSR_IOMMU;
is->is_dtag = PSR_IOMMU_TLB_TAG_DIAG;
is->is_ddram = PSR_IOMMU_TLB_DATA_DIAG;
@@ -982,7 +979,6 @@ psycho_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
return (ENOENT);
}
-/* Write to the correct clr register, and call the actual handler. */
static int
psycho_filter_stub(void *arg)
{
@@ -992,8 +988,8 @@ psycho_filter_stub(void *arg)
if (pc->pci_filter != NULL) {
res = pc->pci_filter(pc->pci_arg);
PSYCHO_WRITE8(pc->pci_sc, pc->pci_clr, 0);
- } else
- res = FILTER_SCHEDULE_THREAD;
+ } else
+ res = FILTER_SCHEDULE_THREAD;
return (res);
}
@@ -1320,7 +1316,7 @@ psycho_adjust_busrange(device_t dev, u_int subbus)
if (subbus > sc->sc_pci_subbus) {
#ifdef PSYCHO_DEBUG
device_printf(dev,
- "adjusting secondary bus number from %d to %d\n",
+ "adjusting subordinate bus number from %d to %d\n",
sc->sc_pci_subbus, subbus);
#endif
sc->sc_pci_subbus = subbus;
@@ -1339,7 +1335,7 @@ psycho_alloc_bus_tag(struct psycho_softc *sc, int type)
panic("%s: out of memory", __func__);
bt->bst_cookie = sc;
- bt->bst_parent = sc->sc_bustag;
+ bt->bst_parent = rman_get_bustag(sc->sc_mem_res);
bt->bst_type = type;
return (bt);
}
diff --git a/sys/sparc64/pci/psychovar.h b/sys/sparc64/pci/psychovar.h
index fe20fe6..ddb4661 100644
--- a/sys/sparc64/pci/psychovar.h
+++ b/sys/sparc64/pci/psychovar.h
@@ -40,13 +40,11 @@
struct psycho_softc {
device_t sc_dev;
+ struct mtx *sc_mtx;
+
/* Interrupt Group Number for this device */
int sc_ign;
- /* Our tags (from parent) */
- bus_space_tag_t sc_bustag;
- bus_space_handle_t sc_bushandle;
-
bus_addr_t sc_pcictl;
phandle_t sc_node; /* Firmware node */
OpenPOWER on IntegriCloud