Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F102065349
D45406.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
D45406.diff
View Options
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -164,10 +164,18 @@
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
DEVMETHOD(bus_delete_resource, pci_delete_resource),
DEVMETHOD(bus_alloc_resource, pci_alloc_resource),
+#ifdef PCI_IOV
+ DEVMETHOD(bus_adjust_resource, pci_adjust_resource),
+#else
DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
+#endif
DEVMETHOD(bus_release_resource, pci_release_resource),
DEVMETHOD(bus_activate_resource, pci_activate_resource),
DEVMETHOD(bus_deactivate_resource, pci_deactivate_resource),
+#ifdef PCI_IOV
+ DEVMETHOD(bus_map_resource, pci_map_resource),
+ DEVMETHOD(bus_unmap_resource, pci_unmap_resource),
+#endif
DEVMETHOD(bus_child_deleted, pci_child_deleted),
DEVMETHOD(bus_child_detached, pci_child_detached),
DEVMETHOD(bus_child_pnpinfo, pci_child_pnpinfo_method),
@@ -5687,14 +5695,30 @@
struct pci_devinfo *dinfo;
int error, rid, type;
- error = bus_generic_activate_resource(dev, child, r);
+ dinfo = device_get_ivars(child);
+#ifdef PCI_IOV
+ if (dinfo->cfg.flags & PCICFG_VF) {
+ switch (rman_get_type(r)) {
+ /* VFs can't have I/O BARs. */
+ case SYS_RES_IOPORT:
+ error = EINVAL;
+ break;
+ case SYS_RES_MEMORY:
+ error = pci_vf_activate_mem_resource(dev, child, r);
+ break;
+ default:
+ error = bus_generic_activate_resource(dev, child, r);
+ break;
+ }
+ } else
+#endif
+ error = bus_generic_activate_resource(dev, child, r);
if (error)
return (error);
/* Enable decoding in the command register when activating BARs. */
if (device_get_parent(child) == dev) {
/* Device ROMs need their decoding explicitly enabled. */
- dinfo = device_get_ivars(child);
rid = rman_get_rid(r);
type = rman_get_type(r);
if (type == SYS_RES_MEMORY && PCIR_IS_BIOS(&dinfo->cfg, rid))
@@ -5716,13 +5740,29 @@
struct pci_devinfo *dinfo;
int error, rid, type;
- error = bus_generic_deactivate_resource(dev, child, r);
+ dinfo = device_get_ivars(child);
+#ifdef PCI_IOV
+ if (dinfo->cfg.flags & PCICFG_VF) {
+ switch (rman_get_type(r)) {
+ /* VFs can't have I/O BARs. */
+ case SYS_RES_IOPORT:
+ error = EINVAL;
+ break;
+ case SYS_RES_MEMORY:
+ error = pci_vf_deactivate_mem_resource(dev, child, r);
+ break;
+ default:
+ error = bus_generic_deactivate_resource(dev, child, r);
+ break;
+ }
+ } else
+#endif
+ error = bus_generic_deactivate_resource(dev, child, r);
if (error)
return (error);
/* Disable decoding for device ROMs. */
if (device_get_parent(child) == dev) {
- dinfo = device_get_ivars(child);
rid = rman_get_rid(r);
type = rman_get_type(r);
if (type == SYS_RES_MEMORY && PCIR_IS_BIOS(&dinfo->cfg, rid))
@@ -5732,6 +5772,76 @@
return (0);
}
+#ifdef PCI_IOV
+int
+pci_adjust_resource(device_t dev, device_t child, struct resource *r,
+ rman_res_t start, rman_res_t end)
+{
+ struct pci_devinfo *dinfo;
+
+ dinfo = device_get_ivars(child);
+ if (dinfo->cfg.flags & PCICFG_VF) {
+ switch (rman_get_type(r)) {
+ /* VFs can't have I/O BARs. */
+ case SYS_RES_IOPORT:
+ return (EINVAL);
+ case SYS_RES_MEMORY:
+ return (pci_vf_adjust_mem_resource(dev, child, r,
+ start, end));
+ }
+
+ /* Fall through for other types of resource allocations. */
+ }
+
+ return (bus_generic_adjust_resource(dev, child, r, start, end));
+}
+
+int
+pci_map_resource(device_t dev, device_t child, struct resource *r,
+ struct resource_map_request *argsp, struct resource_map *map)
+{
+ struct pci_devinfo *dinfo;
+
+ dinfo = device_get_ivars(child);
+ if (dinfo->cfg.flags & PCICFG_VF) {
+ switch (rman_get_type(r)) {
+ /* VFs can't have I/O BARs. */
+ case SYS_RES_IOPORT:
+ return (EINVAL);
+ case SYS_RES_MEMORY:
+ return (pci_vf_map_mem_resource(dev, child, r, argsp,
+ map));
+ }
+
+ /* Fall through for other types of resource allocations. */
+ }
+
+ return (bus_generic_map_resource(dev, child, r, argsp, map));
+}
+
+int
+pci_unmap_resource(device_t dev, device_t child, struct resource *r,
+ struct resource_map *map)
+{
+ struct pci_devinfo *dinfo;
+
+ dinfo = device_get_ivars(child);
+ if (dinfo->cfg.flags & PCICFG_VF) {
+ switch (rman_get_type(r)) {
+ /* VFs can't have I/O BARs. */
+ case SYS_RES_IOPORT:
+ return (EINVAL);
+ case SYS_RES_MEMORY:
+ return (pci_vf_unmap_mem_resource(dev, child, r, map));
+ }
+
+ /* Fall through for other types of resource allocations. */
+ }
+
+ return (bus_generic_unmap_resource(dev, child, r, map));
+}
+#endif
+
void
pci_child_deleted(device_t dev, device_t child)
{
diff --git a/sys/dev/pci/pci_iov.c b/sys/dev/pci/pci_iov.c
--- a/sys/dev/pci/pci_iov.c
+++ b/sys/dev/pci/pci_iov.c
@@ -1070,6 +1070,12 @@
dinfo = device_get_ivars(child);
+ KASSERT(rman_get_type(r) == SYS_RES_MEMORY,
+ ("%s: invalid resource %p", __func__, r));
+ KASSERT(rman_is_region_manager(r, &dinfo->cfg.iov->rman),
+ ("%s: rman %p doesn't match for resource %p", __func__,
+ &dinfo->cfg.iov->rman, r));
+
if (rman_get_flags(r) & RF_ACTIVE) {
error = bus_deactivate_resource(child, r);
if (error != 0)
@@ -1086,3 +1092,148 @@
return (rman_release_resource(r));
}
+
+int
+pci_vf_activate_mem_resource(device_t dev, device_t child, struct resource *r)
+{
+#ifdef INVARIANTS
+ struct pci_devinfo *dinfo = device_get_ivars(child);
+#endif
+ struct resource_map map;
+ int error;
+
+ KASSERT(rman_get_type(r) == SYS_RES_MEMORY,
+ ("%s: invalid resource %p", __func__, r));
+ KASSERT(rman_is_region_manager(r, &dinfo->cfg.iov->rman),
+ ("%s: rman %p doesn't match for resource %p", __func__,
+ &dinfo->cfg.iov->rman, r));
+
+ error = rman_activate_resource(r);
+ if (error != 0)
+ return (error);
+
+ if ((rman_get_flags(r) & RF_UNMAPPED) == 0) {
+ error = BUS_MAP_RESOURCE(dev, child, r, NULL, &map);
+ if (error != 0) {
+ rman_deactivate_resource(r);
+ return (error);
+ }
+
+ rman_set_mapping(r, &map);
+ }
+ return (0);
+}
+
+int
+pci_vf_deactivate_mem_resource(device_t dev, device_t child, struct resource *r)
+{
+#ifdef INVARIANTS
+ struct pci_devinfo *dinfo = device_get_ivars(child);
+#endif
+ struct resource_map map;
+ int error;
+
+ KASSERT(rman_get_type(r) == SYS_RES_MEMORY,
+ ("%s: invalid resource %p", __func__, r));
+ KASSERT(rman_is_region_manager(r, &dinfo->cfg.iov->rman),
+ ("%s: rman %p doesn't match for resource %p", __func__,
+ &dinfo->cfg.iov->rman, r));
+
+ error = rman_deactivate_resource(r);
+ if (error != 0)
+ return (error);
+
+ if ((rman_get_flags(r) & RF_UNMAPPED) == 0) {
+ rman_get_mapping(r, &map);
+ BUS_UNMAP_RESOURCE(dev, child, r, &map);
+ }
+ return (0);
+}
+
+int
+pci_vf_adjust_mem_resource(device_t dev, device_t child, struct resource *r,
+ rman_res_t start, rman_res_t end)
+{
+#ifdef INVARIANTS
+ struct pci_devinfo *dinfo = device_get_ivars(child);
+#endif
+
+ KASSERT(rman_get_type(r) == SYS_RES_MEMORY,
+ ("%s: invalid resource %p", __func__, r));
+ KASSERT(rman_is_region_manager(r, &dinfo->cfg.iov->rman),
+ ("%s: rman %p doesn't match for resource %p", __func__,
+ &dinfo->cfg.iov->rman, r));
+
+ return (rman_adjust_resource(r, start, end));
+}
+
+static struct resource *
+pci_vf_find_parent_resource(struct pcicfg_iov *iov, struct resource *r)
+{
+ struct resource *pres;
+
+ for (u_int i = 0; i <= PCIR_MAX_BAR_0; i++) {
+ pres = iov->iov_bar[i].res;
+ if (pres != NULL) {
+ if (rman_get_start(pres) <= rman_get_start(r) &&
+ rman_get_end(pres) >= rman_get_end(r))
+ return (pres);
+ }
+ }
+ return (NULL);
+}
+
+int
+pci_vf_map_mem_resource(device_t dev, device_t child, struct resource *r,
+ struct resource_map_request *argsp, struct resource_map *map)
+{
+ struct pci_devinfo *dinfo = device_get_ivars(child);
+ struct pcicfg_iov *iov = dinfo->cfg.iov;
+ struct resource_map_request args;
+ struct resource *pres;
+ rman_res_t length, start;
+ int error;
+
+ KASSERT(rman_get_type(r) == SYS_RES_MEMORY,
+ ("%s: invalid resource %p", __func__, r));
+ KASSERT(rman_is_region_manager(r, &iov->rman),
+ ("%s: rman %p doesn't match for resource %p", __func__,
+ &dinfo->cfg.iov->rman, r));
+
+ /* Resources must be active to be mapped. */
+ if (!(rman_get_flags(r) & RF_ACTIVE))
+ return (ENXIO);
+
+ resource_init_map_request(&args);
+ error = resource_validate_map_request(r, argsp, &args, &start, &length);
+ if (error)
+ return (error);
+
+ pres = pci_vf_find_parent_resource(dinfo->cfg.iov, r);
+ if (pres == NULL)
+ return (ENOENT);
+
+ args.offset = start - rman_get_start(pres);
+ args.length = length;
+ return (bus_map_resource(iov->iov_pf, pres, &args, map));
+}
+
+int
+pci_vf_unmap_mem_resource(device_t dev, device_t child, struct resource *r,
+ struct resource_map *map)
+{
+ struct pci_devinfo *dinfo = device_get_ivars(child);
+ struct pcicfg_iov *iov = dinfo->cfg.iov;
+ struct resource *pres;
+
+ KASSERT(rman_get_type(r) == SYS_RES_MEMORY,
+ ("%s: invalid resource %p", __func__, r));
+ KASSERT(rman_is_region_manager(r, &iov->rman),
+ ("%s: rman %p doesn't match for resource %p", __func__,
+ &dinfo->cfg.iov->rman, r));
+
+ pres = pci_vf_find_parent_resource(iov, r);
+ if (pres == NULL)
+ return (ENOENT);
+ return (bus_unmap_resource(iov->iov_pf, pres, map));
+}
diff --git a/sys/dev/pci/pci_private.h b/sys/dev/pci/pci_private.h
--- a/sys/dev/pci/pci_private.h
+++ b/sys/dev/pci/pci_private.h
@@ -65,9 +65,16 @@
bus_get_resource_list_t pci_get_resource_list;
bus_delete_resource_t pci_delete_resource;
bus_alloc_resource_t pci_alloc_resource;
+#ifdef PCI_IOV
+bus_adjust_resource_t pci_adjust_resource;
+#endif
bus_release_resource_t pci_release_resource;
bus_activate_resource_t pci_activate_resource;
bus_deactivate_resource_t pci_deactivate_resource;
+#ifdef PCI_IOV
+bus_map_resource_t pci_map_resource;
+bus_unmap_resource_t pci_unmap_resource;
+#endif
bus_child_deleted_t pci_child_deleted;
bus_child_detached_t pci_child_detached;
bus_child_pnpinfo_t pci_child_pnpinfo_method;
@@ -158,4 +165,16 @@
rman_res_t count, u_int flags);
int pci_vf_release_mem_resource(device_t dev, device_t child,
struct resource *r);
+int pci_vf_activate_mem_resource(device_t dev, device_t child,
+ struct resource *r);
+int pci_vf_deactivate_mem_resource(device_t dev, device_t child,
+ struct resource *r);
+int pci_vf_adjust_mem_resource(device_t dev, device_t child,
+ struct resource *r, rman_res_t start, rman_res_t end);
+int pci_vf_map_mem_resource(device_t dev, device_t child,
+ struct resource *r, struct resource_map_request *argsp,
+ struct resource_map *map);
+int pci_vf_unmap_mem_resource(device_t dev, device_t child,
+ struct resource *r, struct resource_map *map);
+
#endif /* _PCI_PRIVATE_H_ */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Nov 8, 4:44 AM (22 h, 15 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14527884
Default Alt Text
D45406.diff (10 KB)
Attached To
Mode
D45406: pci: Consistently use pci_vf_* for suballocated VF memory resources
Attached
Detach File
Event Timeline
Log In to Comment