Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1030789AbbD1RrU (ORCPT ); Tue, 28 Apr 2015 13:47:20 -0400 Received: from mail-bn1bn0108.outbound.protection.outlook.com ([157.56.110.108]:62688 "EHLO na01-bn1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1030504AbbD1RrN (ORCPT ); Tue, 28 Apr 2015 13:47:13 -0400 Authentication-Results: spf=fail (sender IP is 192.88.158.2) smtp.mailfrom=freescale.com; freescale.mail.onmicrosoft.com; dkim=none (message not signed) header.d=none; From: "J. German Rivera" To: , , , CC: , , , , , , , , , "J. German Rivera" Subject: [PATCH 4/7] staging: fsl-mc: Upgraded MC bus driver to match MC fw 7.0.0 Date: Tue, 28 Apr 2015 12:39:07 -0500 Message-ID: <1430242750-17745-5-git-send-email-German.Rivera@freescale.com> X-Mailer: git-send-email 2.3.3 In-Reply-To: <1430242750-17745-1-git-send-email-German.Rivera@freescale.com> References: <1430242750-17745-1-git-send-email-German.Rivera@freescale.com> X-EOPAttributedMessage: 0 X-Forefront-Antispam-Report: CIP:192.88.158.2;CTRY:US;IPV:NLI;EFV:NLI;BMV:1;SFV:NSPM;SFS:(10019020)(6009001)(339900001)(199003)(189002)(47776003)(86362001)(2201001)(85426001)(87936001)(19580405001)(19580395003)(46102003)(76176999)(48376002)(50986999)(6806004)(5890100001)(2950100001)(92566002)(36756003)(77096005)(106466001)(62966003)(229853001)(105606002)(50226001)(104016003)(50466002)(5001770100001)(77156002)(4001430100001)(579004);DIR:OUT;SFP:1102;SCL:1;SRVR:BLUPR03MB504;H:az84smr01.freescale.net;FPR:;SPF:Fail;MLV:sfv;A:1;MX:1;LANG:en; MIME-Version: 1.0 Content-Type: text/plain X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BLUPR03MB504; X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(601004)(5005006)(5002010)(3002001);SRVR:BLUPR03MB504;BCL:0;PCL:0;RULEID:;SRVR:BLUPR03MB504; X-Forefront-PRVS: 0560A2214D X-OriginatorOrg: freescale.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 28 Apr 2015 17:47:08.0319 (UTC) X-MS-Exchange-CrossTenant-Id: 710a03f5-10f6-4d38-9ff4-a80b81da590d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=710a03f5-10f6-4d38-9ff4-a80b81da590d;Ip=[192.88.158.2];Helo=[az84smr01.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BLUPR03MB504 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 46260 Lines: 1407 - Migrated MC bus driver to use DPRC flib 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 --- 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 | 106 +++++++++++++--- drivers/staging/fsl-mc/bus/dprc.c | 179 +++++++++++++++++++++++----- drivers/staging/fsl-mc/bus/mc-allocator.c | 26 ++-- drivers/staging/fsl-mc/bus/mc-bus.c | 125 ++++++++----------- 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, 431 insertions(+), 247 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 ce88859..b84cca3 100644 --- a/drivers/staging/fsl-mc/bus/dprc-driver.c +++ b/drivers/staging/fsl-mc/bus/dprc-driver.c @@ -233,12 +233,17 @@ static void dprc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev, WARN_ON(free_count != res_pool->free_count); } +/* + * Clean up all resource pools other than the IRQ pool + */ static void dprc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev) { int pool_type; - for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) - dprc_cleanup_resource_pool(mc_bus_dev, pool_type); + for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) { + if (pool_type != FSL_MC_POOL_IRQ) + dprc_cleanup_resource_pool(mc_bus_dev, pool_type); + } } /** @@ -343,6 +348,57 @@ int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev, EXPORT_SYMBOL_GPL(dprc_scan_objects); /** + * dprc_lookup_object - Finds a given MC object in a DPRC and returns + * the index of the object in the DPRC + * + * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object + * @child_dev: pointer to the fsl-mc device to be looked up + * @child_obj_index: output parameter to hold the index of the object + */ +int dprc_lookup_object(struct fsl_mc_device *mc_bus_dev, + struct fsl_mc_device *child_dev, + uint32_t *child_obj_index) +{ + int i; + int num_child_objects; + int error; + + error = dprc_get_obj_count(mc_bus_dev->mc_io, + mc_bus_dev->mc_handle, + &num_child_objects); + if (error < 0) { + dev_err(&mc_bus_dev->dev, "dprc_get_obj_count() failed: %d\n", + error); + return error; + } + + for (i = 0; i < num_child_objects; i++) { + struct dprc_obj_desc obj_desc; + + error = dprc_get_obj(mc_bus_dev->mc_io, + mc_bus_dev->mc_handle, + i, &obj_desc); + if (error < 0) { + dev_err(&mc_bus_dev->dev, + "dprc_get_obj(i=%d) failed: %d\n", + i, error); + return error; + } + + if (strcmp(obj_desc.type, child_dev->obj_desc.type) == 0 && + obj_desc.id == child_dev->obj_desc.id) { + *child_obj_index = i; + return 0; + } + } + + dev_err(&mc_bus_dev->dev, "%s.%u not found\n", + child_dev->obj_desc.type, child_dev->obj_desc.id); + + return -ENODEV; +} + +/** * dprc_scan_container - Scans a physical DPRC and synchronizes Linux bus state * * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object @@ -377,6 +433,7 @@ static int dprc_scan_container(struct fsl_mc_device *mc_bus_dev) return 0; error: + device_for_each_child(&mc_bus_dev->dev, NULL, __fsl_mc_device_remove); dprc_cleanup_all_resource_pools(mc_bus_dev); return error; } @@ -552,6 +609,22 @@ 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, because this callback is invoked + * with interrupts disabled, and we don't have a reliable + * way of sending commands to the MC from atomic context. + * The MC callback just set 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, @@ -568,24 +641,19 @@ static int register_dprc_irq_handlers(struct fsl_mc_device *mc_dev) goto error_unregister_irq_handlers; } - /* - * 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, + num_irq_handlers_registered++; + 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); goto error_unregister_irq_handlers; } - - num_irq_handlers_registered++; } return 0; @@ -729,15 +797,17 @@ 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); + dprc_cleanup_all_resource_pools(mc_dev); + 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..7a37d2d 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,10 +109,11 @@ 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; } +EXPORT_SYMBOL(dprc_create_container); int dprc_destroy_container(struct fsl_mc_io *mc_io, uint16_t token, @@ -112,6 +129,7 @@ int dprc_destroy_container(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } +EXPORT_SYMBOL(dprc_destroy_container); int dprc_reset_container(struct fsl_mc_io *mc_io, uint16_t token, @@ -127,6 +145,7 @@ int dprc_reset_container(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } +EXPORT_SYMBOL(dprc_reset_container); int dprc_get_irq(struct fsl_mc_io *mc_io, uint16_t token, @@ -158,6 +177,41 @@ int dprc_get_irq(struct fsl_mc_io *mc_io, return 0; } +EXPORT_SYMBOL(dprc_get_irq); + +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; +} +EXPORT_SYMBOL(dprc_obj_get_irq); int dprc_set_irq(struct fsl_mc_io *mc_io, uint16_t token, @@ -180,6 +234,33 @@ int dprc_set_irq(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } +EXPORT_SYMBOL(dprc_set_irq); + +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); +} +EXPORT_SYMBOL(dprc_obj_set_irq); int dprc_get_irq_enable(struct fsl_mc_io *mc_io, uint16_t token, @@ -204,6 +285,7 @@ int dprc_get_irq_enable(struct fsl_mc_io *mc_io, return 0; } +EXPORT_SYMBOL(dprc_get_irq_enable); int dprc_set_irq_enable(struct fsl_mc_io *mc_io, uint16_t token, @@ -221,6 +303,7 @@ int dprc_set_irq_enable(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } +EXPORT_SYMBOL(dprc_set_irq_enable); int dprc_get_irq_mask(struct fsl_mc_io *mc_io, uint16_t token, @@ -245,6 +328,7 @@ int dprc_get_irq_mask(struct fsl_mc_io *mc_io, return 0; } +EXPORT_SYMBOL(dprc_get_irq_mask); int dprc_set_irq_mask(struct fsl_mc_io *mc_io, uint16_t token, @@ -262,6 +346,7 @@ int dprc_set_irq_mask(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } +EXPORT_SYMBOL(dprc_set_irq_mask); int dprc_get_irq_status(struct fsl_mc_io *mc_io, uint16_t token, @@ -286,6 +371,7 @@ int dprc_get_irq_status(struct fsl_mc_io *mc_io, return 0; } +EXPORT_SYMBOL(dprc_get_irq_status); int dprc_clear_irq_status(struct fsl_mc_io *mc_io, uint16_t token, @@ -303,6 +389,7 @@ int dprc_clear_irq_status(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } +EXPORT_SYMBOL(dprc_clear_irq_status); int dprc_get_attributes(struct fsl_mc_io *mc_io, uint16_t token, @@ -331,6 +418,7 @@ int dprc_get_attributes(struct fsl_mc_io *mc_io, return 0; } +EXPORT_SYMBOL(dprc_get_attributes); int dprc_set_res_quota(struct fsl_mc_io *mc_io, uint16_t token, @@ -365,6 +453,7 @@ int dprc_set_res_quota(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } +EXPORT_SYMBOL(dprc_set_res_quota); int dprc_get_res_quota(struct fsl_mc_io *mc_io, uint16_t token, @@ -406,6 +495,7 @@ int dprc_get_res_quota(struct fsl_mc_io *mc_io, return 0; } +EXPORT_SYMBOL(dprc_get_res_quota); int dprc_assign(struct fsl_mc_io *mc_io, uint16_t token, @@ -441,6 +531,7 @@ int dprc_assign(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } +EXPORT_SYMBOL(dprc_assign); int dprc_unassign(struct fsl_mc_io *mc_io, uint16_t token, @@ -477,6 +568,7 @@ int dprc_unassign(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } +EXPORT_SYMBOL(dprc_unassign); int dprc_get_pool_count(struct fsl_mc_io *mc_io, uint16_t token, @@ -499,6 +591,7 @@ int dprc_get_pool_count(struct fsl_mc_io *mc_io, return 0; } +EXPORT_SYMBOL(dprc_get_pool_count); int dprc_get_pool(struct fsl_mc_io *mc_io, uint16_t token, @@ -539,6 +632,7 @@ int dprc_get_pool(struct fsl_mc_io *mc_io, return 0; } +EXPORT_SYMBOL(dprc_get_pool); int dprc_get_obj_count(struct fsl_mc_io *mc_io, uint16_t token, int *obj_count) { @@ -604,7 +698,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 +805,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 +843,47 @@ 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); +} +EXPORT_SYMBOL(dprc_set_obj_label); + int dprc_connect(struct fsl_mc_io *mc_io, uint16_t token, const struct dprc_endpoint *endpoint1, @@ -817,6 +935,7 @@ int dprc_connect(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } +EXPORT_SYMBOL(dprc_connect); int dprc_disconnect(struct fsl_mc_io *mc_io, uint16_t token, @@ -850,6 +969,7 @@ int dprc_disconnect(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } +EXPORT_SYMBOL(dprc_disconnect); int dprc_get_connection(struct fsl_mc_io *mc_io, uint16_t token, @@ -911,3 +1031,4 @@ int dprc_get_connection(struct fsl_mc_io *mc_io, return 0; } +EXPORT_SYMBOL(dprc_get_connection); diff --git a/drivers/staging/fsl-mc/bus/mc-allocator.c b/drivers/staging/fsl-mc/bus/mc-allocator.c index 27497e7..0c5fad0 100644 --- a/drivers/staging/fsl-mc/bus/mc-allocator.c +++ b/drivers/staging/fsl-mc/bus/mc-allocator.c @@ -531,13 +531,19 @@ 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: - 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); + } if (irqs) devm_kfree(&mc_dev->dev, irqs); @@ -555,8 +561,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; @@ -569,8 +576,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); + } devm_kfree(&mc_dev->dev, mc_dev->irqs); mc_dev->irqs = NULL; @@ -604,8 +614,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: @@ -627,8 +637,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 08fd559..55a8b86 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; } @@ -447,13 +465,7 @@ int fsl_mc_device_add(struct dprc_obj_desc *obj_desc, } device_initialize(&mc_dev->dev); - - /* - * FIXME: Enable this code when the GIC-ITS MC support patch is merged - */ -#ifdef GIC_ITS_MC_SUPPORT INIT_LIST_HEAD(&mc_dev->dev.msi_list); -#endif mc_dev->dev.parent = parent_dev; mc_dev->dev.bus = &fsl_mc_bus_type; dev_set_name(&mc_dev->dev, "%s.%d", obj_desc->type, obj_desc->id); @@ -586,10 +598,6 @@ void fsl_mc_device_remove(struct fsl_mc_device *mc_dev) } EXPORT_SYMBOL_GPL(fsl_mc_device_remove); -/* - * FIXME: Enable this code when the GIC-ITS MC support patch is merged - */ -#ifdef GIC_ITS_MC_SUPPORT static int mc_bus_msi_prepare(struct irq_domain *domain, struct device *dev, int nvec, msi_alloc_info_t *info) { @@ -641,6 +649,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 +669,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, as this function is invoked in atomic context + * (interrupts disabled) and we cannot reliably send MC commands + * in atomic context. + */ } } @@ -706,10 +725,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 +734,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; @@ -729,7 +741,6 @@ cleanup_its_of_node: of_node_put(its_of_node); return error; } -#endif /* GIC_ITS_MC_SUPPORT */ /* * Initialize the interrupt pool associated with a MC bus. @@ -739,26 +750,21 @@ int __must_check fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, unsigned int irq_count) { unsigned int i; + struct msi_desc *msi_entry; + struct msi_desc *next_msi_entry; struct fsl_mc_device_irq *irq_resources; struct fsl_mc_device_irq *irq_res; + int error; struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; + struct fsl_mc *mc = dev_get_drvdata(fsl_mc_bus_type.dev_root->parent); struct fsl_mc_resource_pool *res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; - /* - * FIXME: Enable this code when the GIC-ITS MC support patch is merged - */ -#ifdef GIC_ITS_MC_SUPPORT - int error; - struct msi_desc *msi_entry; - struct msi_desc *next_msi_entry; - struct fsl_mc *mc = dev_get_drvdata(fsl_mc_bus_type.dev_root->parent); /* * Detect duplicate invocations of this function: */ if (WARN_ON(!list_empty(&mc_bus_dev->dev.msi_list))) return -EINVAL; -#endif if (WARN_ON(irq_count == 0 || irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS)) @@ -773,10 +779,6 @@ 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 - */ -#ifdef GIC_ITS_MC_SUPPORT msi_entry = alloc_msi_entry(&mc_bus_dev->dev); if (!msi_entry) { dev_err(&mc_bus_dev->dev, "Failed to allocate msi entry\n"); @@ -789,7 +791,6 @@ int __must_check fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, msi_entry->msi_attrib.entry_nr = i; msi_entry->nvec_used = 1; list_add_tail(&msi_entry->list, &mc_bus_dev->dev.msi_list); -#endif /* * NOTE: irq_res->msi_paddr will be set by the @@ -803,10 +804,6 @@ int __must_check fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, } /* - * FIXME: Enable this code when the GIC-ITS MC support patch is merged - */ -#ifdef GIC_ITS_MC_SUPPORT - /* * NOTE: Calling this function will trigger the invocation of the * mc_bus_msi_prepare() callback */ @@ -817,12 +814,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; @@ -830,17 +822,12 @@ int __must_check fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, irq_res->irq_number = irq_num; irq_res->resource.id = irq_num; } -#endif res_pool->max_count = irq_count; res_pool->free_count = irq_count; mc_bus->irq_resources = irq_resources; return 0; - /* - * FIXME: Enable this code when the GIC-ITS MC support patch is merged - */ -#ifdef GIC_ITS_MC_SUPPORT cleanup_msi_entries: list_for_each_entry_safe(msi_entry, next_msi_entry, &mc_bus_dev->dev.msi_list, list) @@ -848,7 +835,6 @@ cleanup_msi_entries: devm_kfree(&mc_bus_dev->dev, irq_resources); return error; -#endif } EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool); @@ -858,32 +844,25 @@ EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool); */ void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus) { - /* - * FIXME: Enable this code when the GIC-ITS MC support patch is merged - */ -#ifdef GIC_ITS_MC_SUPPORT struct msi_desc *msi_entry; struct msi_desc *next_msi_entry; struct fsl_mc *mc = dev_get_drvdata(fsl_mc_bus_type.dev_root->parent); -#endif 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; if (WARN_ON(res_pool->free_count != res_pool->max_count)) return; - /* - * FIXME: Enable this code when the GIC-ITS MC support patch is merged - */ -#ifdef GIC_ITS_MC_SUPPORT msi_domain_free_irqs(mc->irq_domain, &mc_bus->mc_dev.dev); list_for_each_entry_safe(msi_entry, next_msi_entry, &mc_bus->mc_dev.dev.msi_list, list) kfree(msi_entry); -#endif devm_kfree(&mc_bus->mc_dev.dev, mc_bus->irq_resources); res_pool->max_count = 0; @@ -984,12 +963,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; } @@ -1021,15 +1002,9 @@ static int fsl_mc_bus_probe(struct platform_device *pdev) return -ENOMEM; platform_set_drvdata(pdev, mc); - - /* - * FIXME: Enable this code when the GIC-ITS MC support patch is merged - */ -#ifdef GIC_ITS_MC_SUPPORT error = create_mc_irq_domain(pdev, &mc->irq_domain); if (error < 0) return error; -#endif /* * Get physical address of MC portal for the root DPRC: 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_' 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@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/