Add support for vendor specific function for PCI devid acquisition in ITS
It is possible that some HW will use different PCI devids, hence allow to replace the default domain🚌slot:func schema by implementing and registering custom function. Obtained from: Semihalf Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D3118
This commit is contained in:
parent
dd7314a557
commit
72e5c0c258
@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
|
||||
#include <dev/pci/pcireg.h>
|
||||
#include <dev/pci/pcivar.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
@ -89,6 +90,7 @@ static void its_free_tables(struct gic_v3_its_softc *);
|
||||
static void its_init_commandq(struct gic_v3_its_softc *);
|
||||
static int its_init_cpu(struct gic_v3_its_softc *);
|
||||
static void its_init_cpu_collection(struct gic_v3_its_softc *);
|
||||
static uint32_t its_get_devid(device_t);
|
||||
|
||||
static int its_cmd_send(struct gic_v3_its_softc *, struct its_cmd_desc *);
|
||||
|
||||
@ -133,6 +135,23 @@ const char *its_ptab_type[] = {
|
||||
[GITS_BASER_TYPE_RES7] = "Reserved (7)",
|
||||
};
|
||||
|
||||
/*
|
||||
* Vendor specific quirks.
|
||||
* One needs to add appropriate entry to its_quirks[]
|
||||
* table if the imlementation varies from the generic ARM ITS.
|
||||
*/
|
||||
|
||||
/* Cavium ThunderX PCI devid acquire function */
|
||||
static uint32_t its_get_devid_thunder(device_t);
|
||||
|
||||
static const struct its_quirks its_quirks[] = {
|
||||
{
|
||||
.cpuid = CPU_ID_RAW(CPU_IMPL_CAVIUM, CPU_PART_THUNDER, 0, 0),
|
||||
.cpuid_mask = CPU_IMPL_MASK | CPU_PART_MASK,
|
||||
.devid_func = its_get_devid_thunder,
|
||||
},
|
||||
};
|
||||
|
||||
static struct gic_v3_its_softc *its_sc;
|
||||
|
||||
#define gic_its_read(sc, len, reg) \
|
||||
@ -1300,7 +1319,7 @@ its_device_alloc_locked(struct gic_v3_its_softc *sc, device_t pci_dev,
|
||||
if (newdev != NULL)
|
||||
return (newdev);
|
||||
|
||||
devid = PCI_DEVID(pci_dev);
|
||||
devid = its_get_devid(pci_dev);
|
||||
|
||||
/* There was no previously created device. Create one now */
|
||||
newdev = malloc(sizeof(*newdev), M_GIC_V3_ITS, (M_WAITOK | M_ZERO));
|
||||
@ -1353,6 +1372,73 @@ its_device_asign_lpi_locked(struct gic_v3_its_softc *sc,
|
||||
its_dev->lpis.lpi_free);
|
||||
its_dev->lpis.lpi_free--;
|
||||
}
|
||||
|
||||
/*
|
||||
* ITS quirks.
|
||||
* Add vendor specific PCI devid function here.
|
||||
*/
|
||||
static uint32_t
|
||||
its_get_devid_thunder(device_t pci_dev)
|
||||
{
|
||||
int bsf;
|
||||
int pem;
|
||||
uint32_t bus;
|
||||
|
||||
bus = pci_get_bus(pci_dev);
|
||||
|
||||
bsf = PCI_RID(pci_get_bus(pci_dev), pci_get_slot(pci_dev),
|
||||
pci_get_function(pci_dev));
|
||||
|
||||
/* ECAM is on bus=0 */
|
||||
if (bus == 0) {
|
||||
return ((pci_get_domain(pci_dev) << PCI_RID_DOMAIN_SHIFT) |
|
||||
bsf);
|
||||
/* PEM otherwise */
|
||||
} else {
|
||||
/* PEM number is equal to domain */
|
||||
pem = pci_get_domain(pci_dev);
|
||||
|
||||
/* Hardcode appropriate PEM numbers */
|
||||
if (pem < 3 )
|
||||
return ((0x1 << PCI_RID_DOMAIN_SHIFT) | bsf);
|
||||
|
||||
if (pem < 6 )
|
||||
return ((0x3 << PCI_RID_DOMAIN_SHIFT) | bsf);
|
||||
|
||||
if (pem < 9 )
|
||||
return ((0x9 << PCI_RID_DOMAIN_SHIFT) | bsf);
|
||||
|
||||
if (pem < 12 )
|
||||
return ((0xB << PCI_RID_DOMAIN_SHIFT) | bsf);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static __inline uint32_t
|
||||
its_get_devid_default(device_t pci_dev)
|
||||
{
|
||||
|
||||
return (PCI_DEVID_GENERIC(pci_dev));
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
its_get_devid(device_t pci_dev)
|
||||
{
|
||||
const struct its_quirks *quirk;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < nitems(its_quirks); i++) {
|
||||
quirk = &its_quirks[i];
|
||||
if (CPU_MATCH_RAW(quirk->cpuid_mask, quirk->cpuid)) {
|
||||
if (quirk->devid_func != NULL)
|
||||
return ((*quirk->devid_func)(pci_dev));
|
||||
}
|
||||
}
|
||||
|
||||
return (its_get_devid_default(pci_dev));
|
||||
}
|
||||
|
||||
/*
|
||||
* Message signalled interrupts handling.
|
||||
*/
|
||||
|
@ -234,6 +234,15 @@ struct gic_v3_its_softc {
|
||||
struct mtx its_spin_mtx;
|
||||
};
|
||||
|
||||
/* Stuff that is specific to the vendor's implementation */
|
||||
typedef uint32_t (*its_devid_func_t)(device_t);
|
||||
|
||||
struct its_quirks {
|
||||
uint64_t cpuid;
|
||||
uint64_t cpuid_mask;
|
||||
its_devid_func_t devid_func;
|
||||
};
|
||||
|
||||
extern devclass_t gic_v3_its_devclass;
|
||||
|
||||
int gic_v3_its_detach(device_t);
|
||||
@ -277,13 +286,12 @@ void lpi_mask_irq(device_t, uint32_t);
|
||||
reg, val); \
|
||||
})
|
||||
|
||||
#define PCI_DEVID(pci_dev) \
|
||||
#define PCI_DEVID_GENERIC(pci_dev) \
|
||||
({ \
|
||||
(((pci_get_domain(pci_dev) >> 2) << 19) | \
|
||||
((pci_get_domain(pci_dev) % 4) << 16) | \
|
||||
(pci_get_bus(pci_dev) << 8) | \
|
||||
(pci_get_slot(pci_dev) << 3) | \
|
||||
(pci_get_function(pci_dev) << 0)); \
|
||||
((pci_get_domain(pci_dev) << PCI_RID_DOMAIN_SHIFT) | \
|
||||
(pci_get_bus(pci_dev) << PCI_RID_BUS_SHIFT) | \
|
||||
(pci_get_slot(pci_dev) << PCI_RID_SLOT_SHIFT) | \
|
||||
(pci_get_function(pci_dev) << PCI_RID_FUNC_SHIFT)); \
|
||||
})
|
||||
|
||||
/*
|
||||
|
@ -51,6 +51,7 @@
|
||||
#define PCIE_ARI_SLOTMAX 0
|
||||
#define PCIE_ARI_FUNCMAX 255
|
||||
|
||||
#define PCI_RID_DOMAIN_SHIFT 16
|
||||
#define PCI_RID_BUS_SHIFT 8
|
||||
#define PCI_RID_SLOT_SHIFT 3
|
||||
#define PCI_RID_FUNC_SHIFT 0
|
||||
|
Loading…
Reference in New Issue
Block a user