Add a new get_id interface to pci and pcib. This will allow us to both

detect failures, and get different PCI IDs.

For the former the interface returns an int to signal an error. The ID is
returned at a uintptr_t * argument.

For the latter there is a type argument that allows selecting the ID type.
This only specifies a single type, however a MSI type will be added
to handle the need to find the ID the hardware passes to the ARM GICv3
interrupt controller.

A follow up commit will be made to remove pci_get_rid.

Reviewed by:	jhb, rstone
Obtained from:	ABT Systems Ltd
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D6239
This commit is contained in:
Andrew Turner 2016-05-11 17:07:29 +00:00
parent 4aa1608aee
commit 9a36a337ff
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=299467
9 changed files with 75 additions and 20 deletions

View File

@ -1290,6 +1290,7 @@ MLINKS+=pci.9 pci_alloc_msi.9 \
pci.9 pci_find_extcap.9 \
pci.9 pci_find_htcap.9 \
pci.9 pci_find_pcie_root_port.9 \
pci.9 pci_get_id.9 \
pci.9 pci_get_max_read_req.9 \
pci.9 pci_get_powerstate.9 \
pci.9 pci_get_vpd_ident.9 \

View File

@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd December 23, 2015
.Dd May 11, 2016
.Dt PCI 9
.Os
.Sh NAME
@ -43,6 +43,7 @@
.Nm pci_find_extcap ,
.Nm pci_find_htcap ,
.Nm pci_find_pcie_root_port ,
.Nm pci_get_id ,
.Nm pci_get_max_read_req ,
.Nm pci_get_powerstate ,
.Nm pci_get_vpd_ident ,
@ -97,6 +98,8 @@
.Ft device_t
.Fn pci_find_pcie_root_port "device_t dev"
.Ft int
.Fn pci_get_id "device_t dev" "enum pci_id_type type" "uintptr_t *id"
.Ft int
.Fn pci_get_max_read_req "device_t dev"
.Ft int
.Fn pci_get_powerstate "device_t dev"
@ -357,6 +360,18 @@ returns
.Dv NULL .
.Pp
The
.Fn pci_get_id
function is used to read an identifier from a device.
The
.Fa type
flag is used to specify which identifier to read.
The following flags are supported:
.Bl -hang -width ".Dv PCI_ID_RID"
.It Dv PCI_ID_RID
Read the routing identifier for the device.
.El
.Pp
The
.Fn pci_get_vpd_ident
function is used to fetch a device's Vital Product Data
.Pq VPD

View File

@ -122,7 +122,8 @@ static void pci_resume_msix(device_t dev);
static int pci_remap_intr_method(device_t bus, device_t dev,
u_int irq);
static uint16_t pci_get_rid_method(device_t dev, device_t child);
static int pci_get_id_method(device_t dev, device_t child,
enum pci_id_type type, uintptr_t *rid);
static struct pci_devinfo * pci_fill_devinfo(device_t pcib, device_t bus, int d,
int b, int s, int f, uint16_t vid, uint16_t did);
@ -190,7 +191,7 @@ static device_method_t pci_methods[] = {
DEVMETHOD(pci_msix_count, pci_msix_count_method),
DEVMETHOD(pci_msix_pba_bar, pci_msix_pba_bar_method),
DEVMETHOD(pci_msix_table_bar, pci_msix_table_bar_method),
DEVMETHOD(pci_get_rid, pci_get_rid_method),
DEVMETHOD(pci_get_id, pci_get_id_method),
DEVMETHOD(pci_alloc_devinfo, pci_alloc_devinfo_method),
DEVMETHOD(pci_child_added, pci_child_added_method),
#ifdef PCI_IOV
@ -5823,11 +5824,12 @@ pci_restore_state(device_t dev)
pci_cfg_restore(dev, dinfo);
}
static uint16_t
pci_get_rid_method(device_t dev, device_t child)
static int
pci_get_id_method(device_t dev, device_t child, enum pci_id_type type,
uintptr_t *id)
{
return (PCIB_GET_RID(device_get_parent(dev), child));
return (PCIB_GET_ID(device_get_parent(dev), child, type, id));
}
/* Find the upstream port of a given PCI device in a root complex. */

View File

@ -27,6 +27,7 @@
#
#include <sys/bus.h>
#include <dev/pci/pcivar.h>
INTERFACE pci;
@ -208,9 +209,11 @@ METHOD int msix_table_bar {
device_t child;
} DEFAULT null_msix_bar;
METHOD uint16_t get_rid {
METHOD int get_id {
device_t dev;
device_t child;
enum pci_id_type type;
uintptr_t *id;
};
METHOD struct pci_devinfo * alloc_devinfo {

View File

@ -59,7 +59,8 @@ static int pcib_suspend(device_t dev);
static int pcib_resume(device_t dev);
static int pcib_power_for_sleep(device_t pcib, device_t dev,
int *pstate);
static uint16_t pcib_ari_get_rid(device_t pcib, device_t dev);
static int pcib_ari_get_id(device_t pcib, device_t dev,
enum pci_id_type type, uintptr_t *id);
static uint32_t pcib_read_config(device_t dev, u_int b, u_int s,
u_int f, u_int reg, int width);
static void pcib_write_config(device_t dev, u_int b, u_int s,
@ -114,7 +115,7 @@ static device_method_t pcib_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, pcib_map_msi),
DEVMETHOD(pcib_power_for_sleep, pcib_power_for_sleep),
DEVMETHOD(pcib_get_rid, pcib_ari_get_rid),
DEVMETHOD(pcib_get_id, pcib_ari_get_id),
DEVMETHOD(pcib_try_enable_ari, pcib_try_enable_ari),
DEVMETHOD(pcib_ari_enabled, pcib_ari_enabled),
DEVMETHOD(pcib_decode_rid, pcib_ari_decode_rid),
@ -2574,26 +2575,32 @@ pcib_ari_enabled(device_t pcib)
return ((sc->flags & PCIB_ENABLE_ARI) != 0);
}
static uint16_t
pcib_ari_get_rid(device_t pcib, device_t dev)
static int
pcib_ari_get_id(device_t pcib, device_t dev, enum pci_id_type type,
uintptr_t *id)
{
struct pcib_softc *sc;
uint8_t bus, slot, func;
if (type != PCI_ID_RID)
return (ENXIO);
sc = device_get_softc(pcib);
if (sc->flags & PCIB_ENABLE_ARI) {
bus = pci_get_bus(dev);
func = pci_get_function(dev);
return (PCI_ARI_RID(bus, func));
*id = (PCI_ARI_RID(bus, func));
} else {
bus = pci_get_bus(dev);
slot = pci_get_slot(dev);
func = pci_get_function(dev);
return (PCI_RID(bus, slot, func));
*id = (PCI_RID(bus, slot, func));
}
return (0);
}
/*

View File

@ -175,10 +175,12 @@ METHOD int power_for_sleep {
#
# Return the PCI Routing Identifier (RID) for the device.
#
METHOD uint16_t get_rid {
METHOD int get_id {
device_t pcib;
device_t dev;
} DEFAULT pcib_get_rid;
enum pci_id_type type;
uintptr_t *id;
} DEFAULT pcib_get_id;
#
# Enable Alternative RID Interpretation if both the downstream port (pcib)

View File

@ -190,7 +190,8 @@ int pcib_release_msi(device_t pcib, device_t dev, int count, int *irqs);
int pcib_alloc_msix(device_t pcib, device_t dev, int *irq);
int pcib_release_msix(device_t pcib, device_t dev, int irq);
int pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr, uint32_t *data);
uint16_t pcib_get_rid(device_t pcib, device_t dev);
int pcib_get_id(device_t pcib, device_t dev, enum pci_id_type type,
uintptr_t *id);
void pcib_decode_rid(device_t pcib, uint16_t rid, int *bus,
int *slot, int *func);

View File

@ -54,16 +54,20 @@ pcib_maxfuncs(device_t dev)
return (PCI_FUNCMAX);
}
uint16_t
pcib_get_rid(device_t pcib, device_t dev)
int
pcib_get_id(device_t pcib, device_t dev, enum pci_id_type type, uintptr_t *id)
{
uint8_t bus, slot, func;
if (type != PCI_ID_RID)
return (ENXIO);
bus = pci_get_bus(dev);
slot = pci_get_slot(dev);
func = pci_get_function(dev);
return (PCI_RID(bus, slot, func));
*id = (PCI_RID(bus, slot, func));
return (0);
}
void

View File

@ -268,6 +268,10 @@ struct pci_devinfo {
#ifdef _SYS_BUS_H_
enum pci_id_type {
PCI_ID_RID,
};
#include "pci_if.h"
enum pci_device_ivars {
@ -542,10 +546,26 @@ pci_msix_table_bar(device_t dev)
return (PCI_MSIX_TABLE_BAR(device_get_parent(dev), dev));
}
static __inline int
pci_get_id(device_t dev, enum pci_id_type type, uintptr_t *id)
{
return (PCI_GET_ID(device_get_parent(dev), dev, type, id));
}
/*
* This is the deprecated interface, there is no way to tell the difference
* between a failure and a valid value that happens to be the same as the
* failure value.
*/
static __inline uint16_t
pci_get_rid(device_t dev)
{
return (PCI_GET_RID(device_get_parent(dev), dev));
uintptr_t rid;
if (pci_get_id(dev, PCI_ID_RID, &rid) != 0)
return (0);
return (rid);
}
static __inline void