Improve additional interrupt ACK for Broadcom XLP

Handling some interrupts in XLP (like PCIe and SATA) involves writing to
vendor specific registers as part of interrupt acknowledgement.

This was earlier done with xlp_establish_intr(), but a better solution
is to provide a function xlp_set_bus_ack() that can be used with
cpu_establish_hardintr(). This will allow platform initialization code to
setup these ACKs without changing the standrard drivers.
This commit is contained in:
Jayachandran C. 2015-02-27 00:57:09 +00:00
parent 87ac2b4068
commit af444e780c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=279341
3 changed files with 35 additions and 33 deletions

View File

@ -68,9 +68,7 @@
* XLR needs custom pre and post handlers for PCI/PCI-e interrupts
* XXX: maybe follow i386 intsrc model
*/
void xlp_establish_intr(const char *name, driver_filter_t filt,
driver_intr_t handler, void *arg, int irq, int flags,
void **cookiep, void (*busack)(int));
void xlp_enable_irq(int irq);
void xlp_set_bus_ack(int irq, void (*ack)(int, void *), void *arg);
#endif /* _RMI_INTERRUPT_H_ */

View File

@ -58,7 +58,8 @@ __FBSDID("$FreeBSD$");
#include <mips/nlm/xlp.h>
struct xlp_intrsrc {
void (*busack)(int); /* Additional ack */
void (*bus_ack)(int, void *); /* Additional ack */
void *bus_ack_arg; /* arg for additional ack */
struct intr_event *ie; /* event corresponding to intr */
int irq;
int irt;
@ -119,23 +120,13 @@ cpu_establish_softintr(const char *name, driver_filter_t * filt,
panic("Soft interrupts unsupported!\n");
}
void
cpu_establish_hardintr(const char *name, driver_filter_t * filt,
void (*handler) (void *), void *arg, int irq, int flags,
void **cookiep)
{
xlp_establish_intr(name, filt, handler, arg, irq, flags,
cookiep, NULL);
}
static void
xlp_post_filter(void *source)
{
struct xlp_intrsrc *src = source;
if (src->busack)
src->busack(src->irq);
if (src->bus_ack)
src->bus_ack(src->irq, src->bus_ack_arg);
nlm_pic_ack(xlp_pic_base, src->irt);
}
@ -144,8 +135,8 @@ xlp_pre_ithread(void *source)
{
struct xlp_intrsrc *src = source;
if (src->busack)
src->busack(src->irq);
if (src->bus_ack)
src->bus_ack(src->irq, src->bus_ack_arg);
}
static void
@ -157,19 +148,35 @@ xlp_post_ithread(void *source)
}
void
xlp_establish_intr(const char *name, driver_filter_t filt,
driver_intr_t handler, void *arg, int irq, int flags,
void **cookiep, void (*busack)(int))
xlp_set_bus_ack(int irq, void (*ack)(int, void *), void *arg)
{
struct xlp_intrsrc *src;
KASSERT(irq > 0 && irq <= XLR_MAX_INTR,
("%s called for bad hard intr %d", __func__, irq));
/* no locking needed - this will called early in boot */
src = &xlp_interrupts[irq];
KASSERT(src->ie != NULL,
("%s called after IRQ enable for %d.", __func__, irq));
src->bus_ack_arg = arg;
src->bus_ack = ack;
}
void
cpu_establish_hardintr(const char *name, driver_filter_t * filt,
void (*handler) (void *), void *arg, int irq, int flags,
void **cookiep)
{
struct intr_event *ie; /* descriptor for the IRQ */
struct xlp_intrsrc *src = NULL;
int errcode;
if (irq < 0 || irq > XLR_MAX_INTR)
panic("%s called for unknown hard intr %d", __func__, irq);
KASSERT(irq > 0 && irq <= XLR_MAX_INTR ,
("%s called for bad hard intr %d", __func__, irq));
/*
* FIXME locking - not needed now, because we do this only on
* Locking - not needed now, because we do this only on
* startup from CPU0
*/
src = &xlp_interrupts[irq];
@ -194,7 +201,6 @@ xlp_establish_intr(const char *name, driver_filter_t filt,
return;
}
src->irq = irq;
src->busack = busack;
src->ie = ie;
}
if (XLP_IRQ_IS_PICINTR(irq)) {

View File

@ -561,7 +561,7 @@ xlp_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
}
static void
bridge_pcie_ack(int irq)
bridge_pcie_ack(int irq, void *arg)
{
uint32_t node,reg;
uint64_t base;
@ -597,7 +597,6 @@ mips_platform_pcib_setup_intr(device_t dev, device_t child,
{
int error = 0;
int xlpirq;
void *extra_ack;
error = rman_activate_resource(irq);
if (error)
@ -656,12 +655,11 @@ mips_platform_pcib_setup_intr(device_t dev, device_t child,
xlpirq = PIC_PCIE_IRQ(link);
}
if (xlpirq >= PIC_PCIE_0_IRQ && xlpirq <= PIC_PCIE_3_IRQ)
extra_ack = bridge_pcie_ack;
else
extra_ack = NULL;
xlp_establish_intr(device_get_name(child), filt,
intr, arg, xlpirq, flags, cookiep, extra_ack);
/* if it is for real PCIe, we need to ack at bridge too */
if (xlpirq >= PIC_PCIE_IRQ(0) && xlpirq <= PIC_PCIE_IRQ(3))
xlp_set_bus_ack(xlpirq, bridge_pcie_ack, NULL);
cpu_establish_hardintr(device_get_name(child), filt, intr, arg,
xlpirq, flags, cookiep);
return (0);
}