[PATCH v2 4/7] staging: fsl-mc: Upgraded MC bus driver to match MC fw 7.0.0
From: J. German Rivera
Date: Wed May 06 2015 - 17:37:29 EST
- Migrated MC bus driver to use DPRC API 0.6.
- Changed IRQ setup infrastructure to be able to program MSIs
for MC objects in an object-independent way.
Signed-off-by: J. German Rivera <German.Rivera@xxxxxxxxxxxxx>
---
Changes in v2:
- Addressed comments from Dan Carpenter:
* Added #ifdef GIC_ITS_MC_SUPPORT's that had been removed
by mistake.
* Removed EXPORTs that are not used by other MC object drivers
yet.
* Removed unused function dprc_lookup_object()
drivers/staging/fsl-mc/bus/dpmcp-cmd.h | 79 --------------
drivers/staging/fsl-mc/bus/dprc-cmd.h | 6 +-
drivers/staging/fsl-mc/bus/dprc-driver.c | 37 +++++--
drivers/staging/fsl-mc/bus/dprc.c | 155 ++++++++++++++++++++++------
drivers/staging/fsl-mc/bus/mc-allocator.c | 26 +++--
drivers/staging/fsl-mc/bus/mc-bus.c | 77 +++++++++-----
drivers/staging/fsl-mc/bus/mc-sys.c | 6 +-
drivers/staging/fsl-mc/include/dpmng.h | 4 +-
drivers/staging/fsl-mc/include/dprc.h | 114 +++++++++++++++-----
drivers/staging/fsl-mc/include/mc-private.h | 29 +++++-
drivers/staging/fsl-mc/include/mc.h | 4 +
11 files changed, 345 insertions(+), 192 deletions(-)
diff --git a/drivers/staging/fsl-mc/bus/dpmcp-cmd.h b/drivers/staging/fsl-mc/bus/dpmcp-cmd.h
index 57f326b..62bdc18 100644
--- a/drivers/staging/fsl-mc/bus/dpmcp-cmd.h
+++ b/drivers/staging/fsl-mc/bus/dpmcp-cmd.h
@@ -54,83 +54,4 @@
#define DPMCP_CMDID_GET_IRQ_STATUS 0x016
#define DPMCP_CMDID_CLEAR_IRQ_STATUS 0x017
-/* cmd, param, offset, width, type, arg_name */
-#define DPMCP_CMD_CREATE(cmd, cfg) \
- MC_CMD_OP(cmd, 0, 0, 32, int, cfg->portal_id)
-
-/* cmd, param, offset, width, type, arg_name */
-#define DPMCP_CMD_SET_IRQ(cmd, irq_index, irq_addr, irq_val, user_irq_id) \
-do { \
- MC_CMD_OP(cmd, 0, 0, 8, uint8_t, irq_index);\
- MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_val);\
- MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_addr); \
- MC_CMD_OP(cmd, 2, 0, 32, int, user_irq_id); \
-} while (0)
-
-/* cmd, param, offset, width, type, arg_name */
-#define DPMCP_CMD_GET_IRQ(cmd, irq_index) \
- MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index)
-
-/* cmd, param, offset, width, type, arg_name */
-#define DPMCP_RSP_GET_IRQ(cmd, type, irq_addr, irq_val, user_irq_id) \
-do { \
- MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_val); \
- MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_addr); \
- MC_RSP_OP(cmd, 2, 0, 32, int, user_irq_id); \
- MC_RSP_OP(cmd, 2, 32, 32, int, type); \
-} while (0)
-
-/* cmd, param, offset, width, type, arg_name */
-#define DPMCP_CMD_SET_IRQ_ENABLE(cmd, irq_index, en) \
-do { \
- MC_CMD_OP(cmd, 0, 0, 8, uint8_t, en); \
- MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\
-} while (0)
-
-/* cmd, param, offset, width, type, arg_name */
-#define DPMCP_CMD_GET_IRQ_ENABLE(cmd, irq_index) \
- MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index)
-
-/* cmd, param, offset, width, type, arg_name */
-#define DPMCP_RSP_GET_IRQ_ENABLE(cmd, en) \
- MC_RSP_OP(cmd, 0, 0, 8, uint8_t, en)
-
-/* cmd, param, offset, width, type, arg_name */
-#define DPMCP_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \
-do { \
- MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask);\
- MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\
-} while (0)
-
-/* cmd, param, offset, width, type, arg_name */
-#define DPMCP_CMD_GET_IRQ_MASK(cmd, irq_index) \
- MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index)
-
-/* cmd, param, offset, width, type, arg_name */
-#define DPMCP_RSP_GET_IRQ_MASK(cmd, mask) \
- MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask)
-
-/* cmd, param, offset, width, type, arg_name */
-#define DPMCP_CMD_GET_IRQ_STATUS(cmd, irq_index) \
- MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index)
-
-/* cmd, param, offset, width, type, arg_name */
-#define DPMCP_RSP_GET_IRQ_STATUS(cmd, status) \
- MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status)
-
-/* cmd, param, offset, width, type, arg_name */
-#define DPMCP_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \
-do { \
- MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \
- MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\
-} while (0)
-
-/* cmd, param, offset, width, type, arg_name */
-#define DPMCP_RSP_GET_ATTRIBUTES(cmd, attr) \
-do { \
- MC_RSP_OP(cmd, 0, 32, 32, int, attr->id);\
- MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->version.major);\
- MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->version.minor);\
-} while (0)
-
#endif /* _FSL_DPMCP_CMD_H */
diff --git a/drivers/staging/fsl-mc/bus/dprc-cmd.h b/drivers/staging/fsl-mc/bus/dprc-cmd.h
index 0920248..df5ad5f 100644
--- a/drivers/staging/fsl-mc/bus/dprc-cmd.h
+++ b/drivers/staging/fsl-mc/bus/dprc-cmd.h
@@ -41,7 +41,7 @@
#define _FSL_DPRC_CMD_H
/* DPRC Version */
-#define DPRC_VER_MAJOR 3
+#define DPRC_VER_MAJOR 4
#define DPRC_VER_MINOR 0
/* Command IDs */
@@ -72,12 +72,14 @@
#define DPRC_CMDID_GET_RES_COUNT 0x15B
#define DPRC_CMDID_GET_RES_IDS 0x15C
#define DPRC_CMDID_GET_OBJ_REG 0x15E
+#define DPRC_CMDID_OBJ_SET_IRQ 0x15F
+#define DPRC_CMDID_OBJ_GET_IRQ 0x160
+#define DPRC_CMDID_SET_OBJ_LABEL 0x161
#define DPRC_CMDID_CONNECT 0x167
#define DPRC_CMDID_DISCONNECT 0x168
#define DPRC_CMDID_GET_POOL 0x169
#define DPRC_CMDID_GET_POOL_COUNT 0x16A
-#define DPRC_CMDID_GET_PORTAL_PADDR 0x16B
#define DPRC_CMDID_GET_CONNECTION 0x16C
diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c
index 85e293b..338fd7d 100644
--- a/drivers/staging/fsl-mc/bus/dprc-driver.c
+++ b/drivers/staging/fsl-mc/bus/dprc-driver.c
@@ -500,6 +500,21 @@ static int register_dprc_irq_handlers(struct fsl_mc_device *mc_dev)
for (i = 0; i < ARRAY_SIZE(irq_handlers); i++) {
irq = mc_dev->irqs[i];
+
+ if (WARN_ON(irq->dev_irq_index != i)) {
+ error = -EINVAL;
+ goto error_unregister_irq_handlers;
+ }
+
+ /*
+ * NOTE: Normally, devm_request_threaded_irq() programs the MSI
+ * physically in the device (by invoking a device-specific
+ * callback). However, for MC IRQs, we have to program the MSI
+ * outside of this callback in an object-specific way, because
+ * the object-independent way of programming MSI is not reliable
+ * yet. For now, the MC callback just sets the msi_paddr and
+ * msi_value fields of the irq structure.
+ */
error = devm_request_threaded_irq(&mc_dev->dev,
irq->irq_number,
irq_handlers[i].irq_handler,
@@ -518,18 +533,17 @@ static int register_dprc_irq_handlers(struct fsl_mc_device *mc_dev)
/*
* Program the MSI (paddr, value) pair in the device:
- *
- * TODO: This needs to be moved to mc_bus_msi_domain_write_msg()
- * when the MC object-independent dprc_set_irq() flib API
- * becomes available
*/
- error = dprc_set_irq(mc_dev->mc_io, mc_dev->mc_handle,
- i, irq->msi_paddr,
+ error = dprc_set_irq(mc_dev->mc_io,
+ mc_dev->mc_handle,
+ i,
+ irq->msi_paddr,
irq->msi_value,
irq->irq_number);
if (error < 0) {
dev_err(&mc_dev->dev,
- "mc_set_irq() failed: %d\n", error);
+ "dprc_set_irq() failed for IRQ %u: %d\n",
+ i, error);
return error;
}
}
@@ -663,15 +677,16 @@ static int dprc_probe(struct fsl_mc_device *mc_dev)
*/
error = dprc_setup_irqs(mc_dev);
if (error < 0)
- goto error_cleanup_open;
+ goto error_cleanup_dprc_scan;
dev_info(&mc_dev->dev, "DPRC device bound to driver");
return 0;
-error_cleanup_open:
- if (mc_bus->irq_resources)
- fsl_mc_cleanup_irq_pool(mc_bus);
+error_cleanup_dprc_scan:
+ device_for_each_child(&mc_dev->dev, NULL, __fsl_mc_device_remove);
+ fsl_mc_cleanup_irq_pool(mc_bus);
+error_cleanup_open:
(void)dprc_close(mc_dev->mc_io, mc_dev->mc_handle);
error_cleanup_mc_io:
diff --git a/drivers/staging/fsl-mc/bus/dprc.c b/drivers/staging/fsl-mc/bus/dprc.c
index 19b26e6..62087cc 100644
--- a/drivers/staging/fsl-mc/bus/dprc.c
+++ b/drivers/staging/fsl-mc/bus/dprc.c
@@ -73,7 +73,7 @@ int dprc_create_container(struct fsl_mc_io *mc_io,
uint16_t token,
struct dprc_cfg *cfg,
int *child_container_id,
- uint64_t *child_portal_paddr)
+ uint64_t *child_portal_offset)
{
struct mc_command cmd = { 0 };
int err;
@@ -82,6 +82,22 @@ int dprc_create_container(struct fsl_mc_io *mc_io,
cmd.params[0] |= mc_enc(32, 16, cfg->icid);
cmd.params[0] |= mc_enc(0, 32, cfg->options);
cmd.params[1] |= mc_enc(32, 32, cfg->portal_id);
+ cmd.params[2] |= mc_enc(0, 8, cfg->label[0]);
+ cmd.params[2] |= mc_enc(8, 8, cfg->label[1]);
+ cmd.params[2] |= mc_enc(16, 8, cfg->label[2]);
+ cmd.params[2] |= mc_enc(24, 8, cfg->label[3]);
+ cmd.params[2] |= mc_enc(32, 8, cfg->label[4]);
+ cmd.params[2] |= mc_enc(40, 8, cfg->label[5]);
+ cmd.params[2] |= mc_enc(48, 8, cfg->label[6]);
+ cmd.params[2] |= mc_enc(56, 8, cfg->label[7]);
+ cmd.params[3] |= mc_enc(0, 8, cfg->label[8]);
+ cmd.params[3] |= mc_enc(8, 8, cfg->label[9]);
+ cmd.params[3] |= mc_enc(16, 8, cfg->label[10]);
+ cmd.params[3] |= mc_enc(24, 8, cfg->label[11]);
+ cmd.params[3] |= mc_enc(32, 8, cfg->label[12]);
+ cmd.params[3] |= mc_enc(40, 8, cfg->label[13]);
+ cmd.params[3] |= mc_enc(48, 8, cfg->label[14]);
+ cmd.params[3] |= mc_enc(56, 8, cfg->label[15]);
cmd.header = mc_encode_cmd_header(DPRC_CMDID_CREATE_CONT,
MC_CMD_PRI_LOW, token);
@@ -93,7 +109,7 @@ int dprc_create_container(struct fsl_mc_io *mc_io,
/* retrieve response parameters */
*child_container_id = mc_dec(cmd.params[1], 0, 32);
- *child_portal_paddr = mc_dec(cmd.params[2], 0, 64);
+ *child_portal_offset = mc_dec(cmd.params[2], 0, 64);
return 0;
}
@@ -159,6 +175,39 @@ int dprc_get_irq(struct fsl_mc_io *mc_io,
return 0;
}
+int dprc_obj_get_irq(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ int obj_index,
+ uint8_t irq_index,
+ int *type,
+ uint64_t *irq_addr,
+ uint32_t *irq_val,
+ int *user_irq_id)
+{
+ struct mc_command cmd = { 0 };
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_OBJ_GET_IRQ,
+ MC_CMD_PRI_LOW,
+ token);
+
+ cmd.params[0] |= mc_enc(0, 32, obj_index);
+ cmd.params[0] |= mc_enc(32, 8, irq_index);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ *irq_val = mc_dec(cmd.params[0], 0, 32);
+ *irq_addr = mc_dec(cmd.params[1], 0, 64);
+ *user_irq_id = mc_dec(cmd.params[2], 0, 32);
+ *type = mc_dec(cmd.params[2], 32, 32);
+ return 0;
+}
+
int dprc_set_irq(struct fsl_mc_io *mc_io,
uint16_t token,
uint8_t irq_index,
@@ -181,6 +230,31 @@ int dprc_set_irq(struct fsl_mc_io *mc_io,
return mc_send_command(mc_io, &cmd);
}
+int dprc_obj_set_irq(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ int obj_index,
+ uint8_t irq_index,
+ uint64_t irq_addr,
+ uint32_t irq_val,
+ int user_irq_id)
+{
+ struct mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_OBJ_SET_IRQ,
+ MC_CMD_PRI_LOW,
+ token);
+
+ cmd.params[0] |= mc_enc(32, 8, irq_index);
+ cmd.params[0] |= mc_enc(0, 32, irq_val);
+ cmd.params[1] |= mc_enc(0, 64, irq_addr);
+ cmd.params[2] |= mc_enc(0, 32, user_irq_id);
+ cmd.params[2] |= mc_enc(32, 32, obj_index);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
int dprc_get_irq_enable(struct fsl_mc_io *mc_io,
uint16_t token,
uint8_t irq_index,
@@ -604,7 +678,22 @@ int dprc_get_obj(struct fsl_mc_io *mc_io,
obj_desc->type[13] = mc_dec(cmd.params[4], 40, 8);
obj_desc->type[14] = mc_dec(cmd.params[4], 48, 8);
obj_desc->type[15] = '\0';
-
+ obj_desc->label[0] = mc_dec(cmd.params[5], 0, 8);
+ obj_desc->label[1] = mc_dec(cmd.params[5], 8, 8);
+ obj_desc->label[2] = mc_dec(cmd.params[5], 16, 8);
+ obj_desc->label[3] = mc_dec(cmd.params[5], 24, 8);
+ obj_desc->label[4] = mc_dec(cmd.params[5], 32, 8);
+ obj_desc->label[5] = mc_dec(cmd.params[5], 40, 8);
+ obj_desc->label[6] = mc_dec(cmd.params[5], 48, 8);
+ obj_desc->label[7] = mc_dec(cmd.params[5], 56, 8);
+ obj_desc->label[8] = mc_dec(cmd.params[6], 0, 8);
+ obj_desc->label[9] = mc_dec(cmd.params[6], 8, 8);
+ obj_desc->label[10] = mc_dec(cmd.params[6], 16, 8);
+ obj_desc->label[11] = mc_dec(cmd.params[6], 24, 8);
+ obj_desc->label[12] = mc_dec(cmd.params[6], 32, 8);
+ obj_desc->label[13] = mc_dec(cmd.params[6], 40, 8);
+ obj_desc->label[14] = mc_dec(cmd.params[6], 48, 8);
+ obj_desc->label[15] = '\0';
return 0;
}
EXPORT_SYMBOL(dprc_get_obj);
@@ -696,31 +785,6 @@ int dprc_get_res_ids(struct fsl_mc_io *mc_io,
}
EXPORT_SYMBOL(dprc_get_res_ids);
-int dprc_get_portal_paddr(struct fsl_mc_io *mc_io,
- uint16_t token,
- int portal_id,
- uint64_t *portal_addr)
-{
- struct mc_command cmd = { 0 };
- int err;
-
- /* prepare command */
- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_PORTAL_PADDR,
- MC_CMD_PRI_LOW, token);
- cmd.params[0] |= mc_enc(0, 32, portal_id);
-
- /* send command to mc*/
- err = mc_send_command(mc_io, &cmd);
- if (err)
- return err;
-
- /* retrieve response parameters */
- *portal_addr = mc_dec(cmd.params[1], 0, 64);
-
- return 0;
-}
-EXPORT_SYMBOL(dprc_get_portal_paddr);
-
int dprc_get_obj_region(struct fsl_mc_io *mc_io,
uint16_t token,
char *obj_type,
@@ -759,13 +823,46 @@ int dprc_get_obj_region(struct fsl_mc_io *mc_io,
return err;
/* retrieve response parameters */
- region_desc->base_paddr = mc_dec(cmd.params[1], 0, 64);
+ region_desc->base_offset = mc_dec(cmd.params[1], 0, 64);
region_desc->size = mc_dec(cmd.params[2], 0, 32);
return 0;
}
EXPORT_SYMBOL(dprc_get_obj_region);
+int dprc_set_obj_label(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ int obj_index,
+ char *label)
+{
+ struct mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_OBJ_LABEL,
+ MC_CMD_PRI_LOW, token);
+
+ cmd.params[0] |= mc_enc(0, 32, obj_index);
+ cmd.params[1] |= mc_enc(0, 8, label[0]);
+ cmd.params[1] |= mc_enc(8, 8, label[1]);
+ cmd.params[1] |= mc_enc(16, 8, label[2]);
+ cmd.params[1] |= mc_enc(24, 8, label[3]);
+ cmd.params[1] |= mc_enc(32, 8, label[4]);
+ cmd.params[1] |= mc_enc(40, 8, label[5]);
+ cmd.params[1] |= mc_enc(48, 8, label[6]);
+ cmd.params[1] |= mc_enc(56, 8, label[7]);
+ cmd.params[2] |= mc_enc(0, 8, label[8]);
+ cmd.params[2] |= mc_enc(8, 8, label[9]);
+ cmd.params[2] |= mc_enc(16, 8, label[10]);
+ cmd.params[2] |= mc_enc(24, 8, label[11]);
+ cmd.params[2] |= mc_enc(32, 8, label[12]);
+ cmd.params[2] |= mc_enc(40, 8, label[13]);
+ cmd.params[2] |= mc_enc(48, 8, label[14]);
+ cmd.params[2] |= mc_enc(56, 8, label[15]);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
int dprc_connect(struct fsl_mc_io *mc_io,
uint16_t token,
const struct dprc_endpoint *endpoint1,
diff --git a/drivers/staging/fsl-mc/bus/mc-allocator.c b/drivers/staging/fsl-mc/bus/mc-allocator.c
index aa8280a..e445f79 100644
--- a/drivers/staging/fsl-mc/bus/mc-allocator.c
+++ b/drivers/staging/fsl-mc/bus/mc-allocator.c
@@ -523,14 +523,20 @@ int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev)
irqs[i] = to_fsl_mc_irq(resource);
res_allocated_count++;
+
+ WARN_ON(irqs[i]->mc_dev);
+ irqs[i]->mc_dev = mc_dev;
+ irqs[i]->dev_irq_index = i;
}
mc_dev->irqs = irqs;
return 0;
error_resource_alloc:
- for (i = 0; i < res_allocated_count; i++)
+ for (i = 0; i < res_allocated_count; i++) {
+ irqs[i]->mc_dev = NULL;
fsl_mc_resource_free(&irqs[i]->resource);
+ }
return error;
}
@@ -545,8 +551,9 @@ void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev)
int i;
int irq_count;
struct fsl_mc_bus *mc_bus;
+ struct fsl_mc_device_irq **irqs = mc_dev->irqs;
- if (WARN_ON(!mc_dev->irqs))
+ if (WARN_ON(!irqs))
return;
irq_count = mc_dev->obj_desc.irq_count;
@@ -559,8 +566,11 @@ void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev)
if (WARN_ON(!mc_bus->irq_resources))
return;
- for (i = 0; i < irq_count; i++)
- fsl_mc_resource_free(&mc_dev->irqs[i]->resource);
+ for (i = 0; i < irq_count; i++) {
+ WARN_ON(!irqs[i]->mc_dev);
+ irqs[i]->mc_dev = NULL;
+ fsl_mc_resource_free(&irqs[i]->resource);
+ }
mc_dev->irqs = NULL;
}
@@ -593,8 +603,8 @@ static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev)
if (error < 0)
goto error;
- dev_info(&mc_dev->dev,
- "Allocatable MC object device bound to fsl_mc_allocator driver");
+ dev_dbg(&mc_dev->dev,
+ "Allocatable MC object device bound to fsl_mc_allocator driver");
return 0;
error:
@@ -616,8 +626,8 @@ static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev)
if (error < 0)
goto out;
- dev_info(&mc_dev->dev,
- "Allocatable MC object device unbound from fsl_mc_allocator driver");
+ dev_dbg(&mc_dev->dev,
+ "Allocatable MC object device unbound from fsl_mc_allocator driver");
error = 0;
out:
return error;
diff --git a/drivers/staging/fsl-mc/bus/mc-bus.c b/drivers/staging/fsl-mc/bus/mc-bus.c
index 83eb906..b82fd7b 100644
--- a/drivers/staging/fsl-mc/bus/mc-bus.c
+++ b/drivers/staging/fsl-mc/bus/mc-bus.c
@@ -315,7 +315,8 @@ common_cleanup:
return error;
}
-static int translate_mc_addr(uint64_t mc_addr, phys_addr_t *phys_addr)
+static int translate_mc_addr(enum fsl_mc_region_types mc_region_type,
+ uint64_t mc_offset, phys_addr_t *phys_addr)
{
int i;
struct fsl_mc *mc = dev_get_drvdata(fsl_mc_bus_type.dev_root->parent);
@@ -324,7 +325,7 @@ static int translate_mc_addr(uint64_t mc_addr, phys_addr_t *phys_addr)
/*
* Do identity mapping:
*/
- *phys_addr = mc_addr;
+ *phys_addr = mc_offset;
return 0;
}
@@ -332,10 +333,11 @@ static int translate_mc_addr(uint64_t mc_addr, phys_addr_t *phys_addr)
struct fsl_mc_addr_translation_range *range =
&mc->translation_ranges[i];
- if (mc_addr >= range->start_mc_addr &&
- mc_addr < range->end_mc_addr) {
+ if (mc_region_type == range->mc_region_type &&
+ mc_offset >= range->start_mc_offset &&
+ mc_offset < range->end_mc_offset) {
*phys_addr = range->start_phys_addr +
- (mc_addr - range->start_mc_addr);
+ (mc_offset - range->start_mc_offset);
return 0;
}
}
@@ -351,6 +353,22 @@ static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev,
struct resource *regions;
struct dprc_obj_desc *obj_desc = &mc_dev->obj_desc;
struct device *parent_dev = mc_dev->dev.parent;
+ enum fsl_mc_region_types mc_region_type;
+
+ if (strcmp(obj_desc->type, "dprc") == 0 ||
+ strcmp(obj_desc->type, "dpmcp") == 0) {
+ mc_region_type = FSL_MC_PORTAL;
+ } else if (strcmp(obj_desc->type, "dpio") == 0) {
+ mc_region_type = FSL_QBMAN_PORTAL;
+ } else {
+ /*
+ * This function should not have been called for this MC object
+ * type, as this object type is not supposed to have MMIO
+ * regions
+ */
+ WARN_ON(true);
+ return -EINVAL;
+ }
regions = kmalloc_array(obj_desc->region_count,
sizeof(regions[0]), GFP_KERNEL);
@@ -370,14 +388,14 @@ static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev,
goto error_cleanup_regions;
}
- WARN_ON(region_desc.base_paddr == 0x0);
WARN_ON(region_desc.size == 0);
- error = translate_mc_addr(region_desc.base_paddr,
+ error = translate_mc_addr(mc_region_type,
+ region_desc.base_offset,
®ions[i].start);
if (error < 0) {
dev_err(parent_dev,
- "Invalid MC address: %#llx (for %s.%d\'s region %d)\n",
- region_desc.base_paddr,
+ "Invalid MC offset: %#llx (for %s.%d\'s region %d)\n",
+ region_desc.base_offset,
obj_desc->type, obj_desc->id, i);
goto error_cleanup_regions;
}
@@ -641,6 +659,10 @@ static void mc_bus_unmask_msi_irq(struct irq_data *d)
irq_chip_unmask_parent(d);
}
+/*
+ * This function is invoked from devm_request_irq(),
+ * devm_request_threaded_irq(), dev_free_irq()
+ */
static void mc_bus_msi_domain_write_msg(struct irq_data *irq_data,
struct msi_msg *msg)
{
@@ -657,6 +679,13 @@ static void mc_bus_msi_domain_write_msg(struct irq_data *irq_data,
irq_res->msi_paddr =
((u64)msg->address_hi << 32) | msg->address_lo;
irq_res->msi_value = msg->data;
+
+ /*
+ * NOTE: We cannot do the actual programming of the MSI
+ * in the MC, in this function, as the object-independent
+ * way of programming MSIs for MC objects is not reliable
+ * if objects are being added/removed dynamically.
+ */
}
}
@@ -706,10 +735,6 @@ static int create_mc_irq_domain(struct platform_device *mc_pdev,
goto cleanup_its_of_node;
}
- /*
- * FIXME: Enable this code when the GIC-ITS MC support patch is merged
- */
-#ifdef GIC_ITS_MC_SUPPORT
irq_domain = msi_create_irq_domain(mc_of_node, &mc_bus_msi_domain_info,
its_domain->parent);
if (!irq_domain) {
@@ -719,9 +744,6 @@ static int create_mc_irq_domain(struct platform_device *mc_pdev,
}
dev_dbg(&mc_pdev->dev, "Allocated MSI domain\n");
-#else
- irq_domain = NULL;
-#endif
*new_irq_domain = irq_domain;
return 0;
@@ -773,9 +795,10 @@ int __must_check fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus,
for (i = 0; i < irq_count; i++) {
irq_res = &irq_resources[i];
- /*
- * FIXME: Enable this code when the GIC-ITS MC support patch is merged
- */
+ /*
+ * FIXME: Enable this code when the GIC-ITS MC support patch is
+ * merged
+ */
#ifdef GIC_ITS_MC_SUPPORT
msi_entry = alloc_msi_entry(&mc_bus_dev->dev);
if (!msi_entry) {
@@ -817,12 +840,7 @@ int __must_check fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus,
dev_err(&mc_bus_dev->dev, "Failed to allocate IRQs\n");
goto cleanup_msi_entries;
}
-#endif
- /*
- * FIXME: Enable this code when the GIC-ITS MC support patch is merged
- */
-#ifdef GIC_ITS_MC_SUPPORT
for_each_msi_entry(msi_entry, &mc_bus_dev->dev) {
u32 irq_num = msi_entry->irq;
@@ -868,6 +886,9 @@ void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus)
struct fsl_mc_resource_pool *res_pool =
&mc_bus->resource_pools[FSL_MC_POOL_IRQ];
+ if (WARN_ON(!mc_bus->irq_resources))
+ return;
+
if (WARN_ON(res_pool->max_count == 0))
return;
@@ -982,12 +1003,14 @@ static int get_mc_addr_translation_ranges(struct device *dev,
for (i = 0; i < *num_ranges; ++i) {
struct fsl_mc_addr_translation_range *range = &(*ranges)[i];
- range->start_mc_addr = of_read_number(cell, mc_addr_cells);
+ range->mc_region_type = of_read_number(cell, 1);
+ range->start_mc_offset = of_read_number(cell + 1,
+ mc_addr_cells - 1);
cell += mc_addr_cells;
range->start_phys_addr = of_read_number(cell, paddr_cells);
cell += paddr_cells;
- range->end_mc_addr = range->start_mc_addr +
- of_read_number(cell, mc_size_cells);
+ range->end_mc_offset = range->start_mc_offset +
+ of_read_number(cell, mc_size_cells);
cell += mc_size_cells;
}
diff --git a/drivers/staging/fsl-mc/bus/mc-sys.c b/drivers/staging/fsl-mc/bus/mc-sys.c
index 5737f59..9ae000c 100644
--- a/drivers/staging/fsl-mc/bus/mc-sys.c
+++ b/drivers/staging/fsl-mc/bus/mc-sys.c
@@ -256,8 +256,10 @@ int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd)
* TODO: When MC command completion interrupts are supported
* call wait function here instead of usleep_range()
*/
- usleep_range(MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS,
- MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS);
+ if (preemptible()) {
+ usleep_range(MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS,
+ MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS);
+ }
if (time_after_eq(jiffies, jiffies_until_timeout)) {
pr_debug("MC command timed out (portal: %#llx, obj handle: %#x, command: %#x)\n",
diff --git a/drivers/staging/fsl-mc/include/dpmng.h b/drivers/staging/fsl-mc/include/dpmng.h
index 1b052b8..a38eb1a 100644
--- a/drivers/staging/fsl-mc/include/dpmng.h
+++ b/drivers/staging/fsl-mc/include/dpmng.h
@@ -41,11 +41,11 @@ struct fsl_mc_io;
/**
* Management Complex firmware version information
*/
-#define MC_VER_MAJOR 6
+#define MC_VER_MAJOR 7
#define MC_VER_MINOR 0
/**
- * struct mc_versoin
+ * struct mc_version
* @major: Major version number: incremented on API compatibility changes
* @minor: Minor version number: incremented on API additions (that are
* backward compatible); reset when major version is incremented
diff --git a/drivers/staging/fsl-mc/include/dprc.h b/drivers/staging/fsl-mc/include/dprc.h
index f1862a7..610ea31 100644
--- a/drivers/staging/fsl-mc/include/dprc.h
+++ b/drivers/staging/fsl-mc/include/dprc.h
@@ -99,7 +99,7 @@ int dprc_close(struct fsl_mc_io *mc_io, uint16_t token);
/* Object initialization allowed - software context associated with this
* container is allowed to invoke object initialization operations.
*/
-#define DPRC_CFG_OPT_OBJ_CREATE_ALLOWED 0x00000004
+#define DPRC_CFG_OPT_OBJ_CREATE_ALLOWED 0x00000004
/* Topology change allowed - software context associated with this
* container is allowed to invoke topology operations, such as attach/detach
@@ -115,6 +115,9 @@ int dprc_close(struct fsl_mc_io *mc_io, uint16_t token);
/* AIOP - Indicates that container belongs to AIOP. */
#define DPRC_CFG_OPT_AIOP 0x00000020
+/* IRQ Config - Indicates that the container allowed to configure its IRQs. */
+#define DPRC_CFG_OPT_IRQ_CFG_ALLOWED 0x00000040
+
/**
* struct dprc_cfg - Container configuration options
* @icid: Container's ICID; if set to 'DPRC_GET_ICID_FROM_POOL', a free
@@ -122,11 +125,13 @@ int dprc_close(struct fsl_mc_io *mc_io, uint16_t token);
* @portal_id: Portal ID; if set to 'DPRC_GET_PORTAL_ID_FROM_POOL', a free
* portal ID is allocated by the DPRC
* @options: Combination of 'DPRC_CFG_OPT_<X>' options
+ * @label: Object's label
*/
struct dprc_cfg {
uint16_t icid;
int portal_id;
uint64_t options;
+ char label[16];
};
/**
@@ -135,8 +140,7 @@ struct dprc_cfg {
* @token: Token of DPRC object
* @cfg: Child container configuration
* @child_container_id: Returned child container ID
- * @child_portal_paddr: Returned base physical address of the
- * child portal
+ * @child_portal_offset: Returned child portal offset from MC portal base
*
* Return: '0' on Success; Error code otherwise.
*/
@@ -144,7 +148,7 @@ int dprc_create_container(struct fsl_mc_io *mc_io,
uint16_t token,
struct dprc_cfg *cfg,
int *child_container_id,
- uint64_t *child_portal_paddr);
+ uint64_t *child_portal_offset);
/**
* dprc_destroy_container() - Destroy child container.
@@ -201,16 +205,20 @@ int dprc_reset_container(struct fsl_mc_io *mc_io,
/* Number of dprc's IRQs */
#define DPRC_NUM_OF_IRQS 1
-/* Object irq events */
+/* DPRC IRQ events */
-/* IRQ event - Indicates that a new object assigned to the container */
+/* IRQ event - Indicates that a new object added to the container */
#define DPRC_IRQ_EVENT_OBJ_ADDED 0x00000001
-/* IRQ event - Indicates that an object was unassigned from the container */
+
+/* IRQ event - Indicates that an object was removed from the container */
#define DPRC_IRQ_EVENT_OBJ_REMOVED 0x00000002
-/* IRQ event - Indicates that resources assigned to the container */
+
+/* IRQ event - Indicates that resources added to the container */
#define DPRC_IRQ_EVENT_RES_ADDED 0x00000004
-/* IRQ event - Indicates that resources unassigned from the container */
+
+/* IRQ event - Indicates that resources removed from the container */
#define DPRC_IRQ_EVENT_RES_REMOVED 0x00000008
+
/* IRQ event - Indicates that one of the descendant containers that opened by
* this container is destroyed
*/
@@ -610,6 +618,7 @@ int dprc_get_obj_count(struct fsl_mc_io *mc_io, uint16_t token, int *obj_count);
* @irq_count: Number of interrupts supported by the object
* @region_count: Number of mappable regions supported by the object
* @state: Object state: combination of DPRC_OBJ_STATE_ states
+ * @label: Object label
*/
struct dprc_obj_desc {
char type[16];
@@ -620,6 +629,7 @@ struct dprc_obj_desc {
uint8_t irq_count;
uint8_t region_count;
uint32_t state;
+ char label[16];
};
/**
@@ -642,6 +652,53 @@ int dprc_get_obj(struct fsl_mc_io *mc_io,
struct dprc_obj_desc *obj_desc);
/**
+ * dprc_obj_set_irq() - Set IRQ information for object to trigger an interrupt.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @token: Token of DPRC object
+ * @obj_index: Index of the object to set its IRQ (< obj_count returned from
+ * dprc_get_obj_count())
+ * @irq_index: Identifies the interrupt index to configure
+ * @irq_addr: Address that must be written to
+ * signal a message-based interrupt
+ * @irq_val: Value to write into irq_addr address
+ * @user_irq_id: Returned a user defined number associated with this IRQ
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dprc_obj_set_irq(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ int obj_index,
+ uint8_t irq_index,
+ uint64_t irq_addr,
+ uint32_t irq_val,
+ int user_irq_id);
+
+/**
+ * dprc_obj_get_irq() - Get IRQ information from object.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @token: Token of DPRC object
+ * @obj_index: Index of the object to get its IRQ (< obj_count returned from
+ * dprc_get_obj_count())
+ * @irq_index: The interrupt index to configure
+ * @type: Returned interrupt type: 0 represents message interrupt
+ * type (both irq_addr and irq_val are valid)
+ * @irq_addr: Returned address that must be written to
+ * signal the message-based interrupt
+ * @irq_val: Value to write into irq_addr address
+ * @user_irq_id: A user defined number associated with this IRQ
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dprc_obj_get_irq(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ int obj_index,
+ uint8_t irq_index,
+ int *type,
+ uint64_t *irq_addr,
+ uint32_t *irq_val,
+ int *user_irq_id);
+
+/**
* dprc_get_res_count() - Obtains the number of free resources that are assigned
* to this container, by pool type
* @mc_io: Pointer to MC portal's I/O object
@@ -699,26 +756,15 @@ int dprc_get_res_ids(struct fsl_mc_io *mc_io,
struct dprc_res_ids_range_desc *range_desc);
/**
- * dprc_get_portal_paddr() - Get the physical address of MC portals
- * @mc_io: Pointer to MC portal's I/O object
- * @token: Token of DPRC object
- * @portal_id: MC portal ID
- * @portal_addr: The physical address of the MC portal ID
- *
- * Return: '0' on Success; Error code otherwise.
- */
-int dprc_get_portal_paddr(struct fsl_mc_io *mc_io,
- uint16_t token,
- int portal_id,
- uint64_t *portal_addr);
-
-/**
* struct dprc_region_desc - Mappable region descriptor
- * @base_paddr: Region base physical address
+ * @base_offset: Region offset from region's base address.
+ * For DPMCP and DPRC objects, region base is offset from SoC MC portals
+ * base address; For DPIO, region base is offset from SoC QMan portals
+ * base address
* @size: Region size (in bytes)
*/
struct dprc_region_desc {
- uint64_t base_paddr;
+ uint64_t base_offset;
uint32_t size;
};
@@ -741,6 +787,20 @@ int dprc_get_obj_region(struct fsl_mc_io *mc_io,
struct dprc_region_desc *region_desc);
/**
+ * dprc_set_obj_label() - Set object label.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @token: Token of DPRC object
+ * @obj_index; Object index
+ * @label: The required label. The maximum length is 16 chars.
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dprc_set_obj_label(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ int obj_index,
+ char *label);
+
+/**
* struct dprc_endpoint - Endpoint description for link connect/disconnect
* operations
* @type: Endpoint object type: NULL terminated string
@@ -783,8 +843,8 @@ int dprc_disconnect(struct fsl_mc_io *mc_io,
/**
* dprc_get_connection() - Get connected endpoint and link status if connection
* exists.
-* @mc_io Pointer to MC portal's I/O object
-* @token Token of DPRC object
+* @mc_io Pointer to MC portal's I/O object
+* @token Token of DPRC object
* @endpoint1 Endpoint 1 configuration parameters
* @endpoint2 Returned endpoint 2 configuration parameters
* @state: Returned link state: 1 - link is up, 0 - link is down
diff --git a/drivers/staging/fsl-mc/include/mc-private.h b/drivers/staging/fsl-mc/include/mc-private.h
index 5b9c8f2..67ba488 100644
--- a/drivers/staging/fsl-mc/include/mc-private.h
+++ b/drivers/staging/fsl-mc/include/mc-private.h
@@ -52,16 +52,31 @@ struct fsl_mc {
};
/**
+ * enum mc_region_types - Types of MC MMIO regions
+ */
+enum fsl_mc_region_types {
+ FSL_MC_PORTAL = 0x0,
+ FSL_QBMAN_PORTAL,
+
+ /*
+ * New offset types must be added above this entry
+ */
+ FSL_NUM_MC_OFFSET_TYPES
+};
+
+/**
* struct fsl_mc_addr_translation_range - bus to system address translation
* range
- * @start_mc_addr: Start MC address of the range being translated
- * @end_mc_addr: MC address of the first byte after the range (last MC
- * address of the range is end_mc_addr - 1)
+ * @mc_region_type: Type of MC region for the range being translated
+ * @start_mc_offset: Start MC offset of the range being translated
+ * @end_mc_offset: MC offset of the first byte after the range (last MC
+ * offset of the range is end_mc_offset - 1)
* @start_phys_addr: system physical address corresponding to start_mc_addr
*/
struct fsl_mc_addr_translation_range {
- uint64_t start_mc_addr;
- uint64_t end_mc_addr;
+ enum fsl_mc_region_types mc_region_type;
+ uint64_t start_mc_offset;
+ uint64_t end_mc_offset;
phys_addr_t start_phys_addr;
};
@@ -115,6 +130,10 @@ int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
const char *driver_override,
unsigned int *total_irq_count);
+int dprc_lookup_object(struct fsl_mc_device *mc_bus_dev,
+ struct fsl_mc_device *child_dev,
+ uint32_t *child_obj_index);
+
int __init dprc_driver_init(void);
void __exit dprc_driver_exit(void);
diff --git a/drivers/staging/fsl-mc/include/mc.h b/drivers/staging/fsl-mc/include/mc.h
index f965c4d..0a2f381d 100644
--- a/drivers/staging/fsl-mc/include/mc.h
+++ b/drivers/staging/fsl-mc/include/mc.h
@@ -110,12 +110,16 @@ struct fsl_mc_resource {
* @msi_paddr: message-based interrupt physical address
* @msi_value: message-based interrupt data value
* @irq_number: Linux IRQ number assigned to the interrupt
+ * @mc_dev: MC object device that owns this interrupt
+ * @dev_irq_index: device-relative IRQ index
* @resource: MC generic resource associated with the interrupt
*/
struct fsl_mc_device_irq {
phys_addr_t msi_paddr;
uint32_t msi_value;
uint32_t irq_number;
+ struct fsl_mc_device *mc_dev;
+ uint8_t dev_irq_index;
struct fsl_mc_resource resource;
};
--
2.3.3
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/