John Baldwin
2016-04-22 18:54:53 UTC
Yet another extension I've long wanted to make to new-bus is to split out the
part of bus_activate_resource() that establishes a valid mapping for use with
bus_space_* (or the bus_* wrappers) from activating / detactivating. In
particular, making a resource "active" is orthogonal to having a mapping (e.g.
for a PCI BAR, a resource is "active" if the appropriate IO or mem decoding
bit is set in the device's command register. Whether or not the CPU has a
valid mapping for that range doesn't matter).
Secondly, there is a need to be able to specify optional parameters of
mappings. Some drivers may wish to only map a portion of a resource instead
of all of it (e.g. the AGP driver wishes to only map the first page of the
aperture instead of all of the aperture to avoid wasting a lot of KVA on 32-
bit systems). Some drivers may wish to map a memory resource with non-default
memory attributes (e.g. WC).
I have a strawman with an implementation on x86 to permit this.
In this model, a new RF_UNMAPPED flag is added that asks
bus_activate_resource() to not setup the implicit mapping in 'struct
resource'. Instead, a driver requests explicit mappings via
bus_map_resource() and is responsible for calling bus_unmap_resource() to tear
them down. A driver should allocate a 'struct resource_map' for each mapping
(probably by putting it in its softc) and then passing a pointer to that
object to both routines. This structure's members are named so that you can
use the bus_* convenience API on it the same way you can with 'struct
resource' for the implicit mapping.
bus_map_resource() accepts an optional 'args' argument that defines optional
properties of the mapping request. A driver can request a mapping of a subset
of a resource or a specific memory attribute. The 'args' argument is defined
as a structure headed by a size similar to the scheme Konstantin recently used
for make_dev_s().
One use case for this is that I'd like to fix the NEW_PCIB bits in the PCI-PCI
bridge driver to request a mapping in the subset of the resource on the
"parent" bus for the mapping window used by a resource for a child device
instead of passing up that child resource directly to the nexus. The idea is
that any bus driver that creates its own rman and resources should not be
passing those resources up to any of its parents.
Another use case that would benefit from this are bridges that do address
translations (such as the ThunderX Host-PCI bridge driver recently committed).
It can allocate a resource from its parent representing the "parent" side of
its resource window and request mappings for regions of that window
corresponding to child resources when creating mappings of child resources.
What I'd like feedback on now is the API. If we decide to go forward I would
also like help fixing bus drivers to use this.
Some sample code for mapping a resource that uses a WC mapping:
struct foo_softc {
...
struct resource *sc_regs_res;
struct resource_map sc_regs;
...
};
foo_attach(device_t dev)
{
struct resource_map_request args;
...
sc->sc_regs_res = bus_alloc_resource(dev, ..., RF_ACTIVE |
RF_UNMAPPED);
resource_init_map_request(&args, sizeof(args));
args.memattr = VM_MEMATTR_WRITE_COMBINING;
error = bus_map_resource(dev, SYS_RES_MEMORY, sc->regs_res,
&args, &sc->sc_regs);
...
}
foo_something(struct foo_softc *sc)
{
x = bus_read_4(&sc->sc_regs, MY_CSR);
}
foo_detach(device_t dev)
{
bus_unmap_resource(dev, SYS_RES_MEMORY, sc->regs_res, &sc->sc_regs);
bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->regs_res),
sc->regs_res);
}
There is a review with the current WIP code that includes the API and an
implementation for x86. It does not yet have manual page updates.
https://reviews.freebsd.org/D5237
part of bus_activate_resource() that establishes a valid mapping for use with
bus_space_* (or the bus_* wrappers) from activating / detactivating. In
particular, making a resource "active" is orthogonal to having a mapping (e.g.
for a PCI BAR, a resource is "active" if the appropriate IO or mem decoding
bit is set in the device's command register. Whether or not the CPU has a
valid mapping for that range doesn't matter).
Secondly, there is a need to be able to specify optional parameters of
mappings. Some drivers may wish to only map a portion of a resource instead
of all of it (e.g. the AGP driver wishes to only map the first page of the
aperture instead of all of the aperture to avoid wasting a lot of KVA on 32-
bit systems). Some drivers may wish to map a memory resource with non-default
memory attributes (e.g. WC).
I have a strawman with an implementation on x86 to permit this.
In this model, a new RF_UNMAPPED flag is added that asks
bus_activate_resource() to not setup the implicit mapping in 'struct
resource'. Instead, a driver requests explicit mappings via
bus_map_resource() and is responsible for calling bus_unmap_resource() to tear
them down. A driver should allocate a 'struct resource_map' for each mapping
(probably by putting it in its softc) and then passing a pointer to that
object to both routines. This structure's members are named so that you can
use the bus_* convenience API on it the same way you can with 'struct
resource' for the implicit mapping.
bus_map_resource() accepts an optional 'args' argument that defines optional
properties of the mapping request. A driver can request a mapping of a subset
of a resource or a specific memory attribute. The 'args' argument is defined
as a structure headed by a size similar to the scheme Konstantin recently used
for make_dev_s().
One use case for this is that I'd like to fix the NEW_PCIB bits in the PCI-PCI
bridge driver to request a mapping in the subset of the resource on the
"parent" bus for the mapping window used by a resource for a child device
instead of passing up that child resource directly to the nexus. The idea is
that any bus driver that creates its own rman and resources should not be
passing those resources up to any of its parents.
Another use case that would benefit from this are bridges that do address
translations (such as the ThunderX Host-PCI bridge driver recently committed).
It can allocate a resource from its parent representing the "parent" side of
its resource window and request mappings for regions of that window
corresponding to child resources when creating mappings of child resources.
What I'd like feedback on now is the API. If we decide to go forward I would
also like help fixing bus drivers to use this.
Some sample code for mapping a resource that uses a WC mapping:
struct foo_softc {
...
struct resource *sc_regs_res;
struct resource_map sc_regs;
...
};
foo_attach(device_t dev)
{
struct resource_map_request args;
...
sc->sc_regs_res = bus_alloc_resource(dev, ..., RF_ACTIVE |
RF_UNMAPPED);
resource_init_map_request(&args, sizeof(args));
args.memattr = VM_MEMATTR_WRITE_COMBINING;
error = bus_map_resource(dev, SYS_RES_MEMORY, sc->regs_res,
&args, &sc->sc_regs);
...
}
foo_something(struct foo_softc *sc)
{
x = bus_read_4(&sc->sc_regs, MY_CSR);
}
foo_detach(device_t dev)
{
bus_unmap_resource(dev, SYS_RES_MEMORY, sc->regs_res, &sc->sc_regs);
bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->regs_res),
sc->regs_res);
}
There is a review with the current WIP code that includes the API and an
implementation for x86. It does not yet have manual page updates.
https://reviews.freebsd.org/D5237
--
John Baldwin
John Baldwin