- Ensure we find no unexpected partner.
- Failing to register as interrupt controller during attach shouldn't be fatal so just inform about this instead of panicing. - Disable rerun of the streaming cache as workaround for a silicon bug of certain Psycho versions. - Remove the comment regarding lack of newbus'ified bus_dma(9) as being able to associate a DMA tag with a device would allow to implement CDMA flushing/syncing in bus_dmamap_sync(9) but that would totally kill performance. Given that for devices not behind a PCI-PCI bridge the host-to-PCI bridges also only do CDMA flushing/syncing based on interrupts there's no additional disadvantage for polling(4) callbacks in the case schizo(4) has to do the CDMA flushing/syncing but rather a general problem. - Don't panic if the power failure, power management or over-temperature interrupts doesn't exist as these aren't mandatory and not available with all controllers (not even Psychos). [1] - Take advantage of KOBJMETHOD_END. - Remove some redundant variables. - Add missing const. PR: 131371 [1]
This commit is contained in:
parent
2f7c8f0fd9
commit
cdec2d0d7a
@ -83,7 +83,7 @@ static void psycho_set_intr(struct psycho_softc *, u_int, bus_addr_t,
|
||||
driver_filter_t, driver_intr_t);
|
||||
static int psycho_find_intrmap(struct psycho_softc *, u_int, bus_addr_t *,
|
||||
bus_addr_t *, u_long *);
|
||||
static driver_filter_t psycho_dmasync;
|
||||
static driver_filter_t psycho_dma_sync_stub;
|
||||
static void psycho_intr_enable(void *);
|
||||
static void psycho_intr_disable(void *);
|
||||
static void psycho_intr_assign(void *);
|
||||
@ -150,7 +150,7 @@ static device_method_t psycho_methods[] = {
|
||||
/* ofw_bus interface */
|
||||
DEVMETHOD(ofw_bus_get_node, psycho_get_node),
|
||||
|
||||
{ 0, 0 }
|
||||
KOBJMETHOD_END
|
||||
};
|
||||
|
||||
static devclass_t psycho_devclass;
|
||||
@ -175,7 +175,7 @@ struct psycho_icarg {
|
||||
bus_addr_t pica_clr;
|
||||
};
|
||||
|
||||
struct psycho_dmasync {
|
||||
struct psycho_dma_sync {
|
||||
struct psycho_softc *pds_sc;
|
||||
driver_filter_t *pds_handler; /* handler to call */
|
||||
void *pds_arg; /* argument for the handler */
|
||||
@ -232,14 +232,14 @@ struct psycho_desc {
|
||||
const char *pd_name;
|
||||
};
|
||||
|
||||
static const struct psycho_desc psycho_compats[] = {
|
||||
static const struct psycho_desc const psycho_compats[] = {
|
||||
{ "pci108e,8000", PSYCHO_MODE_PSYCHO, "Psycho compatible" },
|
||||
{ "pci108e,a000", PSYCHO_MODE_SABRE, "Sabre compatible" },
|
||||
{ "pci108e,a001", PSYCHO_MODE_SABRE, "Hummingbird compatible" },
|
||||
{ NULL, 0, NULL }
|
||||
};
|
||||
|
||||
static const struct psycho_desc psycho_models[] = {
|
||||
static const struct psycho_desc const psycho_models[] = {
|
||||
{ "SUNW,psycho", PSYCHO_MODE_PSYCHO, "Psycho" },
|
||||
{ "SUNW,sabre", PSYCHO_MODE_SABRE, "Sabre" },
|
||||
{ NULL, 0, NULL }
|
||||
@ -296,8 +296,8 @@ psycho_attach(device_t dev)
|
||||
phandle_t child, node;
|
||||
uint32_t dvmabase, prop, prop_array[2];
|
||||
int32_t rev;
|
||||
u_int ver;
|
||||
int i, n, nrange, rid;
|
||||
u_int rerun, ver;
|
||||
int i, n;
|
||||
|
||||
node = ofw_bus_get_node(dev);
|
||||
sc = device_get_softc(dev);
|
||||
@ -315,7 +315,7 @@ psycho_attach(device_t dev)
|
||||
* (2) the shared Psycho configuration registers
|
||||
*/
|
||||
if (sc->sc_mode == PSYCHO_MODE_PSYCHO) {
|
||||
rid = 2;
|
||||
i = 2;
|
||||
sc->sc_pcictl =
|
||||
bus_get_resource_start(dev, SYS_RES_MEMORY, 0) -
|
||||
bus_get_resource_start(dev, SYS_RES_MEMORY, 2);
|
||||
@ -332,18 +332,18 @@ psycho_attach(device_t dev)
|
||||
/* NOTREACHED */
|
||||
}
|
||||
} else {
|
||||
rid = 0;
|
||||
i = 0;
|
||||
sc->sc_pcictl = PSR_PCICTL0;
|
||||
sc->sc_half = 0;
|
||||
}
|
||||
sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
|
||||
sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &i,
|
||||
(sc->sc_mode == PSYCHO_MODE_PSYCHO ? RF_SHAREABLE : 0) |
|
||||
RF_ACTIVE);
|
||||
if (sc->sc_mem_res == NULL)
|
||||
panic("%s: could not allocate registers", __func__);
|
||||
|
||||
/*
|
||||
* Match other Psycho's that are already configured against
|
||||
* Match other Psychos that are already configured against
|
||||
* the base physical address. This will be the same for a
|
||||
* pair of devices that share register space.
|
||||
*/
|
||||
@ -363,6 +363,8 @@ psycho_attach(device_t dev)
|
||||
panic("%s: could not malloc mutex", __func__);
|
||||
mtx_init(sc->sc_mtx, "pcib_mtx", NULL, MTX_SPIN);
|
||||
} else {
|
||||
if (sc->sc_mode != PSYCHO_MODE_PSYCHO)
|
||||
panic("%s: no partner expected", __func__);
|
||||
if (mtx_initialized(osc->sc_mtx) == 0)
|
||||
panic("%s: mutex not initialized", __func__);
|
||||
sc->sc_mtx = osc->sc_mtx;
|
||||
@ -408,16 +410,17 @@ psycho_attach(device_t dev)
|
||||
case 0:
|
||||
dr |= DIAG_RTRY_DIS;
|
||||
dr &= ~DIAG_DWSYNC_DIS;
|
||||
/* XXX need to also disable rerun of the streaming buffers. */
|
||||
rerun = 0;
|
||||
break;
|
||||
case 1:
|
||||
csr &= ~PCICTL_ARB_PARK;
|
||||
dr |= DIAG_RTRY_DIS | DIAG_DWSYNC_DIS;
|
||||
/* XXX need to also disable rerun of the streaming buffers. */
|
||||
rerun = 0;
|
||||
break;
|
||||
default:
|
||||
dr |= DIAG_DWSYNC_DIS;
|
||||
dr &= ~DIAG_RTRY_DIS;
|
||||
rerun = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -460,13 +463,12 @@ psycho_attach(device_t dev)
|
||||
rman_manage_region(&sc->sc_pci_mem_rman, 0, PSYCHO_MEM_SIZE) != 0)
|
||||
panic("%s: failed to set up memory rman", __func__);
|
||||
|
||||
nrange = OF_getprop_alloc(node, "ranges", sizeof(*range),
|
||||
(void **)&range);
|
||||
n = OF_getprop_alloc(node, "ranges", sizeof(*range), (void **)&range);
|
||||
/*
|
||||
* Make sure that the expected ranges are present. The
|
||||
* OFW_PCI_CS_MEM64 one is not currently used though.
|
||||
*/
|
||||
if (nrange != PSYCHO_NRANGE)
|
||||
if (n != PSYCHO_NRANGE)
|
||||
panic("%s: unsupported number of ranges", __func__);
|
||||
/*
|
||||
* Find the addresses of the various bus spaces.
|
||||
@ -493,7 +495,8 @@ psycho_attach(device_t dev)
|
||||
/*
|
||||
* Hunt through all the interrupt mapping regs and register
|
||||
* our interrupt controller for the corresponding interrupt
|
||||
* vectors.
|
||||
* vectors. We do this early in order to be able to catch
|
||||
* stray interrupts.
|
||||
*/
|
||||
for (n = 0; n <= PSYCHO_MAX_INO; n++) {
|
||||
if (psycho_find_intrmap(sc, n, &intrmap, &intrclr,
|
||||
@ -523,22 +526,23 @@ psycho_attach(device_t dev)
|
||||
INTMAP_ENABLE(INTMAP_VEC(sc->sc_ign, n),
|
||||
PCPU_GET(mid)));
|
||||
#endif
|
||||
if (intr_controller_register(INTMAP_VEC(sc->sc_ign, n),
|
||||
&psycho_ic, pica) != 0)
|
||||
panic("%s: could not register interrupt "
|
||||
"controller for INO %d", __func__, n);
|
||||
i = intr_controller_register(INTMAP_VEC(sc->sc_ign, n),
|
||||
&psycho_ic, pica);
|
||||
if (i != 0)
|
||||
device_printf(dev, "could not register "
|
||||
"interrupt controller for INO %d (%d)\n",
|
||||
n, i);
|
||||
}
|
||||
|
||||
if (sc->sc_mode == PSYCHO_MODE_PSYCHO) {
|
||||
/* Initialize the counter-timer. */
|
||||
if (sc->sc_mode == PSYCHO_MODE_PSYCHO)
|
||||
sparc64_counter_init(device_get_nameunit(dev),
|
||||
rman_get_bustag(sc->sc_mem_res),
|
||||
rman_get_bushandle(sc->sc_mem_res), PSR_TC0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up IOMMU and PCI configuration if we're the first
|
||||
* of a pair of Psycho's to arrive here.
|
||||
* of a pair of Psychos to arrive here or a Hummingbird
|
||||
* or Sabre.
|
||||
*
|
||||
* We should calculate a TSB size based on amount of RAM
|
||||
* and number of bus controllers and number and type of
|
||||
@ -556,10 +560,10 @@ psycho_attach(device_t dev)
|
||||
else
|
||||
sc->sc_is->is_pmaxaddr =
|
||||
IOMMU_MAXADDR(PSYCHO_IOMMU_BITS);
|
||||
sc->sc_is->is_sb[0] = 0;
|
||||
sc->sc_is->is_sb[1] = 0;
|
||||
sc->sc_is->is_sb[0] = sc->sc_is->is_sb[1] = 0;
|
||||
if (OF_getproplen(node, "no-streaming-cache") < 0)
|
||||
sc->sc_is->is_sb[0] = sc->sc_pcictl + PCR_STRBUF;
|
||||
sc->sc_is->is_flags |= (rerun != 1) ? IOMMU_RERUN_DISABLE : 0;
|
||||
psycho_iommu_init(sc, 3, dvmabase);
|
||||
} else {
|
||||
/* Just copy IOMMU state, config tag and address. */
|
||||
@ -694,12 +698,20 @@ psycho_set_intr(struct psycho_softc *sc, u_int index, bus_addr_t intrmap,
|
||||
rid = index;
|
||||
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 && intrmap >= PSR_POWER_INT_MAP) {
|
||||
/*
|
||||
* These interrupts aren't mandatory and not available
|
||||
* with all controllers (not even Psychos).
|
||||
*/
|
||||
return;
|
||||
}
|
||||
if (sc->sc_irq_res[index] == NULL ||
|
||||
INTIGN(vec = rman_get_start(sc->sc_irq_res[index])) != sc->sc_ign ||
|
||||
INTVEC(PSYCHO_READ8(sc, intrmap)) != vec ||
|
||||
intr_vectors[vec].iv_ic != &psycho_ic ||
|
||||
bus_setup_intr(sc->sc_dev, sc->sc_irq_res[index], INTR_TYPE_MISC,
|
||||
filt, intr, sc, &sc->sc_ihand[index]) != 0)
|
||||
bus_setup_intr(sc->sc_dev, sc->sc_irq_res[index],
|
||||
INTR_TYPE_MISC | INTR_FAST, filt, intr, sc,
|
||||
&sc->sc_ihand[index]) != 0)
|
||||
panic("%s: failed to set up interrupt %d", __func__, index);
|
||||
}
|
||||
|
||||
@ -1065,9 +1077,9 @@ psycho_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
|
||||
}
|
||||
|
||||
static int
|
||||
psycho_dmasync(void *arg)
|
||||
psycho_dma_sync_stub(void *arg)
|
||||
{
|
||||
struct psycho_dmasync *pds = arg;
|
||||
struct psycho_dma_sync *pds = arg;
|
||||
|
||||
(void)PCIB_READ_CONFIG(pds->pds_ppb, pds->pds_bus, pds->pds_slot,
|
||||
pds->pds_func, PCIR_VENDOR, 2);
|
||||
@ -1125,7 +1137,7 @@ psycho_setup_intr(device_t dev, device_t child, struct resource *ires,
|
||||
devclass_t pci_devclass;
|
||||
device_t cdev, pdev, pcidev;
|
||||
struct psycho_softc *sc;
|
||||
struct psycho_dmasync *pds;
|
||||
struct psycho_dma_sync *pds;
|
||||
u_long vec;
|
||||
int error;
|
||||
|
||||
@ -1142,17 +1154,12 @@ psycho_setup_intr(device_t dev, device_t child, struct resource *ires,
|
||||
}
|
||||
|
||||
/*
|
||||
* The Sabre-APB-combination has a bug where it does not drain
|
||||
* DMA write data for devices behind additional PCI-PCI bridges
|
||||
* underneath the APB PCI-PCI bridge. The workaround is to do
|
||||
* a read on the farest PCI-PCI bridge followed by a read of the
|
||||
* PCI DMA write sync register of the Sabre.
|
||||
* XXX installing the wrapper for an affected device and the
|
||||
* actual workaround in psycho_dmasync() should be moved to
|
||||
* psycho(4)-specific bus_dma_tag_create() and bus_dmamap_sync()
|
||||
* methods, respectively, once DMA tag creation is newbus'ified,
|
||||
* so the workaround isn't only applied for interrupt handlers
|
||||
* but also for polling(4) callbacks.
|
||||
* The Sabre-APB-combination does not automatically flush DMA
|
||||
* write data for devices behind additional PCI-PCI bridges
|
||||
* underneath the APB PCI-PCI bridge. The procedure for a
|
||||
* manual flush is to do a PIO read on the far side of the
|
||||
* farthest PCI-PCI bridge followed by a read of the PCI DMA
|
||||
* write sync register of the Sabre.
|
||||
*/
|
||||
if (sc->sc_mode == PSYCHO_MODE_SABRE) {
|
||||
pds = malloc(sizeof(*pds), M_DEVBUF, M_NOWAIT | M_ZERO);
|
||||
@ -1191,20 +1198,20 @@ psycho_setup_intr(device_t dev, device_t child, struct resource *ires,
|
||||
pds->pds_func = pci_get_function(pcidev);
|
||||
if (bootverbose)
|
||||
device_printf(dev, "installed DMA sync "
|
||||
"workaround for device %d.%d on bus %d\n",
|
||||
"wrapper for device %d.%d on bus %d\n",
|
||||
pds->pds_slot, pds->pds_func,
|
||||
pds->pds_bus);
|
||||
if (intr == NULL) {
|
||||
pds->pds_handler = filt;
|
||||
error = bus_generic_setup_intr(dev, child,
|
||||
ires, flags, psycho_dmasync, intr, pds,
|
||||
cookiep);
|
||||
ires, flags, psycho_dma_sync_stub, intr,
|
||||
pds, cookiep);
|
||||
} else {
|
||||
pds->pds_handler = (driver_filter_t *)intr;
|
||||
error = bus_generic_setup_intr(dev, child,
|
||||
ires, flags, filt,
|
||||
(driver_intr_t *)psycho_dmasync, pds,
|
||||
cookiep);
|
||||
(driver_intr_t *)psycho_dma_sync_stub,
|
||||
pds, cookiep);
|
||||
}
|
||||
} else
|
||||
error = bus_generic_setup_intr(dev, child, ires,
|
||||
@ -1226,7 +1233,7 @@ psycho_teardown_intr(device_t dev, device_t child, struct resource *vec,
|
||||
void *cookie)
|
||||
{
|
||||
struct psycho_softc *sc;
|
||||
struct psycho_dmasync *pds;
|
||||
struct psycho_dma_sync *pds;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
@ -1314,8 +1321,8 @@ psycho_activate_resource(device_t bus, device_t child, int type, int rid,
|
||||
type, rid, r));
|
||||
if (type == SYS_RES_MEMORY) {
|
||||
/*
|
||||
* Need to memory-map the device space, as some drivers depend
|
||||
* on the virtual address being set and useable.
|
||||
* Need to memory-map the device space, as some drivers
|
||||
* depend on the virtual address being set and usable.
|
||||
*/
|
||||
error = sparc64_bus_mem_map(rman_get_bustag(r),
|
||||
rman_get_bushandle(r), rman_get_size(r), 0, 0, &p);
|
||||
|
@ -49,8 +49,8 @@ struct psycho_softc {
|
||||
|
||||
phandle_t sc_node; /* Firmware node */
|
||||
u_int sc_mode;
|
||||
#define PSYCHO_MODE_SABRE 1
|
||||
#define PSYCHO_MODE_PSYCHO 2
|
||||
#define PSYCHO_MODE_SABRE 0
|
||||
#define PSYCHO_MODE_PSYCHO 1
|
||||
|
||||
/* Bus A or B of a psycho pair? */
|
||||
u_int sc_half;
|
||||
|
Loading…
x
Reference in New Issue
Block a user