- Add a bus_dma tag to each PCI bus that is a child of a Host-PCI bridge.
The tag enforces a single restriction that all DMA transactions must not cross a 4GB boundary. Note that while this restriction technically only applies to PCI-express, this change applies it to all PCI devices as it is simpler to implement that way and errs on the side of caution. - Add a softc structure for PCI bus devices to hold the bus_dma tag and a new pci_attach_common() routine that performs actions common to the attach phase of all PCI bus drivers. Right now this only consists of a bootverbose printf and the allocate of a bus_dma tag if necessary. - Adjust all PCI bus drivers to allocate a PCI bus softc and to call pci_attach_common() from their attach routines. MFC after: 2 weeks
This commit is contained in:
parent
3b7eabb569
commit
1b1596a3b3
@ -99,7 +99,8 @@ static device_method_t acpi_pci_methods[] = {
|
||||
|
||||
static devclass_t pci_devclass;
|
||||
|
||||
DEFINE_CLASS_1(pci, acpi_pci_driver, acpi_pci_methods, 0, pci_driver);
|
||||
DEFINE_CLASS_1(pci, acpi_pci_driver, acpi_pci_methods, sizeof(struct pci_softc),
|
||||
pci_driver);
|
||||
DRIVER_MODULE(acpi_pci, pcib, acpi_pci_driver, pci_devclass, 0, 0);
|
||||
MODULE_DEPEND(acpi_pci, acpi, 1, 1, 1);
|
||||
MODULE_DEPEND(acpi_pci, pci, 1, 1, 1);
|
||||
@ -276,7 +277,11 @@ acpi_pci_probe(device_t dev)
|
||||
static int
|
||||
acpi_pci_attach(device_t dev)
|
||||
{
|
||||
int busno, domain;
|
||||
int busno, domain, error;
|
||||
|
||||
error = pci_attach_common(dev);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
/*
|
||||
* Since there can be multiple independantly numbered PCI
|
||||
@ -286,9 +291,6 @@ acpi_pci_attach(device_t dev)
|
||||
*/
|
||||
domain = pcib_get_domain(dev);
|
||||
busno = pcib_get_bus(dev);
|
||||
if (bootverbose)
|
||||
device_printf(dev, "domain=%d, physical bus=%d\n",
|
||||
domain, busno);
|
||||
|
||||
/*
|
||||
* First, PCI devices are added as in the normal PCI bus driver.
|
||||
|
@ -316,6 +316,7 @@ static device_method_t cardbus_methods[] = {
|
||||
DEVMETHOD(device_resume, cardbus_resume),
|
||||
|
||||
/* Bus interface */
|
||||
DEVMETHOD(bus_get_dma_tag, bus_generic_get_dma_tag),
|
||||
DEVMETHOD(bus_read_ivar, cardbus_read_ivar),
|
||||
DEVMETHOD(bus_driver_added, cardbus_driver_added),
|
||||
|
||||
|
@ -70,6 +70,19 @@ __FBSDID("$FreeBSD$");
|
||||
#include "pcib_if.h"
|
||||
#include "pci_if.h"
|
||||
|
||||
/*
|
||||
* XXX: Due to a limitation of the bus_dma_tag_create() API, we cannot
|
||||
* specify a 4GB boundary on 32-bit targets. Usually this does not
|
||||
* matter as it is ok to use a boundary of 0 on these systems.
|
||||
* However, in the case of PAE, DMA addresses can cross a 4GB
|
||||
* boundary, so as a workaround use a 2GB boundary.
|
||||
*/
|
||||
#ifdef PAE
|
||||
#define PCI_DMA_BOUNDARY (1u << 31)
|
||||
#else
|
||||
#define PCI_DMA_BOUNDARY ((bus_size_t)((uint64_t)1 << 32))
|
||||
#endif
|
||||
|
||||
#define PCIR_IS_BIOS(cfg, reg) \
|
||||
(((cfg)->hdrtype == PCIM_HDRTYPE_NORMAL && reg == PCIR_BIOS) || \
|
||||
((cfg)->hdrtype == PCIM_HDRTYPE_BRIDGE && reg == PCIR_BIOS_1))
|
||||
@ -95,6 +108,7 @@ static void pci_load_vendor_data(void);
|
||||
static int pci_describe_parse_line(char **ptr, int *vendor,
|
||||
int *device, char **desc);
|
||||
static char *pci_describe_device(device_t dev);
|
||||
static bus_dma_tag_t pci_get_dma_tag(device_t bus, device_t dev);
|
||||
static int pci_modevent(module_t mod, int what, void *arg);
|
||||
static void pci_hdrtypedata(device_t pcib, int b, int s, int f,
|
||||
pcicfgregs *cfg);
|
||||
@ -137,6 +151,7 @@ static device_method_t pci_methods[] = {
|
||||
DEVMETHOD(bus_setup_intr, pci_setup_intr),
|
||||
DEVMETHOD(bus_teardown_intr, pci_teardown_intr),
|
||||
|
||||
DEVMETHOD(bus_get_dma_tag, pci_get_dma_tag),
|
||||
DEVMETHOD(bus_get_resource_list,pci_get_resource_list),
|
||||
DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
|
||||
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
|
||||
@ -173,7 +188,7 @@ static device_method_t pci_methods[] = {
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
DEFINE_CLASS_0(pci, pci_driver, pci_methods, 0);
|
||||
DEFINE_CLASS_0(pci, pci_driver, pci_methods, sizeof(struct pci_softc));
|
||||
|
||||
static devclass_t pci_devclass;
|
||||
DRIVER_MODULE(pci, pcib, pci_driver, pci_devclass, pci_modevent, 0);
|
||||
@ -3124,10 +3139,41 @@ pci_probe(device_t dev)
|
||||
return (BUS_PROBE_GENERIC);
|
||||
}
|
||||
|
||||
int
|
||||
pci_attach_common(device_t dev)
|
||||
{
|
||||
struct pci_softc *sc;
|
||||
int busno, domain, error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
domain = pcib_get_domain(dev);
|
||||
busno = pcib_get_bus(dev);
|
||||
if (bootverbose)
|
||||
device_printf(dev, "domain=%d, physical bus=%d\n",
|
||||
domain, busno);
|
||||
if (device_get_devclass(device_get_parent(device_get_parent(dev))) !=
|
||||
devclass_find("pci")) {
|
||||
error = bus_dma_tag_create(bus_get_dma_tag(dev), 1,
|
||||
PCI_DMA_BOUNDARY, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
|
||||
NULL, NULL, BUS_SPACE_MAXSIZE, BUS_SPACE_UNRESTRICTED,
|
||||
BUS_SPACE_MAXSIZE, 0, NULL, NULL, &sc->sc_dma_tag);
|
||||
if (error)
|
||||
device_printf(dev, "Failed to create DMA tag: %d\n",
|
||||
error);
|
||||
else
|
||||
sc->sc_dma_tag_valid = 1;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
pci_attach(device_t dev)
|
||||
{
|
||||
int busno, domain;
|
||||
int busno, domain, error;
|
||||
|
||||
error = pci_attach_common(dev);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
/*
|
||||
* Since there can be multiple independantly numbered PCI
|
||||
@ -3137,9 +3183,6 @@ pci_attach(device_t dev)
|
||||
*/
|
||||
domain = pcib_get_domain(dev);
|
||||
busno = pcib_get_bus(dev);
|
||||
if (bootverbose)
|
||||
device_printf(dev, "domain=%d, physical bus=%d\n",
|
||||
domain, busno);
|
||||
pci_add_children(dev, domain, busno, sizeof(struct pci_devinfo));
|
||||
return (bus_generic_attach(dev));
|
||||
}
|
||||
@ -4226,6 +4269,16 @@ pci_get_resource_list (device_t dev, device_t child)
|
||||
return (&dinfo->resources);
|
||||
}
|
||||
|
||||
bus_dma_tag_t
|
||||
pci_get_dma_tag(device_t bus, device_t dev)
|
||||
{
|
||||
struct pci_softc *sc = device_get_softc(bus);
|
||||
|
||||
if (sc->sc_dma_tag_valid)
|
||||
return (sc->sc_dma_tag);
|
||||
return (bus_generic_get_dma_tag(bus, dev));
|
||||
}
|
||||
|
||||
uint32_t
|
||||
pci_read_config_method(device_t dev, device_t child, int reg, int width)
|
||||
{
|
||||
|
@ -38,6 +38,11 @@
|
||||
*/
|
||||
DECLARE_CLASS(pci_driver);
|
||||
|
||||
struct pci_softc {
|
||||
bus_dma_tag_t sc_dma_tag;
|
||||
int sc_dma_tag_valid;
|
||||
};
|
||||
|
||||
extern int pci_do_power_resume;
|
||||
extern int pci_do_power_suspend;
|
||||
|
||||
@ -46,6 +51,7 @@ void pci_add_children(device_t dev, int domain, int busno,
|
||||
void pci_add_child(device_t bus, struct pci_devinfo *dinfo);
|
||||
void pci_add_resources(device_t bus, device_t dev, int force,
|
||||
uint32_t prefetchmask);
|
||||
int pci_attach_common(device_t dev);
|
||||
void pci_delete_child(device_t dev, device_t child);
|
||||
void pci_driver_added(device_t dev, driver_t *driver);
|
||||
int pci_print_child(device_t dev, device_t child);
|
||||
|
@ -95,8 +95,8 @@ struct ofw_pcibus_devinfo {
|
||||
|
||||
static devclass_t pci_devclass;
|
||||
|
||||
DEFINE_CLASS_1(pci, ofw_pcibus_driver, ofw_pcibus_methods, 1 /* no softc */,
|
||||
pci_driver);
|
||||
DEFINE_CLASS_1(pci, ofw_pcibus_driver, ofw_pcibus_methods,
|
||||
sizeof(struct pci_softc), pci_driver);
|
||||
DRIVER_MODULE(ofw_pcibus, pcib, ofw_pcibus_driver, pci_devclass, 0, 0);
|
||||
MODULE_VERSION(ofw_pcibus, 1);
|
||||
MODULE_DEPEND(ofw_pcibus, pci, 1, 1, 1);
|
||||
@ -116,12 +116,13 @@ static int
|
||||
ofw_pcibus_attach(device_t dev)
|
||||
{
|
||||
u_int busno, domain;
|
||||
int error;
|
||||
|
||||
error = pci_attach_common(dev);
|
||||
if (error)
|
||||
return (error);
|
||||
domain = pcib_get_domain(dev);
|
||||
busno = pcib_get_bus(dev);
|
||||
if (bootverbose)
|
||||
device_printf(dev, "domain=%d, physical bus=%d\n",
|
||||
domain, busno);
|
||||
|
||||
/*
|
||||
* Attach those children represented in the device tree.
|
||||
|
@ -100,8 +100,8 @@ struct ofw_pcibus_devinfo {
|
||||
|
||||
static devclass_t pci_devclass;
|
||||
|
||||
DEFINE_CLASS_1(pci, ofw_pcibus_driver, ofw_pcibus_methods, 1 /* no softc */,
|
||||
pci_driver);
|
||||
DEFINE_CLASS_1(pci, ofw_pcibus_driver, ofw_pcibus_methods,
|
||||
sizeof(struct pci_softc), pci_driver);
|
||||
EARLY_DRIVER_MODULE(ofw_pcibus, pcib, ofw_pcibus_driver, pci_devclass, 0, 0,
|
||||
BUS_PASS_BUS);
|
||||
MODULE_VERSION(ofw_pcibus, 1);
|
||||
@ -230,13 +230,14 @@ ofw_pcibus_attach(device_t dev)
|
||||
phandle_t node, child;
|
||||
uint32_t clock;
|
||||
u_int busno, domain, func, slot;
|
||||
int error;
|
||||
|
||||
error = pci_attach_common(dev);
|
||||
if (error)
|
||||
return (error);
|
||||
pcib = device_get_parent(dev);
|
||||
domain = pcib_get_domain(dev);
|
||||
busno = pcib_get_bus(dev);
|
||||
if (bootverbose)
|
||||
device_printf(dev, "domain=%d, physical bus=%d\n",
|
||||
domain, busno);
|
||||
node = ofw_bus_get_node(dev);
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user