2020-03-19 15:42:06

by Diana Madalina Craciun

[permalink] [raw]
Subject: [PATCH 00/10] bus/fsl-mc: Extend mc-bus driver functionalities in preparation for mc-bus VFIO support

The vfio-mc bus driver needs some additional services to be exported by the
mc-bus driver like:
- a way to reset the DPRC container
- support for driver_override such taht the objects within a DPRC to be
bind to the VFIO driver
- functions to setup/tear dowan a DPRC
- functions for allocating the pool of interrupts. In case of VFIO the
interrupts are not configured at probe time, but later, when the userspace
configures the interrupts.

Bharat Bhushan (3):
bus/fsl-mc: add support for 'driver_override' in the mc-bus
bus/fsl-mc: Propagate driver_override for a child DPRC's children
bus/fsl-mc: Add dprc-reset-container support

Diana Craciun (7):
bus/fsl-mc: Do no longer export the total number of irqs outside dprc_scan_objects
bus/fsl-mc: Add a new parameter to dprc_scan_objects function
bus/fsl-mc: Set the QMAN/BMAN region flags
bus/fsl-mc: Export a dprc scan function to be used by multiple
entities
bus/fsl-mc: Export a cleanup function for DPRC
bus/fsl-mc: Add a container setup function
bus/fsl-mc: Export IRQ pool handling functions to be used by VFIO

drivers/bus/fsl-mc/dprc-driver.c | 184 ++++++++++++++++----------
drivers/bus/fsl-mc/dprc.c | 41 ++++++
drivers/bus/fsl-mc/fsl-mc-allocator.c | 12 +-
drivers/bus/fsl-mc/fsl-mc-bus.c | 81 +++++++++++-
drivers/bus/fsl-mc/fsl-mc-private.h | 23 +---
drivers/bus/fsl-mc/mc-io.c | 7 +-
include/linux/fsl/mc.h | 27 ++++
7 files changed, 279 insertions(+), 96 deletions(-)

--
2.17.1


2020-03-19 15:42:07

by Diana Madalina Craciun

[permalink] [raw]
Subject: [PATCH 07/10] bus/fsl-mc: Export a dprc scan function to be used by multiple entities

Currently the DPRC scan function is used only by the bus driver.
But the same functionality will be needed by the VFIO driver.
To support this, the dprc scan function was exported and a little
bit adjusted to fit both scenarios.

Signed-off-by: Diana Craciun <[email protected]>
---
drivers/bus/fsl-mc/dprc-driver.c | 15 ++++++---------
drivers/bus/fsl-mc/fsl-mc-bus.c | 2 ++
include/linux/fsl/mc.h | 4 ++++
3 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/drivers/bus/fsl-mc/dprc-driver.c b/drivers/bus/fsl-mc/dprc-driver.c
index 7eaf78900dfc..789220f0372a 100644
--- a/drivers/bus/fsl-mc/dprc-driver.c
+++ b/drivers/bus/fsl-mc/dprc-driver.c
@@ -335,7 +335,9 @@ static int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
* bus driver with the actual state of the MC by adding and removing
* devices as appropriate.
*/
-static int dprc_scan_container(struct fsl_mc_device *mc_bus_dev)
+int dprc_scan_container(struct fsl_mc_device *mc_bus_dev,
+ const char *driver_override,
+ bool alloc_interrupts)
{
int error;
struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
@@ -346,15 +348,12 @@ static int dprc_scan_container(struct fsl_mc_device *mc_bus_dev)
* Discover objects in the DPRC:
*/
mutex_lock(&mc_bus->scan_mutex);
- error = dprc_scan_objects(mc_bus_dev, NULL, true);
+ error = dprc_scan_objects(mc_bus_dev, driver_override, alloc_interrupts);
mutex_unlock(&mc_bus->scan_mutex);
- if (error < 0) {
- fsl_mc_cleanup_all_resource_pools(mc_bus_dev);
- return error;
- }

return 0;
}
+EXPORT_SYMBOL_GPL(dprc_scan_container);

/**
* dprc_irq0_handler - Regular ISR for DPRC interrupt 0
@@ -679,12 +678,10 @@ static int dprc_probe(struct fsl_mc_device *mc_dev)
goto error_cleanup_open;
}

- mutex_init(&mc_bus->scan_mutex);
-
/*
* Discover MC objects in DPRC object:
*/
- error = dprc_scan_container(mc_dev);
+ error = dprc_scan_container(mc_dev, NULL, true);
if (error < 0)
goto error_cleanup_open;

diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
index a99a0edef252..1865221bb12d 100644
--- a/drivers/bus/fsl-mc/fsl-mc-bus.c
+++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
@@ -635,7 +635,9 @@ int fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc,
if (!mc_bus)
return -ENOMEM;

+ mutex_init(&mc_bus->scan_mutex);
mc_dev = &mc_bus->mc_dev;
+
} else {
/*
* Allocate a regular fsl_mc_device object:
diff --git a/include/linux/fsl/mc.h b/include/linux/fsl/mc.h
index b9d5e5955adb..2bdd96a482fb 100644
--- a/include/linux/fsl/mc.h
+++ b/include/linux/fsl/mc.h
@@ -476,6 +476,10 @@ int dprc_reset_container(struct fsl_mc_io *mc_io,
u16 token,
int child_container_id);

+int dprc_scan_container(struct fsl_mc_device *mc_bus_dev,
+ const char *driver_override,
+ bool alloc_interrupts);
+
/*
* Data Path Buffer Pool (DPBP) API
* Contains initialization APIs and runtime control APIs for DPBP
--
2.17.1

2020-03-19 15:42:18

by Diana Madalina Craciun

[permalink] [raw]
Subject: [PATCH 06/10] bus/fsl-mc: Add dprc-reset-container support

From: Bharat Bhushan <[email protected]>

DPRC reset is required by VFIO-mc in order to stop a device
to further generate DMA transactions.

Signed-off-by: Bharat Bhushan <[email protected]>
Signed-off-by: Laurentiu Tudor <[email protected]>
Signed-off-by: Diana Craciun <[email protected]>
---
drivers/bus/fsl-mc/dprc.c | 41 +++++++++++++++++++++++++++++
drivers/bus/fsl-mc/fsl-mc-private.h | 5 ++++
include/linux/fsl/mc.h | 5 ++++
3 files changed, 51 insertions(+)

diff --git a/drivers/bus/fsl-mc/dprc.c b/drivers/bus/fsl-mc/dprc.c
index 602f030d84eb..5ae17fd957ba 100644
--- a/drivers/bus/fsl-mc/dprc.c
+++ b/drivers/bus/fsl-mc/dprc.c
@@ -72,6 +72,47 @@ int dprc_close(struct fsl_mc_io *mc_io,
}
EXPORT_SYMBOL_GPL(dprc_close);

+/**
+ * dprc_reset_container - Reset child container.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPRC object
+ * @child_container_id: ID of the container to reset
+ *
+ * In case a software context crashes or becomes non-responsive, the parent
+ * may wish to reset its resources container before the software context is
+ * restarted.
+ *
+ * This routine informs all objects assigned to the child container that the
+ * container is being reset, so they may perform any cleanup operations that are
+ * needed. All objects handles that were owned by the child container shall be
+ * closed.
+ *
+ * Note that such request may be submitted even if the child software context
+ * has not crashed, but the resulting object cleanup operations will not be
+ * aware of that.
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dprc_reset_container(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ u16 token,
+ int child_container_id)
+{
+ struct fsl_mc_command cmd = { 0 };
+ struct dprc_cmd_reset_container *cmd_params;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_RESET_CONT,
+ cmd_flags, token);
+ cmd_params = (struct dprc_cmd_reset_container *)cmd.params;
+ cmd_params->child_container_id = cpu_to_le32(child_container_id);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+EXPORT_SYMBOL_GPL(dprc_reset_container);
+
/**
* dprc_set_irq() - Set IRQ information for the DPRC to trigger an interrupt.
* @mc_io: Pointer to MC portal's I/O object
diff --git a/drivers/bus/fsl-mc/fsl-mc-private.h b/drivers/bus/fsl-mc/fsl-mc-private.h
index 81b9a9b16698..66ccf7fb34af 100644
--- a/drivers/bus/fsl-mc/fsl-mc-private.h
+++ b/drivers/bus/fsl-mc/fsl-mc-private.h
@@ -92,6 +92,7 @@ int dpmcp_reset(struct fsl_mc_io *mc_io,
#define DPRC_CMDID_GET_API_VERSION DPRC_CMD(0xa05)

#define DPRC_CMDID_GET_ATTR DPRC_CMD(0x004)
+#define DPRC_CMDID_RESET_CONT DPRC_CMD(0x005)

#define DPRC_CMDID_SET_IRQ DPRC_CMD(0x010)
#define DPRC_CMDID_SET_IRQ_ENABLE DPRC_CMD(0x012)
@@ -112,6 +113,10 @@ struct dprc_cmd_open {
__le32 container_id;
};

+struct dprc_cmd_reset_container {
+ __le32 child_container_id;
+};
+
struct dprc_cmd_set_irq {
/* cmd word 0 */
__le32 irq_val;
diff --git a/include/linux/fsl/mc.h b/include/linux/fsl/mc.h
index f997f8091408..b9d5e5955adb 100644
--- a/include/linux/fsl/mc.h
+++ b/include/linux/fsl/mc.h
@@ -471,6 +471,11 @@ static inline bool is_fsl_mc_bus_dpseci(const struct fsl_mc_device *mc_dev)
return mc_dev->dev.type == &fsl_mc_bus_dpseci_type;
}

+int dprc_reset_container(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ u16 token,
+ int child_container_id);
+
/*
* Data Path Buffer Pool (DPBP) API
* Contains initialization APIs and runtime control APIs for DPBP
--
2.17.1

2020-03-19 15:42:23

by Diana Madalina Craciun

[permalink] [raw]
Subject: [PATCH 10/10] bus/fsl-mc: Export IRQ pool handling functions to be used by VFIO

The IRQ pool handling functions can be used by both DPRC
driver and VFIO. Adapt and export those functions.

Signed-off-by: Diana Craciun <[email protected]>
---
drivers/bus/fsl-mc/dprc-driver.c | 5 ++---
drivers/bus/fsl-mc/fsl-mc-allocator.c | 12 ++++++++----
drivers/bus/fsl-mc/fsl-mc-private.h | 10 ----------
include/linux/fsl/mc.h | 11 +++++++++++
4 files changed, 21 insertions(+), 17 deletions(-)

diff --git a/drivers/bus/fsl-mc/dprc-driver.c b/drivers/bus/fsl-mc/dprc-driver.c
index 0fe45c301858..2a64172c0101 100644
--- a/drivers/bus/fsl-mc/dprc-driver.c
+++ b/drivers/bus/fsl-mc/dprc-driver.c
@@ -307,7 +307,7 @@ static int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
}

if (alloc_interrupts && !mc_bus->irq_resources) {
- error = fsl_mc_populate_irq_pool(mc_bus,
+ error = fsl_mc_populate_irq_pool(mc_bus_dev,
FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
if (error < 0)
return error;
@@ -763,7 +763,6 @@ static void dprc_teardown_irq(struct fsl_mc_device *mc_dev)
int dprc_cleanup(struct fsl_mc_device *mc_dev)
{
int error;
- struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);

if (!is_fsl_mc_bus_dprc(mc_dev))
return -EINVAL;
@@ -772,7 +771,7 @@ int dprc_cleanup(struct fsl_mc_device *mc_dev)
return -EINVAL;

if (dev_get_msi_domain(&mc_dev->dev)) {
- fsl_mc_cleanup_irq_pool(mc_bus);
+ fsl_mc_cleanup_irq_pool(mc_dev);
dev_set_msi_domain(&mc_dev->dev, NULL);
}

diff --git a/drivers/bus/fsl-mc/fsl-mc-allocator.c b/drivers/bus/fsl-mc/fsl-mc-allocator.c
index cc7bb900f524..e71a6f52ea0c 100644
--- a/drivers/bus/fsl-mc/fsl-mc-allocator.c
+++ b/drivers/bus/fsl-mc/fsl-mc-allocator.c
@@ -344,7 +344,7 @@ EXPORT_SYMBOL_GPL(fsl_mc_object_free);
* Initialize the interrupt pool associated with an fsl-mc bus.
* It allocates a block of IRQs from the GIC-ITS.
*/
-int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus,
+int fsl_mc_populate_irq_pool(struct fsl_mc_device *mc_bus_dev,
unsigned int irq_count)
{
unsigned int i;
@@ -352,10 +352,14 @@ int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus,
struct fsl_mc_device_irq *irq_resources;
struct fsl_mc_device_irq *mc_dev_irq;
int error;
- struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
+ struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
struct fsl_mc_resource_pool *res_pool =
&mc_bus->resource_pools[FSL_MC_POOL_IRQ];

+ /* do nothing if the IRQ pool is already populated */
+ if (mc_bus->irq_resources)
+ return 0;
+
if (irq_count == 0 ||
irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS)
return -EINVAL;
@@ -407,9 +411,9 @@ EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool);
* Teardown the interrupt pool associated with an fsl-mc bus.
* It frees the IRQs that were allocated to the pool, back to the GIC-ITS.
*/
-void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus)
+void fsl_mc_cleanup_irq_pool(struct fsl_mc_device *mc_bus_dev)
{
- struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
+ struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
struct fsl_mc_resource_pool *res_pool =
&mc_bus->resource_pools[FSL_MC_POOL_IRQ];

diff --git a/drivers/bus/fsl-mc/fsl-mc-private.h b/drivers/bus/fsl-mc/fsl-mc-private.h
index 66ccf7fb34af..2762e9ecb098 100644
--- a/drivers/bus/fsl-mc/fsl-mc-private.h
+++ b/drivers/bus/fsl-mc/fsl-mc-private.h
@@ -518,11 +518,6 @@ struct dpcon_cmd_set_notification {
__le64 user_ctx;
};

-/**
- * Maximum number of total IRQs that can be pre-allocated for an MC bus'
- * IRQ pool
- */
-#define FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS 256

/**
* struct fsl_mc_resource_pool - Pool of MC resources of a given
@@ -599,11 +594,6 @@ void fsl_mc_msi_domain_free_irqs(struct device *dev);
int fsl_mc_find_msi_domain(struct device *mc_platform_dev,
struct irq_domain **mc_msi_domain);

-int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus,
- unsigned int irq_count);
-
-void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus);
-
int __must_check fsl_create_mc_io(struct device *dev,
phys_addr_t mc_portal_phys_addr,
u32 mc_portal_size,
diff --git a/include/linux/fsl/mc.h b/include/linux/fsl/mc.h
index 59b39c635ec9..ad918b99be42 100644
--- a/include/linux/fsl/mc.h
+++ b/include/linux/fsl/mc.h
@@ -484,6 +484,17 @@ int dprc_setup(struct fsl_mc_device *mc_dev);

int dprc_cleanup(struct fsl_mc_device *mc_dev);

+/**
+ * Maximum number of total IRQs that can be pre-allocated for an MC bus'
+ * IRQ pool
+ */
+#define FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS 256
+
+int fsl_mc_populate_irq_pool(struct fsl_mc_device *mc_bus_dev,
+ unsigned int irq_count);
+
+void fsl_mc_cleanup_irq_pool(struct fsl_mc_device *mc_bus_dev);
+
/*
* Data Path Buffer Pool (DPBP) API
* Contains initialization APIs and runtime control APIs for DPBP
--
2.17.1

2020-03-19 15:42:40

by Diana Madalina Craciun

[permalink] [raw]
Subject: [PATCH 05/10] bus/fsl-mc: Set the QMAN/BMAN region flags

The QMAN region is memory mapped, so it should be of type
IORESOURCE_MEM. The region flags bits were wrongly used to
pass additional information. Use the bus specific bits for
this purpose.

Signed-off-by: Diana Craciun <[email protected]>
---
drivers/bus/fsl-mc/fsl-mc-bus.c | 7 ++-----
drivers/bus/fsl-mc/fsl-mc-private.h | 6 ------
2 files changed, 2 insertions(+), 11 deletions(-)

diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
index b9ccac9862b7..a99a0edef252 100644
--- a/drivers/bus/fsl-mc/fsl-mc-bus.c
+++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
@@ -571,11 +571,8 @@ static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev,

regions[i].end = regions[i].start + region_desc.size - 1;
regions[i].name = "fsl-mc object MMIO region";
- regions[i].flags = IORESOURCE_IO;
- if (region_desc.flags & DPRC_REGION_CACHEABLE)
- regions[i].flags |= IORESOURCE_CACHEABLE;
- if (region_desc.flags & DPRC_REGION_SHAREABLE)
- regions[i].flags |= IORESOURCE_MEM;
+ regions[i].flags = region_desc.flags & IORESOURCE_BITS;
+ regions[i].flags |= IORESOURCE_MEM;
}

mc_dev->regions = regions;
diff --git a/drivers/bus/fsl-mc/fsl-mc-private.h b/drivers/bus/fsl-mc/fsl-mc-private.h
index be6bb0fb4603..81b9a9b16698 100644
--- a/drivers/bus/fsl-mc/fsl-mc-private.h
+++ b/drivers/bus/fsl-mc/fsl-mc-private.h
@@ -359,12 +359,6 @@ int dprc_set_obj_irq(struct fsl_mc_io *mc_io,
int obj_id,
u8 irq_index,
struct dprc_irq_cfg *irq_cfg);
-
-/* Region flags */
-/* Cacheable - Indicates that region should be mapped as cacheable */
-#define DPRC_REGION_CACHEABLE 0x00000001
-#define DPRC_REGION_SHAREABLE 0x00000002
-
/**
* enum dprc_region_type - Region type
* @DPRC_REGION_TYPE_MC_PORTAL: MC portal region
--
2.17.1

2020-03-19 15:42:41

by Diana Madalina Craciun

[permalink] [raw]
Subject: [PATCH 09/10] bus/fsl-mc: Add a container setup function

Both DPRC driver and VFIO driver use a initialization code
for the DPRC. Introduced a new function which groups this
initialization code. The function is exported and may be
used by VFIO as well.

Signed-off-by: Diana Craciun <[email protected]>
---
drivers/bus/fsl-mc/dprc-driver.c | 77 +++++++++++++++++++++-----------
drivers/bus/fsl-mc/mc-io.c | 7 ++-
include/linux/fsl/mc.h | 2 +
3 files changed, 60 insertions(+), 26 deletions(-)

diff --git a/drivers/bus/fsl-mc/dprc-driver.c b/drivers/bus/fsl-mc/dprc-driver.c
index a655e3fee291..0fe45c301858 100644
--- a/drivers/bus/fsl-mc/dprc-driver.c
+++ b/drivers/bus/fsl-mc/dprc-driver.c
@@ -570,16 +570,15 @@ static int dprc_setup_irq(struct fsl_mc_device *mc_dev)
}

/**
- * dprc_probe - callback invoked when a DPRC is being bound to this driver
+ * dprc_setup - opens and creates a mc_io for DPRC
*
* @mc_dev: Pointer to fsl-mc device representing a DPRC
*
* It opens the physical DPRC in the MC.
- * It scans the DPRC to discover the MC objects contained in it.
- * It creates the interrupt pool for the MC bus associated with the DPRC.
- * It configures the interrupts for the DPRC device itself.
+ * It configures the DPRC portal used to communicate with MC
*/
-static int dprc_probe(struct fsl_mc_device *mc_dev)
+
+int dprc_setup(struct fsl_mc_device *mc_dev)
{
int error;
size_t region_size;
@@ -589,12 +588,6 @@ static int dprc_probe(struct fsl_mc_device *mc_dev)
bool msi_domain_set = false;
u16 major_ver, minor_ver;

- if (!is_fsl_mc_bus_dprc(mc_dev))
- return -EINVAL;
-
- if (dev_get_msi_domain(&mc_dev->dev))
- return -EINVAL;
-
if (!mc_dev->mc_io) {
/*
* This is a child DPRC:
@@ -678,35 +671,69 @@ static int dprc_probe(struct fsl_mc_device *mc_dev)
goto error_cleanup_open;
}

+ return 0;
+
+error_cleanup_open:
+ (void)dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
+
+error_cleanup_msi_domain:
+ if (msi_domain_set)
+ dev_set_msi_domain(&mc_dev->dev, NULL);
+
+ if (mc_io_created) {
+ fsl_destroy_mc_io(mc_dev->mc_io);
+ mc_dev->mc_io = NULL;
+ }
+
+ return error;
+}
+EXPORT_SYMBOL_GPL(dprc_setup);
+
+/**
+ * dprc_probe - callback invoked when a DPRC is being bound to this driver
+ *
+ * @mc_dev: Pointer to fsl-mc device representing a DPRC
+ *
+ * It opens the physical DPRC in the MC.
+ * It scans the DPRC to discover the MC objects contained in it.
+ * It creates the interrupt pool for the MC bus associated with the DPRC.
+ * It configures the interrupts for the DPRC device itself.
+ */
+static int dprc_probe(struct fsl_mc_device *mc_dev)
+{
+ int error;
+
+ if (!is_fsl_mc_bus_dprc(mc_dev))
+ return -EINVAL;
+
+ if (dev_get_msi_domain(&mc_dev->dev))
+ return -EINVAL;
+
+ error = dprc_setup(mc_dev);
+ if (error < 0)
+ return error;
+
/*
* Discover MC objects in DPRC object:
*/
error = dprc_scan_container(mc_dev, NULL, true);
if (error < 0)
- goto error_cleanup_open;
+ goto dprc_cleanup;

/*
* Configure interrupt for the DPRC object associated with this MC bus:
*/
error = dprc_setup_irq(mc_dev);
if (error < 0)
- goto error_cleanup_open;
+ goto scan_cleanup;

dev_info(&mc_dev->dev, "DPRC device bound to driver");
return 0;

-error_cleanup_open:
- (void)dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
-
-error_cleanup_msi_domain:
- if (msi_domain_set)
- dev_set_msi_domain(&mc_dev->dev, NULL);
-
- if (mc_io_created) {
- fsl_destroy_mc_io(mc_dev->mc_io);
- mc_dev->mc_io = NULL;
- }
-
+scan_cleanup:
+ device_for_each_child(&mc_dev->dev, NULL, __fsl_mc_device_remove);
+dprc_cleanup:
+ dprc_cleanup(mc_dev);
return error;
}

diff --git a/drivers/bus/fsl-mc/mc-io.c b/drivers/bus/fsl-mc/mc-io.c
index 6ae48ad80409..e1dfe4a76519 100644
--- a/drivers/bus/fsl-mc/mc-io.c
+++ b/drivers/bus/fsl-mc/mc-io.c
@@ -129,7 +129,12 @@ int __must_check fsl_create_mc_io(struct device *dev,
*/
void fsl_destroy_mc_io(struct fsl_mc_io *mc_io)
{
- struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
+ struct fsl_mc_device *dpmcp_dev;
+
+ if (!mc_io)
+ return;
+
+ dpmcp_dev = mc_io->dpmcp_dev;

if (dpmcp_dev)
fsl_mc_io_unset_dpmcp(mc_io);
diff --git a/include/linux/fsl/mc.h b/include/linux/fsl/mc.h
index e3ba273a1122..59b39c635ec9 100644
--- a/include/linux/fsl/mc.h
+++ b/include/linux/fsl/mc.h
@@ -480,6 +480,8 @@ int dprc_scan_container(struct fsl_mc_device *mc_bus_dev,
const char *driver_override,
bool alloc_interrupts);

+int dprc_setup(struct fsl_mc_device *mc_dev);
+
int dprc_cleanup(struct fsl_mc_device *mc_dev);

/*
--
2.17.1

2020-03-19 15:42:49

by Diana Madalina Craciun

[permalink] [raw]
Subject: [PATCH 03/10] bus/fsl-mc: add support for 'driver_override' in the mc-bus

From: Bharat Bhushan <[email protected]>

This patch is required for vfio-fsl-mc meta driver to successfully bind
layerscape container devices for device passthrough. This patch adds
a mechanism to allow a layerscape device to specify a driver rather than
a layerscape driver provide a device match.

Example to allow a device (dprc.1) to specifically bind
with driver (vfio-fsl-mc):-
- echo vfio-fsl-mc > /sys/bus/fsl-mc/devices/dprc.1/driver_override
- echo dprc.1 > /sys/bus/fsl-mc/drivers/fsl_mc_dprc/unbind
- echo dprc.1 > /sys/bus/fsl-mc/drivers/vfio-fsl-mc/bind

Signed-off-by: Bharat Bhushan <[email protected]>
Signed-off-by: Laurentiu Tudor <[email protected]>
Signed-off-by: Diana Craciun <[email protected]>
---
drivers/bus/fsl-mc/fsl-mc-bus.c | 54 +++++++++++++++++++++++++++++++++
include/linux/fsl/mc.h | 1 +
2 files changed, 55 insertions(+)

diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
index c78d10ea641f..baf8259262a9 100644
--- a/drivers/bus/fsl-mc/fsl-mc-bus.c
+++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
@@ -3,6 +3,7 @@
* Freescale Management Complex (MC) bus driver
*
* Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
+ * Copyright 2019-2020 NXP
* Author: German Rivera <[email protected]>
*
*/
@@ -83,6 +84,12 @@ static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv)
struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(drv);
bool found = false;

+ /* When driver_override is set, only bind to the matching driver */
+ if (mc_dev->driver_override) {
+ found = !strcmp(mc_dev->driver_override, mc_drv->driver.name);
+ goto out;
+ }
+
if (!mc_drv->match_id_table)
goto out;

@@ -147,8 +154,52 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR_RO(modalias);

+static ssize_t driver_override_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
+ const char *driver_override, *old = mc_dev->driver_override;
+ char *cp;
+
+ if (WARN_ON(dev->bus != &fsl_mc_bus_type))
+ return -EINVAL;
+
+ if (count >= (PAGE_SIZE - 1))
+ return -EINVAL;
+
+ driver_override = kstrndup(buf, count, GFP_KERNEL);
+ if (!driver_override)
+ return -ENOMEM;
+
+ cp = strchr(driver_override, '\n');
+ if (cp)
+ *cp = '\0';
+
+ if (strlen(driver_override)) {
+ mc_dev->driver_override = driver_override;
+ } else {
+ kfree(driver_override);
+ mc_dev->driver_override = NULL;
+ }
+
+ kfree(old);
+
+ return count;
+}
+
+static ssize_t driver_override_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", mc_dev->driver_override);
+}
+static DEVICE_ATTR_RW(driver_override);
+
static struct attribute *fsl_mc_dev_attrs[] = {
&dev_attr_modalias.attr,
+ &dev_attr_driver_override.attr,
NULL,
};

@@ -704,6 +755,9 @@ EXPORT_SYMBOL_GPL(fsl_mc_device_add);
*/
void fsl_mc_device_remove(struct fsl_mc_device *mc_dev)
{
+ kfree(mc_dev->driver_override);
+ mc_dev->driver_override = NULL;
+
/*
* The device-specific remove callback will get invoked by device_del()
*/
diff --git a/include/linux/fsl/mc.h b/include/linux/fsl/mc.h
index 54d9436600c7..88095fd30c80 100644
--- a/include/linux/fsl/mc.h
+++ b/include/linux/fsl/mc.h
@@ -194,6 +194,7 @@ struct fsl_mc_device {
struct fsl_mc_device_irq **irqs;
struct fsl_mc_resource *resource;
struct device_link *consumer_link;
+ const char *driver_override;
};

#define to_fsl_mc_device(_dev) \
--
2.17.1

2020-03-19 15:43:36

by Diana Madalina Craciun

[permalink] [raw]
Subject: [PATCH 02/10] bus/fsl-mc: Add a new parameter to dprc_scan_objects function

Prepare the dprc_scan_objects function to be used by
the VFIO mc driver code. The function is used to scan the mc
objects by the bus driver. The same functionality is
needed by the VFIO mc driver, but in this case the
interrupt configuration is delayed until the userspace
configures the interrupts. In order to use the same function
in both drivers add a new parameter.

Signed-off-by: Diana Craciun <[email protected]>
---
drivers/bus/fsl-mc/dprc-driver.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/bus/fsl-mc/dprc-driver.c b/drivers/bus/fsl-mc/dprc-driver.c
index 035b220779d0..d373b28abe2d 100644
--- a/drivers/bus/fsl-mc/dprc-driver.c
+++ b/drivers/bus/fsl-mc/dprc-driver.c
@@ -198,7 +198,9 @@ static void dprc_add_new_devices(struct fsl_mc_device *mc_bus_dev,
* dprc_scan_objects - Discover objects in a DPRC
*
* @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
- *
+ * @alloc_interrupts: if true the function allocates the interrupt pool,
+ * otherwise the interrupt allocation is delayed
+
* Detects objects added and removed from a DPRC and synchronizes the
* state of the Linux bus driver, MC by adding and removing
* devices accordingly.
@@ -211,7 +213,8 @@ static void dprc_add_new_devices(struct fsl_mc_device *mc_bus_dev,
* populated before they can get allocation requests from probe callbacks
* of the device drivers for the non-allocatable devices.
*/
-static int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev)
+static int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
+ bool alloc_interrupts)
{
int num_child_objects;
int dprc_get_obj_failures;
@@ -299,7 +302,7 @@ static int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev)
irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
}

- if (!mc_bus->irq_resources) {
+ if (alloc_interrupts && !mc_bus->irq_resources) {
error = fsl_mc_populate_irq_pool(mc_bus,
FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
if (error < 0)
@@ -339,7 +342,7 @@ static int dprc_scan_container(struct fsl_mc_device *mc_bus_dev)
* Discover objects in the DPRC:
*/
mutex_lock(&mc_bus->scan_mutex);
- error = dprc_scan_objects(mc_bus_dev);
+ error = dprc_scan_objects(mc_bus_dev, true);
mutex_unlock(&mc_bus->scan_mutex);
if (error < 0) {
fsl_mc_cleanup_all_resource_pools(mc_bus_dev);
@@ -409,7 +412,7 @@ static irqreturn_t dprc_irq0_handler_thread(int irq_num, void *arg)
DPRC_IRQ_EVENT_OBJ_DESTROYED |
DPRC_IRQ_EVENT_OBJ_CREATED)) {

- error = dprc_scan_objects(mc_dev);
+ error = dprc_scan_objects(mc_dev, true);
if (error < 0) {
/*
* If the error is -ENXIO, we ignore it, as it indicates
--
2.17.1

2020-03-23 12:06:58

by Laurentiu Tudor

[permalink] [raw]
Subject: Re: [PATCH 02/10] bus/fsl-mc: Add a new parameter to dprc_scan_objects function



On 3/19/2020 5:40 PM, Diana Craciun wrote:
> Prepare the dprc_scan_objects function to be used by
> the VFIO mc driver code. The function is used to scan the mc
> objects by the bus driver. The same functionality is
> needed by the VFIO mc driver, but in this case the
> interrupt configuration is delayed until the userspace
> configures the interrupts. In order to use the same function
> in both drivers add a new parameter.
>
> Signed-off-by: Diana Craciun <[email protected]>
> ---
> drivers/bus/fsl-mc/dprc-driver.c | 13 ++++++++-----
> 1 file changed, 8 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/bus/fsl-mc/dprc-driver.c b/drivers/bus/fsl-mc/dprc-driver.c
> index 035b220779d0..d373b28abe2d 100644
> --- a/drivers/bus/fsl-mc/dprc-driver.c
> +++ b/drivers/bus/fsl-mc/dprc-driver.c
> @@ -198,7 +198,9 @@ static void dprc_add_new_devices(struct fsl_mc_device *mc_bus_dev,
> * dprc_scan_objects - Discover objects in a DPRC
> *
> * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
> - *
> + * @alloc_interrupts: if true the function allocates the interrupt pool,
> + * otherwise the interrupt allocation is delayed
> +

nit: missing * here.

---
Best Regards, Laurentiu

> * Detects objects added and removed from a DPRC and synchronizes the
> * state of the Linux bus driver, MC by adding and removing
> * devices accordingly.
> @@ -211,7 +213,8 @@ static void dprc_add_new_devices(struct fsl_mc_device *mc_bus_dev,
> * populated before they can get allocation requests from probe callbacks
> * of the device drivers for the non-allocatable devices.
> */
> -static int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev)
> +static int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
> + bool alloc_interrupts)
> {
> int num_child_objects;
> int dprc_get_obj_failures;
> @@ -299,7 +302,7 @@ static int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev)
> irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
> }
>
> - if (!mc_bus->irq_resources) {
> + if (alloc_interrupts && !mc_bus->irq_resources) {
> error = fsl_mc_populate_irq_pool(mc_bus,
> FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
> if (error < 0)
> @@ -339,7 +342,7 @@ static int dprc_scan_container(struct fsl_mc_device *mc_bus_dev)
> * Discover objects in the DPRC:
> */
> mutex_lock(&mc_bus->scan_mutex);
> - error = dprc_scan_objects(mc_bus_dev);
> + error = dprc_scan_objects(mc_bus_dev, true);
> mutex_unlock(&mc_bus->scan_mutex);
> if (error < 0) {
> fsl_mc_cleanup_all_resource_pools(mc_bus_dev);
> @@ -409,7 +412,7 @@ static irqreturn_t dprc_irq0_handler_thread(int irq_num, void *arg)
> DPRC_IRQ_EVENT_OBJ_DESTROYED |
> DPRC_IRQ_EVENT_OBJ_CREATED)) {
>
> - error = dprc_scan_objects(mc_dev);
> + error = dprc_scan_objects(mc_dev, true);
> if (error < 0) {
> /*
> * If the error is -ENXIO, we ignore it, as it indicates
>

2020-03-23 12:31:33

by Laurentiu Tudor

[permalink] [raw]
Subject: Re: [PATCH 03/10] bus/fsl-mc: add support for 'driver_override' in the mc-bus



On 3/19/2020 5:40 PM, Diana Craciun wrote:
> From: Bharat Bhushan <[email protected]>
>
> This patch is required for vfio-fsl-mc meta driver to successfully bind
> layerscape container devices for device passthrough. This patch adds
> a mechanism to allow a layerscape device to specify a driver rather than
> a layerscape driver provide a device match.
>
> Example to allow a device (dprc.1) to specifically bind
> with driver (vfio-fsl-mc):-
> - echo vfio-fsl-mc > /sys/bus/fsl-mc/devices/dprc.1/driver_override
> - echo dprc.1 > /sys/bus/fsl-mc/drivers/fsl_mc_dprc/unbind
> - echo dprc.1 > /sys/bus/fsl-mc/drivers/vfio-fsl-mc/bind
>
> Signed-off-by: Bharat Bhushan <[email protected]>
> Signed-off-by: Laurentiu Tudor <[email protected]>
> Signed-off-by: Diana Craciun <[email protected]>
> ---
> drivers/bus/fsl-mc/fsl-mc-bus.c | 54 +++++++++++++++++++++++++++++++++
> include/linux/fsl/mc.h | 1 +
> 2 files changed, 55 insertions(+)
>
> diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
> index c78d10ea641f..baf8259262a9 100644
> --- a/drivers/bus/fsl-mc/fsl-mc-bus.c
> +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
> @@ -3,6 +3,7 @@
> * Freescale Management Complex (MC) bus driver
> *
> * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
> + * Copyright 2019-2020 NXP
> * Author: German Rivera <[email protected]>
> *
> */
> @@ -83,6 +84,12 @@ static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv)
> struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(drv);
> bool found = false;
>
> + /* When driver_override is set, only bind to the matching driver */
> + if (mc_dev->driver_override) {
> + found = !strcmp(mc_dev->driver_override, mc_drv->driver.name);

I think we can use sysfs_streq() here and ...


> + goto out;
> + }
> +
> if (!mc_drv->match_id_table)
> goto out;
>
> @@ -147,8 +154,52 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
> }
> static DEVICE_ATTR_RO(modalias);
>
> +static ssize_t driver_override_store(struct device *dev,
> + struct device_attribute *attr,
> + const char *buf, size_t count)
> +{
> + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
> + const char *driver_override, *old = mc_dev->driver_override;
> + char *cp;
> +
> + if (WARN_ON(dev->bus != &fsl_mc_bus_type))
> + return -EINVAL;
> +
> + if (count >= (PAGE_SIZE - 1))
> + return -EINVAL;
> +
> + driver_override = kstrndup(buf, count, GFP_KERNEL);
> + if (!driver_override)
> + return -ENOMEM;
> +
> + cp = strchr(driver_override, '\n');
> + if (cp)
> + *cp = '\0';

drop this strchr() ...

> + if (strlen(driver_override)) {
> + mc_dev->driver_override = driver_override;
> + } else {
> + kfree(driver_override);
> + mc_dev->driver_override = NULL;
> + }
> +
> + kfree(old);
> +
> + return count;
> +}
> +
> +static ssize_t driver_override_show(struct device *dev,
> + struct device_attribute *attr, char *buf)
> +{
> + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
> +
> + return snprintf(buf, PAGE_SIZE, "%s\n", mc_dev->driver_override);

and also the terminating '\n' here.

> +}
> +static DEVICE_ATTR_RW(driver_override);
> +
> static struct attribute *fsl_mc_dev_attrs[] = {
> &dev_attr_modalias.attr,
> + &dev_attr_driver_override.attr,
> NULL,
> };
>
> @@ -704,6 +755,9 @@ EXPORT_SYMBOL_GPL(fsl_mc_device_add);
> */
> void fsl_mc_device_remove(struct fsl_mc_device *mc_dev)
> {
> + kfree(mc_dev->driver_override);
> + mc_dev->driver_override = NULL;
> +
> /*
> * The device-specific remove callback will get invoked by device_del()
> */
> diff --git a/include/linux/fsl/mc.h b/include/linux/fsl/mc.h
> index 54d9436600c7..88095fd30c80 100644
> --- a/include/linux/fsl/mc.h
> +++ b/include/linux/fsl/mc.h
> @@ -194,6 +194,7 @@ struct fsl_mc_device {
> struct fsl_mc_device_irq **irqs;
> struct fsl_mc_resource *resource;
> struct device_link *consumer_link;
> + const char *driver_override;

We probably don't want const here.

---
Best Regards, Laurentiu

> };
>
> #define to_fsl_mc_device(_dev) \
>

2020-03-23 12:50:41

by Laurentiu Tudor

[permalink] [raw]
Subject: Re: [PATCH 07/10] bus/fsl-mc: Export a dprc scan function to be used by multiple entities



On 3/19/2020 5:40 PM, Diana Craciun wrote:
> Currently the DPRC scan function is used only by the bus driver.
> But the same functionality will be needed by the VFIO driver.
> To support this, the dprc scan function was exported and a little
> bit adjusted to fit both scenarios.
>
> Signed-off-by: Diana Craciun <[email protected]>
> ---
> drivers/bus/fsl-mc/dprc-driver.c | 15 ++++++---------
> drivers/bus/fsl-mc/fsl-mc-bus.c | 2 ++
> include/linux/fsl/mc.h | 4 ++++
> 3 files changed, 12 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/bus/fsl-mc/dprc-driver.c b/drivers/bus/fsl-mc/dprc-driver.c
> index 7eaf78900dfc..789220f0372a 100644
> --- a/drivers/bus/fsl-mc/dprc-driver.c
> +++ b/drivers/bus/fsl-mc/dprc-driver.c
> @@ -335,7 +335,9 @@ static int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
> * bus driver with the actual state of the MC by adding and removing
> * devices as appropriate.
> */
> -static int dprc_scan_container(struct fsl_mc_device *mc_bus_dev)
> +int dprc_scan_container(struct fsl_mc_device *mc_bus_dev,
> + const char *driver_override,
> + bool alloc_interrupts)
> {
> int error;
> struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
> @@ -346,15 +348,12 @@ static int dprc_scan_container(struct fsl_mc_device *mc_bus_dev)
> * Discover objects in the DPRC:
> */
> mutex_lock(&mc_bus->scan_mutex);
> - error = dprc_scan_objects(mc_bus_dev, NULL, true);
> + error = dprc_scan_objects(mc_bus_dev, driver_override, alloc_interrupts);
> mutex_unlock(&mc_bus->scan_mutex);
> - if (error < 0) {
> - fsl_mc_cleanup_all_resource_pools(mc_bus_dev);
> - return error;
> - }
>
> return 0;
> }
> +EXPORT_SYMBOL_GPL(dprc_scan_container);
>
> /**
> * dprc_irq0_handler - Regular ISR for DPRC interrupt 0
> @@ -679,12 +678,10 @@ static int dprc_probe(struct fsl_mc_device *mc_dev)
> goto error_cleanup_open;
> }
>
> - mutex_init(&mc_bus->scan_mutex);
> -

It's not obvious that this is related, maybe it should be mentioned in
the commit message.

> /*
> * Discover MC objects in DPRC object:
> */
> - error = dprc_scan_container(mc_dev);
> + error = dprc_scan_container(mc_dev, NULL, true);
> if (error < 0)
> goto error_cleanup_open;
>
> diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
> index a99a0edef252..1865221bb12d 100644
> --- a/drivers/bus/fsl-mc/fsl-mc-bus.c
> +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
> @@ -635,7 +635,9 @@ int fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc,
> if (!mc_bus)
> return -ENOMEM;
>
> + mutex_init(&mc_bus->scan_mutex);
> mc_dev = &mc_bus->mc_dev;
> +

nit: extra white space.

---
Best Regards, Laurentiu

> } else {
> /*
> * Allocate a regular fsl_mc_device object:
> diff --git a/include/linux/fsl/mc.h b/include/linux/fsl/mc.h
> index b9d5e5955adb..2bdd96a482fb 100644
> --- a/include/linux/fsl/mc.h
> +++ b/include/linux/fsl/mc.h
> @@ -476,6 +476,10 @@ int dprc_reset_container(struct fsl_mc_io *mc_io,
> u16 token,
> int child_container_id);
>
> +int dprc_scan_container(struct fsl_mc_device *mc_bus_dev,
> + const char *driver_override,
> + bool alloc_interrupts);
> +
> /*
> * Data Path Buffer Pool (DPBP) API
> * Contains initialization APIs and runtime control APIs for DPBP
>

2020-03-23 13:07:34

by Laurentiu Tudor

[permalink] [raw]
Subject: Re: [PATCH 09/10] bus/fsl-mc: Add a container setup function



On 3/19/2020 5:40 PM, Diana Craciun wrote:
> Both DPRC driver and VFIO driver use a initialization code
> for the DPRC. Introduced a new function which groups this
> initialization code. The function is exported and may be
> used by VFIO as well.
>
> Signed-off-by: Diana Craciun <[email protected]>
> ---
> drivers/bus/fsl-mc/dprc-driver.c | 77 +++++++++++++++++++++-----------
> drivers/bus/fsl-mc/mc-io.c | 7 ++-
> include/linux/fsl/mc.h | 2 +
> 3 files changed, 60 insertions(+), 26 deletions(-)
>
> diff --git a/drivers/bus/fsl-mc/dprc-driver.c b/drivers/bus/fsl-mc/dprc-driver.c
> index a655e3fee291..0fe45c301858 100644
> --- a/drivers/bus/fsl-mc/dprc-driver.c
> +++ b/drivers/bus/fsl-mc/dprc-driver.c
> @@ -570,16 +570,15 @@ static int dprc_setup_irq(struct fsl_mc_device *mc_dev)
> }
>
> /**
> - * dprc_probe - callback invoked when a DPRC is being bound to this driver
> + * dprc_setup - opens and creates a mc_io for DPRC
> *
> * @mc_dev: Pointer to fsl-mc device representing a DPRC
> *
> * It opens the physical DPRC in the MC.
> - * It scans the DPRC to discover the MC objects contained in it.
> - * It creates the interrupt pool for the MC bus associated with the DPRC.
> - * It configures the interrupts for the DPRC device itself.
> + * It configures the DPRC portal used to communicate with MC
> */
> -static int dprc_probe(struct fsl_mc_device *mc_dev)
> +
> +int dprc_setup(struct fsl_mc_device *mc_dev)
> {
> int error;
> size_t region_size;
> @@ -589,12 +588,6 @@ static int dprc_probe(struct fsl_mc_device *mc_dev)
> bool msi_domain_set = false;
> u16 major_ver, minor_ver;
>
> - if (!is_fsl_mc_bus_dprc(mc_dev))
> - return -EINVAL;
> -
> - if (dev_get_msi_domain(&mc_dev->dev))
> - return -EINVAL;
> -
> if (!mc_dev->mc_io) {
> /*
> * This is a child DPRC:
> @@ -678,35 +671,69 @@ static int dprc_probe(struct fsl_mc_device *mc_dev)
> goto error_cleanup_open;
> }
>
> + return 0;
> +
> +error_cleanup_open:
> + (void)dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
> +
> +error_cleanup_msi_domain:
> + if (msi_domain_set)
> + dev_set_msi_domain(&mc_dev->dev, NULL);
> +
> + if (mc_io_created) {
> + fsl_destroy_mc_io(mc_dev->mc_io);
> + mc_dev->mc_io = NULL;
> + }
> +
> + return error;
> +}
> +EXPORT_SYMBOL_GPL(dprc_setup);
> +
> +/**
> + * dprc_probe - callback invoked when a DPRC is being bound to this driver
> + *
> + * @mc_dev: Pointer to fsl-mc device representing a DPRC
> + *
> + * It opens the physical DPRC in the MC.
> + * It scans the DPRC to discover the MC objects contained in it.
> + * It creates the interrupt pool for the MC bus associated with the DPRC.
> + * It configures the interrupts for the DPRC device itself.
> + */
> +static int dprc_probe(struct fsl_mc_device *mc_dev)
> +{
> + int error;
> +
> + if (!is_fsl_mc_bus_dprc(mc_dev))
> + return -EINVAL;
> +
> + if (dev_get_msi_domain(&mc_dev->dev))
> + return -EINVAL;
> +
> + error = dprc_setup(mc_dev);
> + if (error < 0)
> + return error;
> +
> /*
> * Discover MC objects in DPRC object:
> */
> error = dprc_scan_container(mc_dev, NULL, true);
> if (error < 0)
> - goto error_cleanup_open;
> + goto dprc_cleanup;
>
> /*
> * Configure interrupt for the DPRC object associated with this MC bus:
> */
> error = dprc_setup_irq(mc_dev);
> if (error < 0)
> - goto error_cleanup_open;
> + goto scan_cleanup;
>
> dev_info(&mc_dev->dev, "DPRC device bound to driver");
> return 0;
>
> -error_cleanup_open:
> - (void)dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
> -
> -error_cleanup_msi_domain:
> - if (msi_domain_set)
> - dev_set_msi_domain(&mc_dev->dev, NULL);
> -
> - if (mc_io_created) {
> - fsl_destroy_mc_io(mc_dev->mc_io);
> - mc_dev->mc_io = NULL;
> - }
> -
> +scan_cleanup:
> + device_for_each_child(&mc_dev->dev, NULL, __fsl_mc_device_remove);
> +dprc_cleanup:
> + dprc_cleanup(mc_dev);
> return error;
> }
>
> diff --git a/drivers/bus/fsl-mc/mc-io.c b/drivers/bus/fsl-mc/mc-io.c
> index 6ae48ad80409..e1dfe4a76519 100644
> --- a/drivers/bus/fsl-mc/mc-io.c
> +++ b/drivers/bus/fsl-mc/mc-io.c
> @@ -129,7 +129,12 @@ int __must_check fsl_create_mc_io(struct device *dev,
> */
> void fsl_destroy_mc_io(struct fsl_mc_io *mc_io)
> {
> - struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
> + struct fsl_mc_device *dpmcp_dev;
> +
> + if (!mc_io)
> + return;
> +
> + dpmcp_dev = mc_io->dpmcp_dev;

Is this change related to the patch?

---
Best Regards, Laurentiu

> if (dpmcp_dev)
> fsl_mc_io_unset_dpmcp(mc_io);
> diff --git a/include/linux/fsl/mc.h b/include/linux/fsl/mc.h
> index e3ba273a1122..59b39c635ec9 100644
> --- a/include/linux/fsl/mc.h
> +++ b/include/linux/fsl/mc.h
> @@ -480,6 +480,8 @@ int dprc_scan_container(struct fsl_mc_device *mc_bus_dev,
> const char *driver_override,
> bool alloc_interrupts);
>
> +int dprc_setup(struct fsl_mc_device *mc_dev);
> +
> int dprc_cleanup(struct fsl_mc_device *mc_dev);
>
> /*
>

2020-04-09 11:16:00

by Diana Madalina Craciun

[permalink] [raw]
Subject: Re: [PATCH 03/10] bus/fsl-mc: add support for 'driver_override' in the mc-bus

On 3/23/2020 2:30 PM, Laurentiu Tudor wrote:
>
> On 3/19/2020 5:40 PM, Diana Craciun wrote:
>> From: Bharat Bhushan <[email protected]>
>>
>> This patch is required for vfio-fsl-mc meta driver to successfully bind
>> layerscape container devices for device passthrough. This patch adds
>> a mechanism to allow a layerscape device to specify a driver rather than
>> a layerscape driver provide a device match.
>>
>> Example to allow a device (dprc.1) to specifically bind
>> with driver (vfio-fsl-mc):-
>> - echo vfio-fsl-mc > /sys/bus/fsl-mc/devices/dprc.1/driver_override
>> - echo dprc.1 > /sys/bus/fsl-mc/drivers/fsl_mc_dprc/unbind
>> - echo dprc.1 > /sys/bus/fsl-mc/drivers/vfio-fsl-mc/bind
>>
>> Signed-off-by: Bharat Bhushan <[email protected]>
>> Signed-off-by: Laurentiu Tudor <[email protected]>
>> Signed-off-by: Diana Craciun <[email protected]>
>> ---
>> drivers/bus/fsl-mc/fsl-mc-bus.c | 54 +++++++++++++++++++++++++++++++++
>> include/linux/fsl/mc.h | 1 +
>> 2 files changed, 55 insertions(+)
>>
>> diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
>> index c78d10ea641f..baf8259262a9 100644
>> --- a/drivers/bus/fsl-mc/fsl-mc-bus.c
>> +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
>> @@ -3,6 +3,7 @@
>> * Freescale Management Complex (MC) bus driver
>> *
>> * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
>> + * Copyright 2019-2020 NXP
>> * Author: German Rivera <[email protected]>
>> *
>> */
>> @@ -83,6 +84,12 @@ static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv)
>> struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(drv);
>> bool found = false;
>>
>> + /* When driver_override is set, only bind to the matching driver */
>> + if (mc_dev->driver_override) {
>> + found = !strcmp(mc_dev->driver_override, mc_drv->driver.name);
> I think we can use sysfs_streq() here and ...

I would prefer to maintain consistency with other buses and store the
driver_override string without the terminating newline.

>
>
>> + goto out;
>> + }
>> +
>> if (!mc_drv->match_id_table)
>> goto out;
>>
>> @@ -147,8 +154,52 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
>> }
>> static DEVICE_ATTR_RO(modalias);
>>
>> +static ssize_t driver_override_store(struct device *dev,
>> + struct device_attribute *attr,
>> + const char *buf, size_t count)
>> +{
>> + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
>> + const char *driver_override, *old = mc_dev->driver_override;
>> + char *cp;
>> +
>> + if (WARN_ON(dev->bus != &fsl_mc_bus_type))
>> + return -EINVAL;
>> +
>> + if (count >= (PAGE_SIZE - 1))
>> + return -EINVAL;
>> +
>> + driver_override = kstrndup(buf, count, GFP_KERNEL);
>> + if (!driver_override)
>> + return -ENOMEM;
>> +
>> + cp = strchr(driver_override, '\n');
>> + if (cp)
>> + *cp = '\0';
> drop this strchr() ...
>
>> + if (strlen(driver_override)) {
>> + mc_dev->driver_override = driver_override;
>> + } else {
>> + kfree(driver_override);
>> + mc_dev->driver_override = NULL;
>> + }
>> +
>> + kfree(old);
>> +
>> + return count;
>> +}
>> +
>> +static ssize_t driver_override_show(struct device *dev,
>> + struct device_attribute *attr, char *buf)
>> +{
>> + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
>> +
>> + return snprintf(buf, PAGE_SIZE, "%s\n", mc_dev->driver_override);
> and also the terminating '\n' here.
>
>> +}
>> +static DEVICE_ATTR_RW(driver_override);
>> +
>> static struct attribute *fsl_mc_dev_attrs[] = {
>> &dev_attr_modalias.attr,
>> + &dev_attr_driver_override.attr,
>> NULL,
>> };
>>
>> @@ -704,6 +755,9 @@ EXPORT_SYMBOL_GPL(fsl_mc_device_add);
>> */
>> void fsl_mc_device_remove(struct fsl_mc_device *mc_dev)
>> {
>> + kfree(mc_dev->driver_override);
>> + mc_dev->driver_override = NULL;
>> +
>> /*
>> * The device-specific remove callback will get invoked by device_del()
>> */
>> diff --git a/include/linux/fsl/mc.h b/include/linux/fsl/mc.h
>> index 54d9436600c7..88095fd30c80 100644
>> --- a/include/linux/fsl/mc.h
>> +++ b/include/linux/fsl/mc.h
>> @@ -194,6 +194,7 @@ struct fsl_mc_device {
>> struct fsl_mc_device_irq **irqs;
>> struct fsl_mc_resource *resource;
>> struct device_link *consumer_link;
>> + const char *driver_override;
> We probably don't want const here.

OK

>
> ---
> Best Regards, Laurentiu
>
>> };
>>
>> #define to_fsl_mc_device(_dev) \
>>

Diana