From e09b41010ba33a20a87472ee821fa407a5b8da36 Mon Sep 17 00:00:00 2001 From: José Pekkarinen Date: Mon, 11 Apr 2016 10:41:07 +0300 Subject: These changes are the raw update to linux-4.4.6-rt14. Kernel sources are taken from kernel.org, and rt patch from the rt wiki download page. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During the rebasing, the following patch collided: Force tick interrupt and get rid of softirq magic(I70131fb85). Collisions have been removed because its logic was found on the source already. Change-Id: I7f57a4081d9deaa0d9ccfc41a6c8daccdee3b769 Signed-off-by: José Pekkarinen --- kernel/drivers/staging/fsl-mc/bus/dpbp.c | 356 +++++++-- kernel/drivers/staging/fsl-mc/bus/dpmcp-cmd.h | 81 +- kernel/drivers/staging/fsl-mc/bus/dpmcp.c | 316 ++++++-- kernel/drivers/staging/fsl-mc/bus/dpmcp.h | 220 +----- kernel/drivers/staging/fsl-mc/bus/dpmng.c | 31 +- kernel/drivers/staging/fsl-mc/bus/dprc-cmd.h | 7 +- kernel/drivers/staging/fsl-mc/bus/dprc-driver.c | 12 +- kernel/drivers/staging/fsl-mc/bus/dprc.c | 955 ++++++++++++++++++++--- kernel/drivers/staging/fsl-mc/bus/mc-allocator.c | 98 ++- kernel/drivers/staging/fsl-mc/bus/mc-bus.c | 135 +++- kernel/drivers/staging/fsl-mc/bus/mc-sys.c | 208 ++++- 11 files changed, 1787 insertions(+), 632 deletions(-) (limited to 'kernel/drivers/staging/fsl-mc/bus') diff --git a/kernel/drivers/staging/fsl-mc/bus/dpbp.c b/kernel/drivers/staging/fsl-mc/bus/dpbp.c index d99ab6d0b..2d97173f8 100644 --- a/kernel/drivers/staging/fsl-mc/bus/dpbp.c +++ b/kernel/drivers/staging/fsl-mc/bus/dpbp.c @@ -34,14 +34,34 @@ #include "../include/dpbp.h" #include "../include/dpbp-cmd.h" -int dpbp_open(struct fsl_mc_io *mc_io, int dpbp_id, uint16_t *token) +/** + * dpbp_open() - Open a control session for the specified object. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @dpbp_id: DPBP unique ID + * @token: Returned token; use in subsequent API calls + * + * This function can be used to open a control session for an + * already created object; an object may have been declared in + * the DPL or by calling the dpbp_create function. + * This function returns a unique authentication token, + * associated with the specific object ID and the specific MC + * portal; this token must be used in all subsequent commands for + * this specific object + * + * Return: '0' on Success; Error code otherwise. + */ +int dpbp_open(struct fsl_mc_io *mc_io, + u32 cmd_flags, + int dpbp_id, + u16 *token) { struct mc_command cmd = { 0 }; int err; /* prepare command */ cmd.header = mc_encode_cmd_header(DPBP_CMDID_OPEN, - MC_CMD_PRI_LOW, 0); + cmd_flags, 0); cmd.params[0] |= mc_enc(0, 32, dpbp_id); /* send command to mc*/ @@ -56,12 +76,25 @@ int dpbp_open(struct fsl_mc_io *mc_io, int dpbp_id, uint16_t *token) } EXPORT_SYMBOL(dpbp_open); -int dpbp_close(struct fsl_mc_io *mc_io, uint16_t token) +/** + * dpbp_close() - Close the control session of the object + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPBP object + * + * After this function is called, no further operations are + * allowed on the object without opening a new control session. + * + * Return: '0' on Success; Error code otherwise. + */ +int dpbp_close(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token) { struct mc_command cmd = { 0 }; /* prepare command */ - cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLOSE, MC_CMD_PRI_HIGH, + cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLOSE, cmd_flags, token); /* send command to mc*/ @@ -69,9 +102,31 @@ int dpbp_close(struct fsl_mc_io *mc_io, uint16_t token) } EXPORT_SYMBOL(dpbp_close); +/** + * dpbp_create() - Create the DPBP object. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @cfg: Configuration structure + * @token: Returned token; use in subsequent API calls + * + * Create the DPBP object, allocate required resources and + * perform required initialization. + * + * The object can be created either by declaring it in the + * DPL file, or by calling this function. + * This function returns a unique authentication token, + * associated with the specific object ID and the specific MC + * portal; this token must be used in all subsequent calls to + * this specific object. For objects that are created using the + * DPL file, call dpbp_open function to get an authentication + * token first. + * + * Return: '0' on Success; Error code otherwise. + */ int dpbp_create(struct fsl_mc_io *mc_io, + u32 cmd_flags, const struct dpbp_cfg *cfg, - uint16_t *token) + u16 *token) { struct mc_command cmd = { 0 }; int err; @@ -80,7 +135,7 @@ int dpbp_create(struct fsl_mc_io *mc_io, /* prepare command */ cmd.header = mc_encode_cmd_header(DPBP_CMDID_CREATE, - MC_CMD_PRI_LOW, 0); + cmd_flags, 0); /* send command to mc*/ err = mc_send_command(mc_io, &cmd); @@ -93,24 +148,44 @@ int dpbp_create(struct fsl_mc_io *mc_io, return 0; } -int dpbp_destroy(struct fsl_mc_io *mc_io, uint16_t token) +/** + * dpbp_destroy() - Destroy the DPBP object and release all its resources. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPBP object + * + * Return: '0' on Success; error code otherwise. + */ +int dpbp_destroy(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token) { struct mc_command cmd = { 0 }; /* prepare command */ cmd.header = mc_encode_cmd_header(DPBP_CMDID_DESTROY, - MC_CMD_PRI_LOW, token); + cmd_flags, token); /* send command to mc*/ return mc_send_command(mc_io, &cmd); } -int dpbp_enable(struct fsl_mc_io *mc_io, uint16_t token) +/** + * dpbp_enable() - Enable the DPBP. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPBP object + * + * Return: '0' on Success; Error code otherwise. + */ +int dpbp_enable(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token) { struct mc_command cmd = { 0 }; /* prepare command */ - cmd.header = mc_encode_cmd_header(DPBP_CMDID_ENABLE, MC_CMD_PRI_LOW, + cmd.header = mc_encode_cmd_header(DPBP_CMDID_ENABLE, cmd_flags, token); /* send command to mc*/ @@ -118,25 +193,47 @@ int dpbp_enable(struct fsl_mc_io *mc_io, uint16_t token) } EXPORT_SYMBOL(dpbp_enable); -int dpbp_disable(struct fsl_mc_io *mc_io, uint16_t token) +/** + * dpbp_disable() - Disable the DPBP. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPBP object + * + * Return: '0' on Success; Error code otherwise. + */ +int dpbp_disable(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token) { struct mc_command cmd = { 0 }; /* prepare command */ cmd.header = mc_encode_cmd_header(DPBP_CMDID_DISABLE, - MC_CMD_PRI_LOW, token); + cmd_flags, token); /* send command to mc*/ return mc_send_command(mc_io, &cmd); } EXPORT_SYMBOL(dpbp_disable); -int dpbp_is_enabled(struct fsl_mc_io *mc_io, uint16_t token, int *en) +/** + * dpbp_is_enabled() - Check if the DPBP is enabled. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPBP object + * @en: Returns '1' if object is enabled; '0' otherwise + * + * Return: '0' on Success; Error code otherwise. + */ +int dpbp_is_enabled(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + int *en) { struct mc_command cmd = { 0 }; int err; /* prepare command */ - cmd.header = mc_encode_cmd_header(DPBP_CMDID_IS_ENABLED, MC_CMD_PRI_LOW, + cmd.header = mc_encode_cmd_header(DPBP_CMDID_IS_ENABLED, cmd_flags, token); /* send command to mc*/ @@ -150,53 +247,83 @@ int dpbp_is_enabled(struct fsl_mc_io *mc_io, uint16_t token, int *en) return 0; } -int dpbp_reset(struct fsl_mc_io *mc_io, uint16_t token) +/** + * dpbp_reset() - Reset the DPBP, returns the object to initial state. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPBP object + * + * Return: '0' on Success; Error code otherwise. + */ +int dpbp_reset(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token) { struct mc_command cmd = { 0 }; /* prepare command */ cmd.header = mc_encode_cmd_header(DPBP_CMDID_RESET, - MC_CMD_PRI_LOW, token); + cmd_flags, token); /* send command to mc*/ return mc_send_command(mc_io, &cmd); } +/** + * dpbp_set_irq() - Set IRQ information for the DPBP to trigger an interrupt. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPBP object + * @irq_index: Identifies the interrupt index to configure + * @irq_cfg: IRQ configuration + * + * Return: '0' on Success; Error code otherwise. + */ int dpbp_set_irq(struct fsl_mc_io *mc_io, - uint16_t token, - uint8_t irq_index, - uint64_t irq_paddr, - uint32_t irq_val, - int user_irq_id) + u32 cmd_flags, + u16 token, + u8 irq_index, + struct dpbp_irq_cfg *irq_cfg) { struct mc_command cmd = { 0 }; /* prepare command */ cmd.header = mc_encode_cmd_header(DPBP_CMDID_SET_IRQ, - MC_CMD_PRI_LOW, token); + cmd_flags, token); cmd.params[0] |= mc_enc(0, 8, irq_index); - cmd.params[0] |= mc_enc(32, 32, irq_val); - cmd.params[1] |= mc_enc(0, 64, irq_paddr); - cmd.params[2] |= mc_enc(0, 32, user_irq_id); + cmd.params[0] |= mc_enc(32, 32, irq_cfg->val); + cmd.params[1] |= mc_enc(0, 64, irq_cfg->addr); + cmd.params[2] |= mc_enc(0, 32, irq_cfg->user_irq_id); /* send command to mc*/ return mc_send_command(mc_io, &cmd); } +/** + * dpbp_get_irq() - Get IRQ information from the DPBP. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPBP object + * @irq_index: The interrupt index to configure + * @type: Interrupt type: 0 represents message interrupt + * type (both irq_addr and irq_val are valid) + * @irq_cfg: IRQ attributes + * + * Return: '0' on Success; Error code otherwise. + */ int dpbp_get_irq(struct fsl_mc_io *mc_io, - uint16_t token, - uint8_t irq_index, + u32 cmd_flags, + u16 token, + u8 irq_index, int *type, - uint64_t *irq_paddr, - uint32_t *irq_val, - int *user_irq_id) + struct dpbp_irq_cfg *irq_cfg) { struct mc_command cmd = { 0 }; int err; /* prepare command */ cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ, - MC_CMD_PRI_LOW, token); + cmd_flags, token); cmd.params[0] |= mc_enc(32, 8, irq_index); /* send command to mc*/ @@ -205,23 +332,39 @@ int dpbp_get_irq(struct fsl_mc_io *mc_io, return err; /* retrieve response parameters */ - *irq_val = (uint32_t)mc_dec(cmd.params[0], 0, 32); - *irq_paddr = (uint64_t)mc_dec(cmd.params[1], 0, 64); - *user_irq_id = (int)mc_dec(cmd.params[2], 0, 32); + irq_cfg->val = (u32)mc_dec(cmd.params[0], 0, 32); + irq_cfg->addr = (u64)mc_dec(cmd.params[1], 0, 64); + irq_cfg->user_irq_id = (int)mc_dec(cmd.params[2], 0, 32); *type = (int)mc_dec(cmd.params[2], 32, 32); return 0; } +/** + * dpbp_set_irq_enable() - Set overall interrupt state. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPBP object + * @irq_index: The interrupt index to configure + * @en: Interrupt state - enable = 1, disable = 0 + * + * Allows GPP software to control when interrupts are generated. + * Each interrupt can have up to 32 causes. The enable/disable control's the + * overall interrupt state. if the interrupt is disabled no causes will cause + * an interrupt. + * + * Return: '0' on Success; Error code otherwise. + */ int dpbp_set_irq_enable(struct fsl_mc_io *mc_io, - uint16_t token, - uint8_t irq_index, - uint8_t en) + u32 cmd_flags, + u16 token, + u8 irq_index, + u8 en) { struct mc_command cmd = { 0 }; /* prepare command */ cmd.header = mc_encode_cmd_header(DPBP_CMDID_SET_IRQ_ENABLE, - MC_CMD_PRI_LOW, token); + cmd_flags, token); cmd.params[0] |= mc_enc(0, 8, en); cmd.params[0] |= mc_enc(32, 8, irq_index); @@ -229,17 +372,28 @@ int dpbp_set_irq_enable(struct fsl_mc_io *mc_io, return mc_send_command(mc_io, &cmd); } +/** + * dpbp_get_irq_enable() - Get overall interrupt state + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPBP object + * @irq_index: The interrupt index to configure + * @en: Returned interrupt state - enable = 1, disable = 0 + * + * Return: '0' on Success; Error code otherwise. + */ int dpbp_get_irq_enable(struct fsl_mc_io *mc_io, - uint16_t token, - uint8_t irq_index, - uint8_t *en) + u32 cmd_flags, + u16 token, + u8 irq_index, + u8 *en) { struct mc_command cmd = { 0 }; int err; /* prepare command */ cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ_ENABLE, - MC_CMD_PRI_LOW, token); + cmd_flags, token); cmd.params[0] |= mc_enc(32, 8, irq_index); /* send command to mc*/ @@ -248,20 +402,37 @@ int dpbp_get_irq_enable(struct fsl_mc_io *mc_io, return err; /* retrieve response parameters */ - *en = (uint8_t)mc_dec(cmd.params[0], 0, 8); + *en = (u8)mc_dec(cmd.params[0], 0, 8); return 0; } +/** + * dpbp_set_irq_mask() - Set interrupt mask. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPBP object + * @irq_index: The interrupt index to configure + * @mask: Event mask to trigger interrupt; + * each bit: + * 0 = ignore event + * 1 = consider event for asserting IRQ + * + * Every interrupt can have up to 32 causes and the interrupt model supports + * masking/unmasking each cause independently + * + * Return: '0' on Success; Error code otherwise. + */ int dpbp_set_irq_mask(struct fsl_mc_io *mc_io, - uint16_t token, - uint8_t irq_index, - uint32_t mask) + u32 cmd_flags, + u16 token, + u8 irq_index, + u32 mask) { struct mc_command cmd = { 0 }; /* prepare command */ cmd.header = mc_encode_cmd_header(DPBP_CMDID_SET_IRQ_MASK, - MC_CMD_PRI_LOW, token); + cmd_flags, token); cmd.params[0] |= mc_enc(0, 32, mask); cmd.params[0] |= mc_enc(32, 8, irq_index); @@ -269,17 +440,31 @@ int dpbp_set_irq_mask(struct fsl_mc_io *mc_io, return mc_send_command(mc_io, &cmd); } +/** + * dpbp_get_irq_mask() - Get interrupt mask. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPBP object + * @irq_index: The interrupt index to configure + * @mask: Returned event mask to trigger interrupt + * + * Every interrupt can have up to 32 causes and the interrupt model supports + * masking/unmasking each cause independently + * + * Return: '0' on Success; Error code otherwise. + */ int dpbp_get_irq_mask(struct fsl_mc_io *mc_io, - uint16_t token, - uint8_t irq_index, - uint32_t *mask) + u32 cmd_flags, + u16 token, + u8 irq_index, + u32 *mask) { struct mc_command cmd = { 0 }; int err; /* prepare command */ cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ_MASK, - MC_CMD_PRI_LOW, token); + cmd_flags, token); cmd.params[0] |= mc_enc(32, 8, irq_index); /* send command to mc*/ @@ -288,21 +473,35 @@ int dpbp_get_irq_mask(struct fsl_mc_io *mc_io, return err; /* retrieve response parameters */ - *mask = (uint32_t)mc_dec(cmd.params[0], 0, 32); + *mask = (u32)mc_dec(cmd.params[0], 0, 32); return 0; } +/** + * dpbp_get_irq_status() - Get the current status of any pending interrupts. + * + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPBP object + * @irq_index: The interrupt index to configure + * @status: Returned interrupts status - one bit per cause: + * 0 = no interrupt pending + * 1 = interrupt pending + * + * Return: '0' on Success; Error code otherwise. + */ int dpbp_get_irq_status(struct fsl_mc_io *mc_io, - uint16_t token, - uint8_t irq_index, - uint32_t *status) + u32 cmd_flags, + u16 token, + u8 irq_index, + u32 *status) { struct mc_command cmd = { 0 }; int err; /* prepare command */ cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ_STATUS, - MC_CMD_PRI_LOW, token); + cmd_flags, token); cmd.params[0] |= mc_enc(32, 8, irq_index); /* send command to mc*/ @@ -311,20 +510,34 @@ int dpbp_get_irq_status(struct fsl_mc_io *mc_io, return err; /* retrieve response parameters */ - *status = (uint32_t)mc_dec(cmd.params[0], 0, 32); + *status = (u32)mc_dec(cmd.params[0], 0, 32); return 0; } +/** + * dpbp_clear_irq_status() - Clear a pending interrupt's status + * + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPBP object + * @irq_index: The interrupt index to configure + * @status: Bits to clear (W1C) - one bit per cause: + * 0 = don't change + * 1 = clear status bit + * + * Return: '0' on Success; Error code otherwise. + */ int dpbp_clear_irq_status(struct fsl_mc_io *mc_io, - uint16_t token, - uint8_t irq_index, - uint32_t status) + u32 cmd_flags, + u16 token, + u8 irq_index, + u32 status) { struct mc_command cmd = { 0 }; /* prepare command */ cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLEAR_IRQ_STATUS, - MC_CMD_PRI_LOW, token); + cmd_flags, token); cmd.params[0] |= mc_enc(0, 32, status); cmd.params[0] |= mc_enc(32, 8, irq_index); @@ -332,8 +545,19 @@ int dpbp_clear_irq_status(struct fsl_mc_io *mc_io, return mc_send_command(mc_io, &cmd); } +/** + * dpbp_get_attributes - Retrieve DPBP attributes. + * + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPBP object + * @attr: Returned object's attributes + * + * Return: '0' on Success; Error code otherwise. + */ int dpbp_get_attributes(struct fsl_mc_io *mc_io, - uint16_t token, + u32 cmd_flags, + u16 token, struct dpbp_attr *attr) { struct mc_command cmd = { 0 }; @@ -341,7 +565,7 @@ int dpbp_get_attributes(struct fsl_mc_io *mc_io, /* prepare command */ cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_ATTR, - MC_CMD_PRI_LOW, token); + cmd_flags, token); /* send command to mc*/ err = mc_send_command(mc_io, &cmd); @@ -349,10 +573,10 @@ int dpbp_get_attributes(struct fsl_mc_io *mc_io, return err; /* retrieve response parameters */ - attr->bpid = (uint16_t)mc_dec(cmd.params[0], 16, 16); + attr->bpid = (u16)mc_dec(cmd.params[0], 16, 16); attr->id = (int)mc_dec(cmd.params[0], 32, 32); - attr->version.major = (uint16_t)mc_dec(cmd.params[1], 0, 16); - attr->version.minor = (uint16_t)mc_dec(cmd.params[1], 16, 16); + attr->version.major = (u16)mc_dec(cmd.params[1], 0, 16); + attr->version.minor = (u16)mc_dec(cmd.params[1], 16, 16); return 0; } EXPORT_SYMBOL(dpbp_get_attributes); diff --git a/kernel/drivers/staging/fsl-mc/bus/dpmcp-cmd.h b/kernel/drivers/staging/fsl-mc/bus/dpmcp-cmd.h index 57f326b60..a87e9f84f 100644 --- a/kernel/drivers/staging/fsl-mc/bus/dpmcp-cmd.h +++ b/kernel/drivers/staging/fsl-mc/bus/dpmcp-cmd.h @@ -34,7 +34,7 @@ /* DPMCP Version */ #define DPMCP_VER_MAJOR 2 -#define DPMCP_VER_MINOR 0 +#define DPMCP_VER_MINOR 1 /* Command IDs */ #define DPMCP_CMDID_CLOSE 0x800 @@ -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/kernel/drivers/staging/fsl-mc/bus/dpmcp.c b/kernel/drivers/staging/fsl-mc/bus/dpmcp.c index 6b9da5b7f..b0248f574 100644 --- a/kernel/drivers/staging/fsl-mc/bus/dpmcp.c +++ b/kernel/drivers/staging/fsl-mc/bus/dpmcp.c @@ -34,14 +34,34 @@ #include "dpmcp.h" #include "dpmcp-cmd.h" -int dpmcp_open(struct fsl_mc_io *mc_io, int dpmcp_id, uint16_t *token) +/** + * dpmcp_open() - Open a control session for the specified object. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @dpmcp_id: DPMCP unique ID + * @token: Returned token; use in subsequent API calls + * + * This function can be used to open a control session for an + * already created object; an object may have been declared in + * the DPL or by calling the dpmcp_create function. + * This function returns a unique authentication token, + * associated with the specific object ID and the specific MC + * portal; this token must be used in all subsequent commands for + * this specific object + * + * Return: '0' on Success; Error code otherwise. + */ +int dpmcp_open(struct fsl_mc_io *mc_io, + u32 cmd_flags, + int dpmcp_id, + u16 *token) { struct mc_command cmd = { 0 }; int err; /* prepare command */ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_OPEN, - MC_CMD_PRI_LOW, 0); + cmd_flags, 0); cmd.params[0] |= mc_enc(0, 32, dpmcp_id); /* send command to mc*/ @@ -55,28 +75,63 @@ int dpmcp_open(struct fsl_mc_io *mc_io, int dpmcp_id, uint16_t *token) return err; } -int dpmcp_close(struct fsl_mc_io *mc_io, uint16_t token) +/** + * dpmcp_close() - Close the control session of the object + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPMCP object + * + * After this function is called, no further operations are + * allowed on the object without opening a new control session. + * + * Return: '0' on Success; Error code otherwise. + */ +int dpmcp_close(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token) { struct mc_command cmd = { 0 }; /* prepare command */ - cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CLOSE, MC_CMD_PRI_HIGH, - token); + cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CLOSE, + cmd_flags, token); /* send command to mc*/ return mc_send_command(mc_io, &cmd); } +/** + * dpmcp_create() - Create the DPMCP object. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @cfg: Configuration structure + * @token: Returned token; use in subsequent API calls + * + * Create the DPMCP object, allocate required resources and + * perform required initialization. + * + * The object can be created either by declaring it in the + * DPL file, or by calling this function. + * This function returns a unique authentication token, + * associated with the specific object ID and the specific MC + * portal; this token must be used in all subsequent calls to + * this specific object. For objects that are created using the + * DPL file, call dpmcp_open function to get an authentication + * token first. + * + * Return: '0' on Success; Error code otherwise. + */ int dpmcp_create(struct fsl_mc_io *mc_io, + u32 cmd_flags, const struct dpmcp_cfg *cfg, - uint16_t *token) + u16 *token) { struct mc_command cmd = { 0 }; int err; /* prepare command */ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CREATE, - MC_CMD_PRI_LOW, 0); + cmd_flags, 0); cmd.params[0] |= mc_enc(0, 32, cfg->portal_id); /* send command to mc*/ @@ -90,65 +145,105 @@ int dpmcp_create(struct fsl_mc_io *mc_io, return 0; } -int dpmcp_destroy(struct fsl_mc_io *mc_io, uint16_t token) +/** + * dpmcp_destroy() - Destroy the DPMCP object and release all its resources. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPMCP object + * + * Return: '0' on Success; error code otherwise. + */ +int dpmcp_destroy(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token) { struct mc_command cmd = { 0 }; /* prepare command */ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_DESTROY, - MC_CMD_PRI_LOW, token); + cmd_flags, token); /* send command to mc*/ return mc_send_command(mc_io, &cmd); } -int dpmcp_reset(struct fsl_mc_io *mc_io, uint16_t token) +/** + * dpmcp_reset() - Reset the DPMCP, returns the object to initial state. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPMCP object + * + * Return: '0' on Success; Error code otherwise. + */ +int dpmcp_reset(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token) { struct mc_command cmd = { 0 }; /* prepare command */ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_RESET, - MC_CMD_PRI_LOW, token); + cmd_flags, token); /* send command to mc*/ return mc_send_command(mc_io, &cmd); } +/** + * dpmcp_set_irq() - Set IRQ information for the DPMCP to trigger an interrupt. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPMCP object + * @irq_index: Identifies the interrupt index to configure + * @irq_cfg: IRQ configuration + * + * Return: '0' on Success; Error code otherwise. + */ int dpmcp_set_irq(struct fsl_mc_io *mc_io, - uint16_t token, - uint8_t irq_index, - uint64_t irq_addr, - uint32_t irq_val, - int user_irq_id) + u32 cmd_flags, + u16 token, + u8 irq_index, + struct dpmcp_irq_cfg *irq_cfg) { struct mc_command cmd = { 0 }; /* prepare command */ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_SET_IRQ, - MC_CMD_PRI_LOW, token); + cmd_flags, token); cmd.params[0] |= mc_enc(0, 8, irq_index); - cmd.params[0] |= mc_enc(32, 32, irq_val); - cmd.params[1] |= mc_enc(0, 64, irq_addr); - cmd.params[2] |= mc_enc(0, 32, user_irq_id); + cmd.params[0] |= mc_enc(32, 32, irq_cfg->val); + cmd.params[1] |= mc_enc(0, 64, irq_cfg->paddr); + cmd.params[2] |= mc_enc(0, 32, irq_cfg->user_irq_id); /* send command to mc*/ return mc_send_command(mc_io, &cmd); } +/** + * dpmcp_get_irq() - Get IRQ information from the DPMCP. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPMCP object + * @irq_index: The interrupt index to configure + * @type: Interrupt type: 0 represents message interrupt + * type (both irq_addr and irq_val are valid) + * @irq_cfg: IRQ attributes + * + * Return: '0' on Success; Error code otherwise. + */ int dpmcp_get_irq(struct fsl_mc_io *mc_io, - uint16_t token, - uint8_t irq_index, - int *type, - uint64_t *irq_addr, - uint32_t *irq_val, - int *user_irq_id) + u32 cmd_flags, + u16 token, + u8 irq_index, + int *type, + struct dpmcp_irq_cfg *irq_cfg) { struct mc_command cmd = { 0 }; int err; /* prepare command */ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ, - MC_CMD_PRI_LOW, token); + cmd_flags, token); cmd.params[0] |= mc_enc(32, 8, irq_index); /* send command to mc*/ @@ -157,23 +252,39 @@ int dpmcp_get_irq(struct fsl_mc_io *mc_io, return err; /* retrieve response parameters */ - *irq_val = (uint32_t)mc_dec(cmd.params[0], 0, 32); - *irq_addr = (uint64_t)mc_dec(cmd.params[1], 0, 64); - *user_irq_id = (int)mc_dec(cmd.params[2], 0, 32); + irq_cfg->val = (u32)mc_dec(cmd.params[0], 0, 32); + irq_cfg->paddr = (u64)mc_dec(cmd.params[1], 0, 64); + irq_cfg->user_irq_id = (int)mc_dec(cmd.params[2], 0, 32); *type = (int)mc_dec(cmd.params[2], 32, 32); return 0; } +/** + * dpmcp_set_irq_enable() - Set overall interrupt state. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPMCP object + * @irq_index: The interrupt index to configure + * @en: Interrupt state - enable = 1, disable = 0 + * + * Allows GPP software to control when interrupts are generated. + * Each interrupt can have up to 32 causes. The enable/disable control's the + * overall interrupt state. if the interrupt is disabled no causes will cause + * an interrupt. + * + * Return: '0' on Success; Error code otherwise. + */ int dpmcp_set_irq_enable(struct fsl_mc_io *mc_io, - uint16_t token, - uint8_t irq_index, - uint8_t en) + u32 cmd_flags, + u16 token, + u8 irq_index, + u8 en) { struct mc_command cmd = { 0 }; /* prepare command */ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_SET_IRQ_ENABLE, - MC_CMD_PRI_LOW, token); + cmd_flags, token); cmd.params[0] |= mc_enc(0, 8, en); cmd.params[0] |= mc_enc(32, 8, irq_index); @@ -181,17 +292,28 @@ int dpmcp_set_irq_enable(struct fsl_mc_io *mc_io, return mc_send_command(mc_io, &cmd); } +/** + * dpmcp_get_irq_enable() - Get overall interrupt state + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPMCP object + * @irq_index: The interrupt index to configure + * @en: Returned interrupt state - enable = 1, disable = 0 + * + * Return: '0' on Success; Error code otherwise. + */ int dpmcp_get_irq_enable(struct fsl_mc_io *mc_io, - uint16_t token, - uint8_t irq_index, - uint8_t *en) + u32 cmd_flags, + u16 token, + u8 irq_index, + u8 *en) { struct mc_command cmd = { 0 }; int err; /* prepare command */ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ_ENABLE, - MC_CMD_PRI_LOW, token); + cmd_flags, token); cmd.params[0] |= mc_enc(32, 8, irq_index); /* send command to mc*/ @@ -200,20 +322,37 @@ int dpmcp_get_irq_enable(struct fsl_mc_io *mc_io, return err; /* retrieve response parameters */ - *en = (uint8_t)mc_dec(cmd.params[0], 0, 8); + *en = (u8)mc_dec(cmd.params[0], 0, 8); return 0; } +/** + * dpmcp_set_irq_mask() - Set interrupt mask. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPMCP object + * @irq_index: The interrupt index to configure + * @mask: Event mask to trigger interrupt; + * each bit: + * 0 = ignore event + * 1 = consider event for asserting IRQ + * + * Every interrupt can have up to 32 causes and the interrupt model supports + * masking/unmasking each cause independently + * + * Return: '0' on Success; Error code otherwise. + */ int dpmcp_set_irq_mask(struct fsl_mc_io *mc_io, - uint16_t token, - uint8_t irq_index, - uint32_t mask) + u32 cmd_flags, + u16 token, + u8 irq_index, + u32 mask) { struct mc_command cmd = { 0 }; /* prepare command */ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_SET_IRQ_MASK, - MC_CMD_PRI_LOW, token); + cmd_flags, token); cmd.params[0] |= mc_enc(0, 32, mask); cmd.params[0] |= mc_enc(32, 8, irq_index); @@ -221,17 +360,31 @@ int dpmcp_set_irq_mask(struct fsl_mc_io *mc_io, return mc_send_command(mc_io, &cmd); } +/** + * dpmcp_get_irq_mask() - Get interrupt mask. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPMCP object + * @irq_index: The interrupt index to configure + * @mask: Returned event mask to trigger interrupt + * + * Every interrupt can have up to 32 causes and the interrupt model supports + * masking/unmasking each cause independently + * + * Return: '0' on Success; Error code otherwise. + */ int dpmcp_get_irq_mask(struct fsl_mc_io *mc_io, - uint16_t token, - uint8_t irq_index, - uint32_t *mask) + u32 cmd_flags, + u16 token, + u8 irq_index, + u32 *mask) { struct mc_command cmd = { 0 }; int err; /* prepare command */ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ_MASK, - MC_CMD_PRI_LOW, token); + cmd_flags, token); cmd.params[0] |= mc_enc(32, 8, irq_index); /* send command to mc*/ @@ -240,21 +393,35 @@ int dpmcp_get_irq_mask(struct fsl_mc_io *mc_io, return err; /* retrieve response parameters */ - *mask = (uint32_t)mc_dec(cmd.params[0], 0, 32); + *mask = (u32)mc_dec(cmd.params[0], 0, 32); return 0; } +/** + * dpmcp_get_irq_status() - Get the current status of any pending interrupts. + * + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPMCP object + * @irq_index: The interrupt index to configure + * @status: Returned interrupts status - one bit per cause: + * 0 = no interrupt pending + * 1 = interrupt pending + * + * Return: '0' on Success; Error code otherwise. + */ int dpmcp_get_irq_status(struct fsl_mc_io *mc_io, - uint16_t token, - uint8_t irq_index, - uint32_t *status) + u32 cmd_flags, + u16 token, + u8 irq_index, + u32 *status) { struct mc_command cmd = { 0 }; int err; /* prepare command */ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ_STATUS, - MC_CMD_PRI_LOW, token); + cmd_flags, token); cmd.params[0] |= mc_enc(32, 8, irq_index); /* send command to mc*/ @@ -263,20 +430,34 @@ int dpmcp_get_irq_status(struct fsl_mc_io *mc_io, return err; /* retrieve response parameters */ - *status = (uint32_t)mc_dec(cmd.params[0], 0, 32); + *status = (u32)mc_dec(cmd.params[0], 0, 32); return 0; } +/** + * dpmcp_clear_irq_status() - Clear a pending interrupt's status + * + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPMCP object + * @irq_index: The interrupt index to configure + * @status: Bits to clear (W1C) - one bit per cause: + * 0 = don't change + * 1 = clear status bit + * + * Return: '0' on Success; Error code otherwise. + */ int dpmcp_clear_irq_status(struct fsl_mc_io *mc_io, - uint16_t token, - uint8_t irq_index, - uint32_t status) + u32 cmd_flags, + u16 token, + u8 irq_index, + u32 status) { struct mc_command cmd = { 0 }; /* prepare command */ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CLEAR_IRQ_STATUS, - MC_CMD_PRI_LOW, token); + cmd_flags, token); cmd.params[0] |= mc_enc(0, 32, status); cmd.params[0] |= mc_enc(32, 8, irq_index); @@ -284,16 +465,27 @@ int dpmcp_clear_irq_status(struct fsl_mc_io *mc_io, return mc_send_command(mc_io, &cmd); } +/** + * dpmcp_get_attributes - Retrieve DPMCP attributes. + * + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPMCP object + * @attr: Returned object's attributes + * + * Return: '0' on Success; Error code otherwise. + */ int dpmcp_get_attributes(struct fsl_mc_io *mc_io, - uint16_t token, - struct dpmcp_attr *attr) + u32 cmd_flags, + u16 token, + struct dpmcp_attr *attr) { struct mc_command cmd = { 0 }; int err; /* prepare command */ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_ATTR, - MC_CMD_PRI_LOW, token); + cmd_flags, token); /* send command to mc*/ err = mc_send_command(mc_io, &cmd); @@ -302,7 +494,7 @@ int dpmcp_get_attributes(struct fsl_mc_io *mc_io, /* retrieve response parameters */ attr->id = (int)mc_dec(cmd.params[0], 32, 32); - attr->version.major = (uint16_t)mc_dec(cmd.params[1], 0, 16); - attr->version.minor = (uint16_t)mc_dec(cmd.params[1], 16, 16); + attr->version.major = (u16)mc_dec(cmd.params[1], 0, 16); + attr->version.minor = (u16)mc_dec(cmd.params[1], 16, 16); return 0; } diff --git a/kernel/drivers/staging/fsl-mc/bus/dpmcp.h b/kernel/drivers/staging/fsl-mc/bus/dpmcp.h index 5e7c21952..6df351f0c 100644 --- a/kernel/drivers/staging/fsl-mc/bus/dpmcp.h +++ b/kernel/drivers/staging/fsl-mc/bus/dpmcp.h @@ -38,41 +38,20 @@ struct fsl_mc_io; -/** - * dpmcp_open() - Open a control session for the specified object. - * @mc_io: Pointer to MC portal's I/O object - * @dpmcp_id: DPMCP unique ID - * @token: Returned token; use in subsequent API calls - * - * This function can be used to open a control session for an - * already created object; an object may have been declared in - * the DPL or by calling the dpmcp_create function. - * This function returns a unique authentication token, - * associated with the specific object ID and the specific MC - * portal; this token must be used in all subsequent commands for - * this specific object - * - * Return: '0' on Success; Error code otherwise. - */ -int dpmcp_open(struct fsl_mc_io *mc_io, int dpmcp_id, uint16_t *token); +int dpmcp_open(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + int dpmcp_id, + uint16_t *token); /* Get portal ID from pool */ #define DPMCP_GET_PORTAL_ID_FROM_POOL (-1) -/** - * dpmcp_close() - Close the control session of the object - * @mc_io: Pointer to MC portal's I/O object - * @token: Token of DPMCP object - * - * After this function is called, no further operations are - * allowed on the object without opening a new control session. - * - * Return: '0' on Success; Error code otherwise. - */ -int dpmcp_close(struct fsl_mc_io *mc_io, uint16_t token); +int dpmcp_close(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + uint16_t token); /** - * struct dpmcp_cfg() - Structure representing DPMCP configuration + * struct dpmcp_cfg - Structure representing DPMCP configuration * @portal_id: Portal ID; 'DPMCP_GET_PORTAL_ID_FROM_POOL' to get the portal ID * from pool */ @@ -80,199 +59,82 @@ struct dpmcp_cfg { int portal_id; }; -/** - * dpmcp_create() - Create the DPMCP object. - * @mc_io: Pointer to MC portal's I/O object - * @cfg: Configuration structure - * @token: Returned token; use in subsequent API calls - * - * Create the DPMCP object, allocate required resources and - * perform required initialization. - * - * The object can be created either by declaring it in the - * DPL file, or by calling this function. - * This function returns a unique authentication token, - * associated with the specific object ID and the specific MC - * portal; this token must be used in all subsequent calls to - * this specific object. For objects that are created using the - * DPL file, call dpmcp_open function to get an authentication - * token first. - * - * Return: '0' on Success; Error code otherwise. - */ int dpmcp_create(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, const struct dpmcp_cfg *cfg, uint16_t *token); -/** - * dpmcp_destroy() - Destroy the DPMCP object and release all its resources. - * @mc_io: Pointer to MC portal's I/O object - * @token: Token of DPMCP object - * - * Return: '0' on Success; error code otherwise. - */ -int dpmcp_destroy(struct fsl_mc_io *mc_io, uint16_t token); +int dpmcp_destroy(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + uint16_t token); -/** - * dpmcp_reset() - Reset the DPMCP, returns the object to initial state. - * @mc_io: Pointer to MC portal's I/O object - * @token: Token of DPMCP object - * - * Return: '0' on Success; Error code otherwise. - */ -int dpmcp_reset(struct fsl_mc_io *mc_io, uint16_t token); +int dpmcp_reset(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + uint16_t token); /* IRQ */ -/*! - * @name dpmcp IRQ Index and Events - */ +/* IRQ Index */ #define DPMCP_IRQ_INDEX 0 -/*!< Irq index */ +/* irq event - Indicates that the link state changed */ #define DPMCP_IRQ_EVENT_CMD_DONE 0x00000001 -/*!< irq event - Indicates that the link state changed */ -/* @} */ /** - * dpmcp_set_irq() - Set IRQ information for the DPMCP to trigger an interrupt. - * @mc_io: Pointer to MC portal's I/O object - * @token: Token of DPMCP object - * @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 + * struct dpmcp_irq_cfg - IRQ configuration + * @paddr: Address that must be written to signal a message-based interrupt + * @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. */ +struct dpmcp_irq_cfg { + uint64_t paddr; + uint32_t val; + int user_irq_id; +}; + int dpmcp_set_irq(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, uint16_t token, uint8_t irq_index, - uint64_t irq_addr, - uint32_t irq_val, - int user_irq_id); + struct dpmcp_irq_cfg *irq_cfg); -/** - * dpmcp_get_irq() - Get IRQ information from the DPMCP. - * @mc_io: Pointer to MC portal's I/O object - * @token: Token of DPMCP object - * @irq_index: The interrupt index to configure - * @type: 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 dpmcp_get_irq(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, uint16_t token, uint8_t irq_index, int *type, - uint64_t *irq_addr, - uint32_t *irq_val, - int *user_irq_id); + struct dpmcp_irq_cfg *irq_cfg); -/** - * dpmcp_set_irq_enable() - Set overall interrupt state. - * @mc_io: Pointer to MC portal's I/O object - * @token: Token of DPMCP object - * @irq_index: The interrupt index to configure - * @en: Interrupt state - enable = 1, disable = 0 - * - * Allows GPP software to control when interrupts are generated. - * Each interrupt can have up to 32 causes. The enable/disable control's the - * overall interrupt state. if the interrupt is disabled no causes will cause - * an interrupt. - * - * Return: '0' on Success; Error code otherwise. - */ int dpmcp_set_irq_enable(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, uint16_t token, uint8_t irq_index, uint8_t en); -/** - * dpmcp_get_irq_enable() - Get overall interrupt state - * @mc_io: Pointer to MC portal's I/O object - * @token: Token of DPMCP object - * @irq_index: The interrupt index to configure - * @en: Returned interrupt state - enable = 1, disable = 0 - * - * Return: '0' on Success; Error code otherwise. - */ int dpmcp_get_irq_enable(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, uint16_t token, uint8_t irq_index, uint8_t *en); -/** - * dpmcp_set_irq_mask() - Set interrupt mask. - * @mc_io: Pointer to MC portal's I/O object - * @token: Token of DPMCP object - * @irq_index: The interrupt index to configure - * @mask: Event mask to trigger interrupt; - * each bit: - * 0 = ignore event - * 1 = consider event for asserting IRQ - * - * Every interrupt can have up to 32 causes and the interrupt model supports - * masking/unmasking each cause independently - * - * Return: '0' on Success; Error code otherwise. - */ int dpmcp_set_irq_mask(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, uint16_t token, uint8_t irq_index, uint32_t mask); -/** - * dpmcp_get_irq_mask() - Get interrupt mask. - * @mc_io: Pointer to MC portal's I/O object - * @token: Token of DPMCP object - * @irq_index: The interrupt index to configure - * @mask: Returned event mask to trigger interrupt - * - * Every interrupt can have up to 32 causes and the interrupt model supports - * masking/unmasking each cause independently - * - * Return: '0' on Success; Error code otherwise. - */ int dpmcp_get_irq_mask(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, uint16_t token, uint8_t irq_index, uint32_t *mask); -/** - * dpmcp_get_irq_status() - Get the current status of any pending interrupts. - * - * @mc_io: Pointer to MC portal's I/O object - * @token: Token of DPMCP object - * @irq_index: The interrupt index to configure - * @status: Returned interrupts status - one bit per cause: - * 0 = no interrupt pending - * 1 = interrupt pending - * - * Return: '0' on Success; Error code otherwise. - */ int dpmcp_get_irq_status(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, uint16_t token, uint8_t irq_index, uint32_t *status); -/** - * dpmcp_clear_irq_status() - Clear a pending interrupt's status - * - * @mc_io: Pointer to MC portal's I/O object - * @token: Token of DPMCP object - * @irq_index: The interrupt index to configure - * @status: Bits to clear (W1C) - one bit per cause: - * 0 = don't change - * 1 = clear status bit - * - * Return: '0' on Success; Error code otherwise. - */ int dpmcp_clear_irq_status(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, uint16_t token, uint8_t irq_index, uint32_t status); @@ -295,16 +157,8 @@ struct dpmcp_attr { } version; }; -/** - * dpmcp_get_attributes - Retrieve DPMCP attributes. - * - * @mc_io: Pointer to MC portal's I/O object - * @token: Token of DPMCP object - * @attr: Returned object's attributes - * - * Return: '0' on Success; Error code otherwise. - */ int dpmcp_get_attributes(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, uint16_t token, struct dpmcp_attr *attr); diff --git a/kernel/drivers/staging/fsl-mc/bus/dpmng.c b/kernel/drivers/staging/fsl-mc/bus/dpmng.c index 58328e811..f633fcd86 100644 --- a/kernel/drivers/staging/fsl-mc/bus/dpmng.c +++ b/kernel/drivers/staging/fsl-mc/bus/dpmng.c @@ -34,14 +34,26 @@ #include "../include/dpmng.h" #include "dpmng-cmd.h" -int mc_get_version(struct fsl_mc_io *mc_io, struct mc_version *mc_ver_info) +/** + * mc_get_version() - Retrieves the Management Complex firmware + * version information + * @mc_io: Pointer to opaque I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @mc_ver_info: Returned version information structure + * + * Return: '0' on Success; Error code otherwise. + */ +int mc_get_version(struct fsl_mc_io *mc_io, + u32 cmd_flags, + struct mc_version *mc_ver_info) { struct mc_command cmd = { 0 }; int err; /* prepare command */ cmd.header = mc_encode_cmd_header(DPMNG_CMDID_GET_VERSION, - MC_CMD_PRI_LOW, 0); + cmd_flags, + 0); /* send command to mc*/ err = mc_send_command(mc_io, &cmd); @@ -56,14 +68,25 @@ int mc_get_version(struct fsl_mc_io *mc_io, struct mc_version *mc_ver_info) return 0; } -int dpmng_get_container_id(struct fsl_mc_io *mc_io, int *container_id) +/** + * dpmng_get_container_id() - Get container ID associated with a given portal. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @container_id: Requested container ID + * + * Return: '0' on Success; Error code otherwise. + */ +int dpmng_get_container_id(struct fsl_mc_io *mc_io, + u32 cmd_flags, + int *container_id) { struct mc_command cmd = { 0 }; int err; /* prepare command */ cmd.header = mc_encode_cmd_header(DPMNG_CMDID_GET_CONT_ID, - MC_CMD_PRI_LOW, 0); + cmd_flags, + 0); /* send command to mc*/ err = mc_send_command(mc_io, &cmd); diff --git a/kernel/drivers/staging/fsl-mc/bus/dprc-cmd.h b/kernel/drivers/staging/fsl-mc/bus/dprc-cmd.h index 09202489c..6552c2034 100644 --- a/kernel/drivers/staging/fsl-mc/bus/dprc-cmd.h +++ b/kernel/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,15 @@ #define DPRC_CMDID_GET_RES_COUNT 0x15B #define DPRC_CMDID_GET_RES_IDS 0x15C #define DPRC_CMDID_GET_OBJ_REG 0x15E +#define DPRC_CMDID_SET_OBJ_IRQ 0x15F +#define DPRC_CMDID_GET_OBJ_IRQ 0x160 +#define DPRC_CMDID_SET_OBJ_LABEL 0x161 +#define DPRC_CMDID_GET_OBJ_DESC 0x162 #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/kernel/drivers/staging/fsl-mc/bus/dprc-driver.c b/kernel/drivers/staging/fsl-mc/bus/dprc-driver.c index 35c06cff1..2c4cd70b4 100644 --- a/kernel/drivers/staging/fsl-mc/bus/dprc-driver.c +++ b/kernel/drivers/staging/fsl-mc/bus/dprc-driver.c @@ -126,7 +126,7 @@ static void check_plugged_state_change(struct fsl_mc_device *mc_dev, struct dprc_obj_desc *obj_desc) { int error; - uint32_t plugged_flag_at_mc = + u32 plugged_flag_at_mc = (obj_desc->state & DPRC_OBJ_STATE_PLUGGED); if (plugged_flag_at_mc != @@ -262,6 +262,7 @@ int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev) struct dprc_obj_desc *child_obj_desc_array = NULL; error = dprc_get_obj_count(mc_bus_dev->mc_io, + 0, mc_bus_dev->mc_handle, &num_child_objects); if (error < 0) { @@ -289,6 +290,7 @@ int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev) &child_obj_desc_array[i]; error = dprc_get_obj(mc_bus_dev->mc_io, + 0, mc_bus_dev->mc_handle, i, obj_desc); if (error < 0) { @@ -399,7 +401,7 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) return error; } - error = dprc_open(mc_dev->mc_io, mc_dev->obj_desc.id, + error = dprc_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id, &mc_dev->mc_handle); if (error < 0) { dev_err(&mc_dev->dev, "dprc_open() failed: %d\n", error); @@ -419,7 +421,7 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) return 0; error_cleanup_open: - (void)dprc_close(mc_dev->mc_io, mc_dev->mc_handle); + (void)dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle); error_cleanup_mc_io: fsl_destroy_mc_io(mc_dev->mc_io); @@ -447,7 +449,7 @@ static int dprc_remove(struct fsl_mc_device *mc_dev) device_for_each_child(&mc_dev->dev, NULL, __fsl_mc_device_remove); dprc_cleanup_all_resource_pools(mc_dev); - error = dprc_close(mc_dev->mc_io, mc_dev->mc_handle); + error = dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle); if (error < 0) dev_err(&mc_dev->dev, "dprc_close() failed: %d\n", error); @@ -480,7 +482,7 @@ int __init dprc_driver_init(void) return fsl_mc_driver_register(&dprc_driver); } -void __exit dprc_driver_exit(void) +void dprc_driver_exit(void) { fsl_mc_driver_unregister(&dprc_driver); } diff --git a/kernel/drivers/staging/fsl-mc/bus/dprc.c b/kernel/drivers/staging/fsl-mc/bus/dprc.c index 19b26e630..381b9a96a 100644 --- a/kernel/drivers/staging/fsl-mc/bus/dprc.c +++ b/kernel/drivers/staging/fsl-mc/bus/dprc.c @@ -34,13 +34,27 @@ #include "../include/dprc.h" #include "dprc-cmd.h" -int dprc_open(struct fsl_mc_io *mc_io, int container_id, uint16_t *token) +/** + * dprc_open() - Open DPRC object for use + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @container_id: Container ID to open + * @token: Returned token of DPRC object + * + * Return: '0' on Success; Error code otherwise. + * + * @warning Required before any operation on the object. + */ +int dprc_open(struct fsl_mc_io *mc_io, + u32 cmd_flags, + int container_id, + u16 *token) { struct mc_command cmd = { 0 }; int err; /* prepare command */ - cmd.header = mc_encode_cmd_header(DPRC_CMDID_OPEN, MC_CMD_PRI_LOW, + cmd.header = mc_encode_cmd_header(DPRC_CMDID_OPEN, cmd_flags, 0); cmd.params[0] |= mc_enc(0, 32, container_id); @@ -56,12 +70,25 @@ int dprc_open(struct fsl_mc_io *mc_io, int container_id, uint16_t *token) } EXPORT_SYMBOL(dprc_open); -int dprc_close(struct fsl_mc_io *mc_io, uint16_t token) +/** + * dprc_close() - Close the control session of the object + * @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 + * + * After this function is called, no further operations are + * allowed on the object without opening a new control session. + * + * Return: '0' on Success; Error code otherwise. + */ +int dprc_close(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token) { struct mc_command cmd = { 0 }; /* prepare command */ - cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLOSE, MC_CMD_PRI_HIGH, + cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLOSE, cmd_flags, token); /* send command to mc*/ @@ -69,11 +96,23 @@ int dprc_close(struct fsl_mc_io *mc_io, uint16_t token) } EXPORT_SYMBOL(dprc_close); +/** + * dprc_create_container() - Create 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 + * @cfg: Child container configuration + * @child_container_id: Returned child container ID + * @child_portal_offset: Returned child portal offset from MC portal base + * + * Return: '0' on Success; Error code otherwise. + */ int dprc_create_container(struct fsl_mc_io *mc_io, - uint16_t token, + u32 cmd_flags, + u16 token, struct dprc_cfg *cfg, int *child_container_id, - uint64_t *child_portal_paddr) + u64 *child_portal_offset) { struct mc_command cmd = { 0 }; int err; @@ -82,9 +121,25 @@ 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); + cmd_flags, token); /* send command to mc*/ err = mc_send_command(mc_io, &cmd); @@ -93,55 +148,112 @@ 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; } +/** + * dprc_destroy_container() - Destroy 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 destroy + * + * This function terminates the child container, so following this call the + * child container ID becomes invalid. + * + * Notes: + * - All resources and objects of the destroyed container are returned to the + * parent container or destroyed if were created be the destroyed container. + * - This function destroy all the child containers of the specified + * container prior to destroying the container itself. + * + * warning: Only the parent container is allowed to destroy a child policy + * Container 0 can't be destroyed + * + * Return: '0' on Success; Error code otherwise. + * + */ int dprc_destroy_container(struct fsl_mc_io *mc_io, - uint16_t token, + u32 cmd_flags, + u16 token, int child_container_id) { struct mc_command cmd = { 0 }; /* prepare command */ cmd.header = mc_encode_cmd_header(DPRC_CMDID_DESTROY_CONT, - MC_CMD_PRI_LOW, token); + cmd_flags, token); cmd.params[0] |= mc_enc(0, 32, child_container_id); /* send command to mc*/ return mc_send_command(mc_io, &cmd); } +/** + * 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, - uint16_t token, + u32 cmd_flags, + u16 token, int child_container_id) { struct mc_command cmd = { 0 }; /* prepare command */ cmd.header = mc_encode_cmd_header(DPRC_CMDID_RESET_CONT, - MC_CMD_PRI_LOW, token); + cmd_flags, token); cmd.params[0] |= mc_enc(0, 32, child_container_id); /* send command to mc*/ return mc_send_command(mc_io, &cmd); } +/** + * dprc_get_irq() - Get IRQ information from the DPRC. + * @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 + * @irq_index: The interrupt index to configure + * @type: Interrupt type: 0 represents message interrupt + * type (both irq_addr and irq_val are valid) + * @irq_cfg: IRQ attributes + * + * Return: '0' on Success; Error code otherwise. + */ int dprc_get_irq(struct fsl_mc_io *mc_io, - uint16_t token, - uint8_t irq_index, + u32 cmd_flags, + u16 token, + u8 irq_index, int *type, - uint64_t *irq_paddr, - uint32_t *irq_val, - int *user_irq_id) + struct dprc_irq_cfg *irq_cfg) { struct mc_command cmd = { 0 }; int err; /* prepare command */ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ, - MC_CMD_PRI_LOW, + cmd_flags, token); cmd.params[0] |= mc_enc(32, 8, irq_index); @@ -151,47 +263,67 @@ int dprc_get_irq(struct fsl_mc_io *mc_io, return err; /* retrieve response parameters */ - *irq_val = mc_dec(cmd.params[0], 0, 32); - *irq_paddr = mc_dec(cmd.params[1], 0, 64); - *user_irq_id = mc_dec(cmd.params[2], 0, 32); + irq_cfg->val = mc_dec(cmd.params[0], 0, 32); + irq_cfg->paddr = mc_dec(cmd.params[1], 0, 64); + irq_cfg->user_irq_id = mc_dec(cmd.params[2], 0, 32); *type = mc_dec(cmd.params[2], 32, 32); return 0; } +/** + * dprc_set_irq() - Set IRQ information for the DPRC to trigger an interrupt. + * @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 + * @irq_index: Identifies the interrupt index to configure + * @irq_cfg: IRQ configuration + * + * Return: '0' on Success; Error code otherwise. + */ int dprc_set_irq(struct fsl_mc_io *mc_io, - uint16_t token, - uint8_t irq_index, - uint64_t irq_paddr, - uint32_t irq_val, - int user_irq_id) + u32 cmd_flags, + u16 token, + u8 irq_index, + struct dprc_irq_cfg *irq_cfg) { struct mc_command cmd = { 0 }; /* prepare command */ cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ, - MC_CMD_PRI_LOW, + cmd_flags, 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_paddr); - cmd.params[2] |= mc_enc(0, 32, user_irq_id); + cmd.params[0] |= mc_enc(0, 32, irq_cfg->val); + cmd.params[1] |= mc_enc(0, 64, irq_cfg->paddr); + cmd.params[2] |= mc_enc(0, 32, irq_cfg->user_irq_id); /* send command to mc*/ return mc_send_command(mc_io, &cmd); } +/** + * dprc_get_irq_enable() - Get overall interrupt state. + * @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 + * @irq_index: The interrupt index to configure + * @en: Returned interrupt state - enable = 1, disable = 0 + * + * Return: '0' on Success; Error code otherwise. + */ int dprc_get_irq_enable(struct fsl_mc_io *mc_io, - uint16_t token, - uint8_t irq_index, - uint8_t *en) + u32 cmd_flags, + u16 token, + u8 irq_index, + u8 *en) { struct mc_command cmd = { 0 }; int err; /* prepare command */ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_ENABLE, - MC_CMD_PRI_LOW, token); + cmd_flags, token); cmd.params[0] |= mc_enc(32, 8, irq_index); /* send command to mc*/ @@ -205,16 +337,32 @@ int dprc_get_irq_enable(struct fsl_mc_io *mc_io, return 0; } +/** + * dprc_set_irq_enable() - Set overall interrupt state. + * @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 + * @irq_index: The interrupt index to configure + * @en: Interrupt state - enable = 1, disable = 0 + * + * Allows GPP software to control when interrupts are generated. + * Each interrupt can have up to 32 causes. The enable/disable control's the + * overall interrupt state. if the interrupt is disabled no causes will cause + * an interrupt. + * + * Return: '0' on Success; Error code otherwise. + */ int dprc_set_irq_enable(struct fsl_mc_io *mc_io, - uint16_t token, - uint8_t irq_index, - uint8_t en) + u32 cmd_flags, + u16 token, + u8 irq_index, + u8 en) { struct mc_command cmd = { 0 }; /* prepare command */ cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_ENABLE, - MC_CMD_PRI_LOW, token); + cmd_flags, token); cmd.params[0] |= mc_enc(0, 8, en); cmd.params[0] |= mc_enc(32, 8, irq_index); @@ -222,17 +370,31 @@ int dprc_set_irq_enable(struct fsl_mc_io *mc_io, return mc_send_command(mc_io, &cmd); } +/** + * dprc_get_irq_mask() - Get interrupt mask. + * @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 + * @irq_index: The interrupt index to configure + * @mask: Returned event mask to trigger interrupt + * + * Every interrupt can have up to 32 causes and the interrupt model supports + * masking/unmasking each cause independently + * + * Return: '0' on Success; Error code otherwise. + */ int dprc_get_irq_mask(struct fsl_mc_io *mc_io, - uint16_t token, - uint8_t irq_index, - uint32_t *mask) + u32 cmd_flags, + u16 token, + u8 irq_index, + u32 *mask) { struct mc_command cmd = { 0 }; int err; /* prepare command */ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_MASK, - MC_CMD_PRI_LOW, token); + cmd_flags, token); cmd.params[0] |= mc_enc(32, 8, irq_index); /* send command to mc*/ @@ -246,16 +408,33 @@ int dprc_get_irq_mask(struct fsl_mc_io *mc_io, return 0; } +/** + * dprc_set_irq_mask() - Set interrupt mask. + * @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 + * @irq_index: The interrupt index to configure + * @mask: event mask to trigger interrupt; + * each bit: + * 0 = ignore event + * 1 = consider event for asserting irq + * + * Every interrupt can have up to 32 causes and the interrupt model supports + * masking/unmasking each cause independently + * + * Return: '0' on Success; Error code otherwise. + */ int dprc_set_irq_mask(struct fsl_mc_io *mc_io, - uint16_t token, - uint8_t irq_index, - uint32_t mask) + u32 cmd_flags, + u16 token, + u8 irq_index, + u32 mask) { struct mc_command cmd = { 0 }; /* prepare command */ cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_MASK, - MC_CMD_PRI_LOW, token); + cmd_flags, token); cmd.params[0] |= mc_enc(0, 32, mask); cmd.params[0] |= mc_enc(32, 8, irq_index); @@ -263,17 +442,30 @@ int dprc_set_irq_mask(struct fsl_mc_io *mc_io, return mc_send_command(mc_io, &cmd); } +/** + * dprc_get_irq_status() - Get the current status of any pending interrupts. + * @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 + * @irq_index: The interrupt index to configure + * @status: Returned interrupts status - one bit per cause: + * 0 = no interrupt pending + * 1 = interrupt pending + * + * Return: '0' on Success; Error code otherwise. + */ int dprc_get_irq_status(struct fsl_mc_io *mc_io, - uint16_t token, - uint8_t irq_index, - uint32_t *status) + u32 cmd_flags, + u16 token, + u8 irq_index, + u32 *status) { struct mc_command cmd = { 0 }; int err; /* prepare command */ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_STATUS, - MC_CMD_PRI_LOW, token); + cmd_flags, token); cmd.params[0] |= mc_enc(32, 8, irq_index); /* send command to mc*/ @@ -287,16 +479,29 @@ int dprc_get_irq_status(struct fsl_mc_io *mc_io, return 0; } +/** + * dprc_clear_irq_status() - Clear a pending interrupt's status + * @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 + * @irq_index: The interrupt index to configure + * @status: bits to clear (W1C) - one bit per cause: + * 0 = don't change + * 1 = clear status bit + * + * Return: '0' on Success; Error code otherwise. + */ int dprc_clear_irq_status(struct fsl_mc_io *mc_io, - uint16_t token, - uint8_t irq_index, - uint32_t status) + u32 cmd_flags, + u16 token, + u8 irq_index, + u32 status) { struct mc_command cmd = { 0 }; /* prepare command */ cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLEAR_IRQ_STATUS, - MC_CMD_PRI_LOW, token); + cmd_flags, token); cmd.params[0] |= mc_enc(0, 32, status); cmd.params[0] |= mc_enc(32, 8, irq_index); @@ -304,8 +509,18 @@ int dprc_clear_irq_status(struct fsl_mc_io *mc_io, return mc_send_command(mc_io, &cmd); } +/** + * dprc_get_attributes() - Obtains container attributes + * @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 + * @attributes Returned container attributes + * + * Return: '0' on Success; Error code otherwise. + */ int dprc_get_attributes(struct fsl_mc_io *mc_io, - uint16_t token, + u32 cmd_flags, + u16 token, struct dprc_attributes *attr) { struct mc_command cmd = { 0 }; @@ -313,7 +528,7 @@ int dprc_get_attributes(struct fsl_mc_io *mc_io, /* prepare command */ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_ATTR, - MC_CMD_PRI_LOW, + cmd_flags, token); /* send command to mc*/ @@ -332,17 +547,43 @@ int dprc_get_attributes(struct fsl_mc_io *mc_io, return 0; } +/** + * dprc_set_res_quota() - Set allocation policy for a specific resource/object + * type in a 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 child container + * @type: Resource/object type + * @quota: Sets the maximum number of resources of the selected type + * that the child container is allowed to allocate from its parent; + * when quota is set to -1, the policy is the same as container's + * general policy. + * + * Allocation policy determines whether or not a container may allocate + * resources from its parent. Each container has a 'global' allocation policy + * that is set when the container is created. + * + * This function sets allocation policy for a specific resource type. + * The default policy for all resource types matches the container's 'global' + * allocation policy. + * + * Return: '0' on Success; Error code otherwise. + * + * @warning Only the parent container is allowed to change a child policy. + */ int dprc_set_res_quota(struct fsl_mc_io *mc_io, - uint16_t token, + u32 cmd_flags, + u16 token, int child_container_id, char *type, - uint16_t quota) + u16 quota) { struct mc_command cmd = { 0 }; /* prepare command */ cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_RES_QUOTA, - MC_CMD_PRI_LOW, token); + cmd_flags, token); cmd.params[0] |= mc_enc(0, 32, child_container_id); cmd.params[0] |= mc_enc(32, 16, quota); cmd.params[1] |= mc_enc(0, 8, type[0]); @@ -366,18 +607,34 @@ int dprc_set_res_quota(struct fsl_mc_io *mc_io, return mc_send_command(mc_io, &cmd); } +/** + * dprc_get_res_quota() - Gets the allocation policy of a specific + * resource/object type in a 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 child container + * @type: resource/object type + * @quota: Returnes the maximum number of resources of the selected type + * that the child container is allowed to allocate from the parent; + * when quota is set to -1, the policy is the same as container's + * general policy. + * + * Return: '0' on Success; Error code otherwise. + */ int dprc_get_res_quota(struct fsl_mc_io *mc_io, - uint16_t token, + u32 cmd_flags, + u16 token, int child_container_id, char *type, - uint16_t *quota) + u16 *quota) { struct mc_command cmd = { 0 }; int err; /* prepare command */ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_QUOTA, - MC_CMD_PRI_LOW, token); + cmd_flags, token); cmd.params[0] |= mc_enc(0, 32, child_container_id); cmd.params[1] |= mc_enc(0, 8, type[0]); cmd.params[1] |= mc_enc(8, 8, type[1]); @@ -407,8 +664,41 @@ int dprc_get_res_quota(struct fsl_mc_io *mc_io, return 0; } +/** + * dprc_assign() - Assigns objects or resource to a 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 + * @container_id: ID of the child container + * @res_req: Describes the type and amount of resources to + * assign to the given container + * + * Assignment is usually done by a parent (this DPRC) to one of its child + * containers. + * + * According to the DPRC allocation policy, the assigned resources may be taken + * (allocated) from the container's ancestors, if not enough resources are + * available in the container itself. + * + * The type of assignment depends on the dprc_res_req options, as follows: + * - DPRC_RES_REQ_OPT_EXPLICIT: indicates that assigned resources should have + * the explicit base ID specified at the id_base_align field of res_req. + * - DPRC_RES_REQ_OPT_ALIGNED: indicates that the assigned resources should be + * aligned to the value given at id_base_align field of res_req. + * - DPRC_RES_REQ_OPT_PLUGGED: Relevant only for object assignment, + * and indicates that the object must be set to the plugged state. + * + * A container may use this function with its own ID in order to change a + * object state to plugged or unplugged. + * + * If IRQ information has been set in the child DPRC, it will signal an + * interrupt following every change in its object assignment. + * + * Return: '0' on Success; Error code otherwise. + */ int dprc_assign(struct fsl_mc_io *mc_io, - uint16_t token, + u32 cmd_flags, + u16 token, int container_id, struct dprc_res_req *res_req) { @@ -416,7 +706,7 @@ int dprc_assign(struct fsl_mc_io *mc_io, /* prepare command */ cmd.header = mc_encode_cmd_header(DPRC_CMDID_ASSIGN, - MC_CMD_PRI_LOW, token); + cmd_flags, token); cmd.params[0] |= mc_enc(0, 32, container_id); cmd.params[0] |= mc_enc(32, 32, res_req->options); cmd.params[1] |= mc_enc(0, 32, res_req->num); @@ -442,8 +732,24 @@ int dprc_assign(struct fsl_mc_io *mc_io, return mc_send_command(mc_io, &cmd); } +/** + * dprc_unassign() - Un-assigns objects or resources from a child container + * and moves them into this (parent) DPRC. + * @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 child container + * @res_req: Describes the type and amount of resources to un-assign from + * the child container + * + * Un-assignment of objects can succeed only if the object is not in the + * plugged or opened state. + * + * Return: '0' on Success; Error code otherwise. + */ int dprc_unassign(struct fsl_mc_io *mc_io, - uint16_t token, + u32 cmd_flags, + u16 token, int child_container_id, struct dprc_res_req *res_req) { @@ -451,7 +757,7 @@ int dprc_unassign(struct fsl_mc_io *mc_io, /* prepare command */ cmd.header = mc_encode_cmd_header(DPRC_CMDID_UNASSIGN, - MC_CMD_PRI_LOW, + cmd_flags, token); cmd.params[0] |= mc_enc(0, 32, child_container_id); cmd.params[0] |= mc_enc(32, 32, res_req->options); @@ -478,8 +784,18 @@ int dprc_unassign(struct fsl_mc_io *mc_io, return mc_send_command(mc_io, &cmd); } +/** + * dprc_get_pool_count() - Get the number of dprc's pools + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPRC object + * @pool_count: Returned number of resource pools in the dprc + * + * Return: '0' on Success; Error code otherwise. + */ int dprc_get_pool_count(struct fsl_mc_io *mc_io, - uint16_t token, + u32 cmd_flags, + u16 token, int *pool_count) { struct mc_command cmd = { 0 }; @@ -487,7 +803,7 @@ int dprc_get_pool_count(struct fsl_mc_io *mc_io, /* prepare command */ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_POOL_COUNT, - MC_CMD_PRI_LOW, token); + cmd_flags, token); /* send command to mc*/ err = mc_send_command(mc_io, &cmd); @@ -500,8 +816,24 @@ int dprc_get_pool_count(struct fsl_mc_io *mc_io, return 0; } +/** + * dprc_get_pool() - Get the type (string) of a certain dprc's pool + * @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 + * @pool_index; Index of the pool to be queried (< pool_count) + * @type: The type of the pool + * + * The pool types retrieved one by one by incrementing + * pool_index up to (not including) the value of pool_count returned + * from dprc_get_pool_count(). dprc_get_pool_count() must + * be called prior to dprc_get_pool(). + * + * Return: '0' on Success; Error code otherwise. + */ int dprc_get_pool(struct fsl_mc_io *mc_io, - uint16_t token, + u32 cmd_flags, + u16 token, int pool_index, char *type) { @@ -510,7 +842,7 @@ int dprc_get_pool(struct fsl_mc_io *mc_io, /* prepare command */ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_POOL, - MC_CMD_PRI_LOW, + cmd_flags, token); cmd.params[0] |= mc_enc(0, 32, pool_index); @@ -540,14 +872,26 @@ int dprc_get_pool(struct fsl_mc_io *mc_io, return 0; } -int dprc_get_obj_count(struct fsl_mc_io *mc_io, uint16_t token, int *obj_count) +/** + * dprc_get_obj_count() - Obtains the number of objects in the DPRC + * @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 + * @obj_count: Number of objects assigned to the DPRC + * + * Return: '0' on Success; Error code otherwise. + */ +int dprc_get_obj_count(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + int *obj_count) { struct mc_command cmd = { 0 }; int err; /* prepare command */ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_COUNT, - MC_CMD_PRI_LOW, token); + cmd_flags, token); /* send command to mc*/ err = mc_send_command(mc_io, &cmd); @@ -561,8 +905,24 @@ int dprc_get_obj_count(struct fsl_mc_io *mc_io, uint16_t token, int *obj_count) } EXPORT_SYMBOL(dprc_get_obj_count); +/** + * dprc_get_obj() - Get general information on an object + * @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 + * @obj_index: Index of the object to be queried (< obj_count) + * @obj_desc: Returns the requested object descriptor + * + * The object descriptors are retrieved one by one by incrementing + * obj_index up to (not including) the value of obj_count returned + * from dprc_get_obj_count(). dprc_get_obj_count() must + * be called prior to dprc_get_obj(). + * + * Return: '0' on Success; Error code otherwise. + */ int dprc_get_obj(struct fsl_mc_io *mc_io, - uint16_t token, + u32 cmd_flags, + u16 token, int obj_index, struct dprc_obj_desc *obj_desc) { @@ -571,7 +931,7 @@ int dprc_get_obj(struct fsl_mc_io *mc_io, /* prepare command */ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ, - MC_CMD_PRI_LOW, + cmd_flags, token); cmd.params[0] |= mc_enc(0, 32, obj_index); @@ -604,13 +964,253 @@ 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); +/** + * dprc_get_obj_desc() - Get object descriptor. + * + * @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 + * @obj_type: The type of the object to get its descriptor. + * @obj_id: The id of the object to get its descriptor + * @obj_desc: The returned descriptor to fill and return to the user + * + * Return: '0' on Success; Error code otherwise. + * + */ +int dprc_get_obj_desc(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + char *obj_type, + int obj_id, + struct dprc_obj_desc *obj_desc) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_DESC, + cmd_flags, + token); + cmd.params[0] |= mc_enc(0, 32, obj_id); + cmd.params[1] |= mc_enc(0, 8, obj_type[0]); + cmd.params[1] |= mc_enc(8, 8, obj_type[1]); + cmd.params[1] |= mc_enc(16, 8, obj_type[2]); + cmd.params[1] |= mc_enc(24, 8, obj_type[3]); + cmd.params[1] |= mc_enc(32, 8, obj_type[4]); + cmd.params[1] |= mc_enc(40, 8, obj_type[5]); + cmd.params[1] |= mc_enc(48, 8, obj_type[6]); + cmd.params[1] |= mc_enc(56, 8, obj_type[7]); + cmd.params[2] |= mc_enc(0, 8, obj_type[8]); + cmd.params[2] |= mc_enc(8, 8, obj_type[9]); + cmd.params[2] |= mc_enc(16, 8, obj_type[10]); + cmd.params[2] |= mc_enc(24, 8, obj_type[11]); + cmd.params[2] |= mc_enc(32, 8, obj_type[12]); + cmd.params[2] |= mc_enc(40, 8, obj_type[13]); + cmd.params[2] |= mc_enc(48, 8, obj_type[14]); + cmd.params[2] |= mc_enc(56, 8, obj_type[15]); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + obj_desc->id = (int)mc_dec(cmd.params[0], 32, 32); + obj_desc->vendor = (u16)mc_dec(cmd.params[1], 0, 16); + obj_desc->vendor = (u8)mc_dec(cmd.params[1], 16, 8); + obj_desc->region_count = (u8)mc_dec(cmd.params[1], 24, 8); + obj_desc->state = (u32)mc_dec(cmd.params[1], 32, 32); + obj_desc->ver_major = (u16)mc_dec(cmd.params[2], 0, 16); + obj_desc->ver_minor = (u16)mc_dec(cmd.params[2], 16, 16); + obj_desc->type[0] = (char)mc_dec(cmd.params[3], 0, 8); + obj_desc->type[1] = (char)mc_dec(cmd.params[3], 8, 8); + obj_desc->type[2] = (char)mc_dec(cmd.params[3], 16, 8); + obj_desc->type[3] = (char)mc_dec(cmd.params[3], 24, 8); + obj_desc->type[4] = (char)mc_dec(cmd.params[3], 32, 8); + obj_desc->type[5] = (char)mc_dec(cmd.params[3], 40, 8); + obj_desc->type[6] = (char)mc_dec(cmd.params[3], 48, 8); + obj_desc->type[7] = (char)mc_dec(cmd.params[3], 56, 8); + obj_desc->type[8] = (char)mc_dec(cmd.params[4], 0, 8); + obj_desc->type[9] = (char)mc_dec(cmd.params[4], 8, 8); + obj_desc->type[10] = (char)mc_dec(cmd.params[4], 16, 8); + obj_desc->type[11] = (char)mc_dec(cmd.params[4], 24, 8); + obj_desc->type[12] = (char)mc_dec(cmd.params[4], 32, 8); + obj_desc->type[13] = (char)mc_dec(cmd.params[4], 40, 8); + obj_desc->type[14] = (char)mc_dec(cmd.params[4], 48, 8); + obj_desc->type[15] = (char)mc_dec(cmd.params[4], 56, 8); + obj_desc->label[0] = (char)mc_dec(cmd.params[5], 0, 8); + obj_desc->label[1] = (char)mc_dec(cmd.params[5], 8, 8); + obj_desc->label[2] = (char)mc_dec(cmd.params[5], 16, 8); + obj_desc->label[3] = (char)mc_dec(cmd.params[5], 24, 8); + obj_desc->label[4] = (char)mc_dec(cmd.params[5], 32, 8); + obj_desc->label[5] = (char)mc_dec(cmd.params[5], 40, 8); + obj_desc->label[6] = (char)mc_dec(cmd.params[5], 48, 8); + obj_desc->label[7] = (char)mc_dec(cmd.params[5], 56, 8); + obj_desc->label[8] = (char)mc_dec(cmd.params[6], 0, 8); + obj_desc->label[9] = (char)mc_dec(cmd.params[6], 8, 8); + obj_desc->label[10] = (char)mc_dec(cmd.params[6], 16, 8); + obj_desc->label[11] = (char)mc_dec(cmd.params[6], 24, 8); + obj_desc->label[12] = (char)mc_dec(cmd.params[6], 32, 8); + obj_desc->label[13] = (char)mc_dec(cmd.params[6], 40, 8); + obj_desc->label[14] = (char)mc_dec(cmd.params[6], 48, 8); + obj_desc->label[15] = (char)mc_dec(cmd.params[6], 56, 8); + + return 0; +} +EXPORT_SYMBOL(dprc_get_obj_desc); + +/** + * dprc_set_obj_irq() - Set IRQ information for object to trigger an interrupt. + * @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 + * @obj_type: Type of the object to set its IRQ + * @obj_id: ID of the object to set its IRQ + * @irq_index: The interrupt index to configure + * @irq_cfg: IRQ configuration + * + * Return: '0' on Success; Error code otherwise. + */ +int dprc_set_obj_irq(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + char *obj_type, + int obj_id, + u8 irq_index, + struct dprc_irq_cfg *irq_cfg) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_OBJ_IRQ, + cmd_flags, + token); + cmd.params[0] |= mc_enc(32, 8, irq_index); + cmd.params[0] |= mc_enc(0, 32, irq_cfg->val); + cmd.params[1] |= mc_enc(0, 64, irq_cfg->paddr); + cmd.params[2] |= mc_enc(0, 32, irq_cfg->user_irq_id); + cmd.params[2] |= mc_enc(32, 32, obj_id); + cmd.params[3] |= mc_enc(0, 8, obj_type[0]); + cmd.params[3] |= mc_enc(8, 8, obj_type[1]); + cmd.params[3] |= mc_enc(16, 8, obj_type[2]); + cmd.params[3] |= mc_enc(24, 8, obj_type[3]); + cmd.params[3] |= mc_enc(32, 8, obj_type[4]); + cmd.params[3] |= mc_enc(40, 8, obj_type[5]); + cmd.params[3] |= mc_enc(48, 8, obj_type[6]); + cmd.params[3] |= mc_enc(56, 8, obj_type[7]); + cmd.params[4] |= mc_enc(0, 8, obj_type[8]); + cmd.params[4] |= mc_enc(8, 8, obj_type[9]); + cmd.params[4] |= mc_enc(16, 8, obj_type[10]); + cmd.params[4] |= mc_enc(24, 8, obj_type[11]); + cmd.params[4] |= mc_enc(32, 8, obj_type[12]); + cmd.params[4] |= mc_enc(40, 8, obj_type[13]); + cmd.params[4] |= mc_enc(48, 8, obj_type[14]); + cmd.params[4] |= mc_enc(56, 8, obj_type[15]); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} +EXPORT_SYMBOL(dprc_set_obj_irq); + +/** + * dprc_get_obj_irq() - Get IRQ information from object. + * @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 + * @obj_type: Type od the object to get its IRQ + * @obj_id: ID of the object to get its IRQ + * @irq_index: The interrupt index to configure + * @type: Interrupt type: 0 represents message interrupt + * type (both irq_addr and irq_val are valid) + * @irq_cfg: The returned IRQ attributes + * + * Return: '0' on Success; Error code otherwise. + */ +int dprc_get_obj_irq(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + char *obj_type, + int obj_id, + u8 irq_index, + int *type, + struct dprc_irq_cfg *irq_cfg) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_IRQ, + cmd_flags, + token); + cmd.params[0] |= mc_enc(0, 32, obj_id); + cmd.params[0] |= mc_enc(32, 8, irq_index); + cmd.params[1] |= mc_enc(0, 8, obj_type[0]); + cmd.params[1] |= mc_enc(8, 8, obj_type[1]); + cmd.params[1] |= mc_enc(16, 8, obj_type[2]); + cmd.params[1] |= mc_enc(24, 8, obj_type[3]); + cmd.params[1] |= mc_enc(32, 8, obj_type[4]); + cmd.params[1] |= mc_enc(40, 8, obj_type[5]); + cmd.params[1] |= mc_enc(48, 8, obj_type[6]); + cmd.params[1] |= mc_enc(56, 8, obj_type[7]); + cmd.params[2] |= mc_enc(0, 8, obj_type[8]); + cmd.params[2] |= mc_enc(8, 8, obj_type[9]); + cmd.params[2] |= mc_enc(16, 8, obj_type[10]); + cmd.params[2] |= mc_enc(24, 8, obj_type[11]); + cmd.params[2] |= mc_enc(32, 8, obj_type[12]); + cmd.params[2] |= mc_enc(40, 8, obj_type[13]); + cmd.params[2] |= mc_enc(48, 8, obj_type[14]); + cmd.params[2] |= mc_enc(56, 8, obj_type[15]); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + irq_cfg->val = (u32)mc_dec(cmd.params[0], 0, 32); + irq_cfg->paddr = (u64)mc_dec(cmd.params[1], 0, 64); + irq_cfg->user_irq_id = (int)mc_dec(cmd.params[2], 0, 32); + *type = (int)mc_dec(cmd.params[2], 32, 32); + + return 0; +} +EXPORT_SYMBOL(dprc_get_obj_irq); + +/** + * 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 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPRC object + * @type: pool type + * @res_count: Returned number of free resources of the given + * resource type that are assigned to this DPRC + * + * Return: '0' on Success; Error code otherwise. + */ int dprc_get_res_count(struct fsl_mc_io *mc_io, - uint16_t token, + u32 cmd_flags, + u16 token, char *type, int *res_count) { @@ -621,7 +1221,7 @@ int dprc_get_res_count(struct fsl_mc_io *mc_io, /* prepare command */ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_COUNT, - MC_CMD_PRI_LOW, token); + cmd_flags, token); cmd.params[1] |= mc_enc(0, 8, type[0]); cmd.params[1] |= mc_enc(8, 8, type[1]); cmd.params[1] |= mc_enc(16, 8, type[2]); @@ -651,8 +1251,19 @@ int dprc_get_res_count(struct fsl_mc_io *mc_io, } EXPORT_SYMBOL(dprc_get_res_count); +/** + * dprc_get_res_ids() - Obtains IDs of free resources in the 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 + * @type: pool type + * @range_desc: range descriptor + * + * Return: '0' on Success; Error code otherwise. + */ int dprc_get_res_ids(struct fsl_mc_io *mc_io, - uint16_t token, + u32 cmd_flags, + u16 token, char *type, struct dprc_res_ids_range_desc *range_desc) { @@ -661,7 +1272,7 @@ int dprc_get_res_ids(struct fsl_mc_io *mc_io, /* prepare command */ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_IDS, - MC_CMD_PRI_LOW, token); + cmd_flags, token); cmd.params[0] |= mc_enc(42, 7, range_desc->iter_status); cmd.params[1] |= mc_enc(0, 32, range_desc->base_id); cmd.params[1] |= mc_enc(32, 32, range_desc->last_id); @@ -696,36 +1307,24 @@ 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); - +/** + * dprc_get_obj_region() - Get region information for a specified object. + * @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 + * @obj_type; Object type as returned in dprc_get_obj() + * @obj_id: Unique object instance as returned in dprc_get_obj() + * @region_index: The specific region to query + * @region_desc: Returns the requested region descriptor + * + * Return: '0' on Success; Error code otherwise. + */ int dprc_get_obj_region(struct fsl_mc_io *mc_io, - uint16_t token, + u32 cmd_flags, + u16 token, char *obj_type, int obj_id, - uint8_t region_index, + u8 region_index, struct dprc_region_desc *region_desc) { struct mc_command cmd = { 0 }; @@ -733,7 +1332,7 @@ int dprc_get_obj_region(struct fsl_mc_io *mc_io, /* prepare command */ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_REG, - MC_CMD_PRI_LOW, token); + cmd_flags, token); cmd.params[0] |= mc_enc(0, 32, obj_id); cmd.params[0] |= mc_enc(48, 8, region_index); cmd.params[3] |= mc_enc(0, 8, obj_type[0]); @@ -759,28 +1358,113 @@ 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); +/** + * dprc_set_obj_label() - Set object label. + * @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 + * @obj_type: Object's type + * @obj_id: Object's ID + * @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, + u32 cmd_flags, + u16 token, + char *obj_type, + int obj_id, + char *label) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_OBJ_LABEL, + cmd_flags, + token); + + cmd.params[0] |= mc_enc(0, 32, obj_id); + 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]); + cmd.params[3] |= mc_enc(0, 8, obj_type[0]); + cmd.params[3] |= mc_enc(8, 8, obj_type[1]); + cmd.params[3] |= mc_enc(16, 8, obj_type[2]); + cmd.params[3] |= mc_enc(24, 8, obj_type[3]); + cmd.params[3] |= mc_enc(32, 8, obj_type[4]); + cmd.params[3] |= mc_enc(40, 8, obj_type[5]); + cmd.params[3] |= mc_enc(48, 8, obj_type[6]); + cmd.params[3] |= mc_enc(56, 8, obj_type[7]); + cmd.params[4] |= mc_enc(0, 8, obj_type[8]); + cmd.params[4] |= mc_enc(8, 8, obj_type[9]); + cmd.params[4] |= mc_enc(16, 8, obj_type[10]); + cmd.params[4] |= mc_enc(24, 8, obj_type[11]); + cmd.params[4] |= mc_enc(32, 8, obj_type[12]); + cmd.params[4] |= mc_enc(40, 8, obj_type[13]); + cmd.params[4] |= mc_enc(48, 8, obj_type[14]); + cmd.params[4] |= mc_enc(56, 8, obj_type[15]); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} +EXPORT_SYMBOL(dprc_set_obj_label); + +/** + * dprc_connect() - Connect two endpoints to create a network link between them + * @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 + * @endpoint1: Endpoint 1 configuration parameters + * @endpoint2: Endpoint 2 configuration parameters + * @cfg: Connection configuration. The connection configuration is ignored for + * connections made to DPMAC objects, where rate is set according to + * MAC configuration. + * The committed rate is the guaranteed rate for the connection. + * The maximum rate is an upper limit allowed for the connection; it is + * expected to be equal or higher than the committed rate. + * When committed and maximum rates are both zero, the connection is set + * to "best effort" mode, having lower priority compared to connections + * with committed or maximum rates. + * + * Return: '0' on Success; Error code otherwise. + */ int dprc_connect(struct fsl_mc_io *mc_io, - uint16_t token, + u32 cmd_flags, + u16 token, const struct dprc_endpoint *endpoint1, - const struct dprc_endpoint *endpoint2) + const struct dprc_endpoint *endpoint2, + const struct dprc_connection_cfg *cfg) { struct mc_command cmd = { 0 }; /* prepare command */ cmd.header = mc_encode_cmd_header(DPRC_CMDID_CONNECT, - MC_CMD_PRI_LOW, + cmd_flags, token); cmd.params[0] |= mc_enc(0, 32, endpoint1->id); - cmd.params[0] |= mc_enc(32, 32, endpoint1->interface_id); + cmd.params[0] |= mc_enc(32, 32, endpoint1->if_id); cmd.params[1] |= mc_enc(0, 32, endpoint2->id); - cmd.params[1] |= mc_enc(32, 32, endpoint2->interface_id); + cmd.params[1] |= mc_enc(32, 32, endpoint2->if_id); cmd.params[2] |= mc_enc(0, 8, endpoint1->type[0]); cmd.params[2] |= mc_enc(8, 8, endpoint1->type[1]); cmd.params[2] |= mc_enc(16, 8, endpoint1->type[2]); @@ -797,6 +1481,8 @@ int dprc_connect(struct fsl_mc_io *mc_io, cmd.params[3] |= mc_enc(40, 8, endpoint1->type[13]); cmd.params[3] |= mc_enc(48, 8, endpoint1->type[14]); cmd.params[3] |= mc_enc(56, 8, endpoint1->type[15]); + cmd.params[4] |= mc_enc(0, 32, cfg->max_rate); + cmd.params[4] |= mc_enc(32, 32, cfg->committed_rate); cmd.params[5] |= mc_enc(0, 8, endpoint2->type[0]); cmd.params[5] |= mc_enc(8, 8, endpoint2->type[1]); cmd.params[5] |= mc_enc(16, 8, endpoint2->type[2]); @@ -818,18 +1504,28 @@ int dprc_connect(struct fsl_mc_io *mc_io, return mc_send_command(mc_io, &cmd); } +/** + * dprc_disconnect() - Disconnect one endpoint to remove its network connection + * @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 + * @endpoint: Endpoint configuration parameters + * + * Return: '0' on Success; Error code otherwise. + */ int dprc_disconnect(struct fsl_mc_io *mc_io, - uint16_t token, + u32 cmd_flags, + u16 token, const struct dprc_endpoint *endpoint) { struct mc_command cmd = { 0 }; /* prepare command */ cmd.header = mc_encode_cmd_header(DPRC_CMDID_DISCONNECT, - MC_CMD_PRI_LOW, + cmd_flags, token); cmd.params[0] |= mc_enc(0, 32, endpoint->id); - cmd.params[0] |= mc_enc(32, 32, endpoint->interface_id); + cmd.params[0] |= mc_enc(32, 32, endpoint->if_id); cmd.params[1] |= mc_enc(0, 8, endpoint->type[0]); cmd.params[1] |= mc_enc(8, 8, endpoint->type[1]); cmd.params[1] |= mc_enc(16, 8, endpoint->type[2]); @@ -851,21 +1547,34 @@ int dprc_disconnect(struct fsl_mc_io *mc_io, return mc_send_command(mc_io, &cmd); } +/** +* dprc_get_connection() - Get connected endpoint and link status if connection +* exists. +* @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 +* @endpoint1: Endpoint 1 configuration parameters +* @endpoint2: Returned endpoint 2 configuration parameters +* @state: Returned link state: 1 - link is up, 0 - link is down +* +* Return: '0' on Success; -ENAVAIL if connection does not exist. +*/ int dprc_get_connection(struct fsl_mc_io *mc_io, - uint16_t token, - const struct dprc_endpoint *endpoint1, - struct dprc_endpoint *endpoint2, - int *state) + u32 cmd_flags, + u16 token, + const struct dprc_endpoint *endpoint1, + struct dprc_endpoint *endpoint2, + int *state) { struct mc_command cmd = { 0 }; int err; /* prepare command */ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONNECTION, - MC_CMD_PRI_LOW, + cmd_flags, token); cmd.params[0] |= mc_enc(0, 32, endpoint1->id); - cmd.params[0] |= mc_enc(32, 32, endpoint1->interface_id); + cmd.params[0] |= mc_enc(32, 32, endpoint1->if_id); cmd.params[1] |= mc_enc(0, 8, endpoint1->type[0]); cmd.params[1] |= mc_enc(8, 8, endpoint1->type[1]); cmd.params[1] |= mc_enc(16, 8, endpoint1->type[2]); @@ -890,7 +1599,7 @@ int dprc_get_connection(struct fsl_mc_io *mc_io, /* retrieve response parameters */ endpoint2->id = mc_dec(cmd.params[3], 0, 32); - endpoint2->interface_id = mc_dec(cmd.params[3], 32, 32); + endpoint2->if_id = mc_dec(cmd.params[3], 32, 32); endpoint2->type[0] = mc_dec(cmd.params[4], 0, 8); endpoint2->type[1] = mc_dec(cmd.params[4], 8, 8); endpoint2->type[2] = mc_dec(cmd.params[4], 16, 8); diff --git a/kernel/drivers/staging/fsl-mc/bus/mc-allocator.c b/kernel/drivers/staging/fsl-mc/bus/mc-allocator.c index e36235ddb..88d185752 100644 --- a/kernel/drivers/staging/fsl-mc/bus/mc-allocator.c +++ b/kernel/drivers/staging/fsl-mc/bus/mc-allocator.c @@ -111,7 +111,7 @@ static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device goto out; resource = mc_dev->resource; - if (WARN_ON(resource->data != mc_dev)) + if (WARN_ON(!resource || resource->data != mc_dev)) goto out; mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); @@ -277,14 +277,14 @@ EXPORT_SYMBOL_GPL(fsl_mc_resource_free); * portal is allocated from its own MC bus. */ int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev, - uint16_t mc_io_flags, + u16 mc_io_flags, struct fsl_mc_io **new_mc_io) { struct fsl_mc_device *mc_bus_dev; struct fsl_mc_bus *mc_bus; phys_addr_t mc_portal_phys_addr; size_t mc_portal_size; - struct fsl_mc_device *mc_adev; + struct fsl_mc_device *dpmcp_dev; int error = -EINVAL; struct fsl_mc_resource *resource = NULL; struct fsl_mc_io *mc_io = NULL; @@ -304,23 +304,23 @@ int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev, if (error < 0) return error; - mc_adev = resource->data; - if (WARN_ON(!mc_adev)) + dpmcp_dev = resource->data; + if (WARN_ON(!dpmcp_dev)) goto error_cleanup_resource; - if (WARN_ON(mc_adev->obj_desc.region_count == 0)) + if (WARN_ON(dpmcp_dev->obj_desc.region_count == 0)) goto error_cleanup_resource; - mc_portal_phys_addr = mc_adev->regions[0].start; - mc_portal_size = mc_adev->regions[0].end - - mc_adev->regions[0].start + 1; + mc_portal_phys_addr = dpmcp_dev->regions[0].start; + mc_portal_size = dpmcp_dev->regions[0].end - + dpmcp_dev->regions[0].start + 1; if (WARN_ON(mc_portal_size != mc_bus_dev->mc_io->portal_size)) goto error_cleanup_resource; error = fsl_create_mc_io(&mc_bus_dev->dev, mc_portal_phys_addr, - mc_portal_size, resource, + mc_portal_size, dpmcp_dev, mc_io_flags, &mc_io); if (error < 0) goto error_cleanup_resource; @@ -342,12 +342,22 @@ EXPORT_SYMBOL_GPL(fsl_mc_portal_allocate); */ void fsl_mc_portal_free(struct fsl_mc_io *mc_io) { + struct fsl_mc_device *dpmcp_dev; struct fsl_mc_resource *resource; - resource = mc_io->resource; - if (WARN_ON(resource->type != FSL_MC_POOL_DPMCP)) + /* + * Every mc_io obtained by calling fsl_mc_portal_allocate() is supposed + * to have a DPMCP object associated with. + */ + dpmcp_dev = mc_io->dpmcp_dev; + if (WARN_ON(!dpmcp_dev)) return; - if (WARN_ON(!resource->data)) + + resource = dpmcp_dev->resource; + if (WARN_ON(!resource || resource->type != FSL_MC_POOL_DPMCP)) + return; + + if (WARN_ON(resource->data != dpmcp_dev)) return; fsl_destroy_mc_io(mc_io); @@ -363,31 +373,14 @@ EXPORT_SYMBOL_GPL(fsl_mc_portal_free); int fsl_mc_portal_reset(struct fsl_mc_io *mc_io) { int error; - uint16_t token; - struct fsl_mc_resource *resource = mc_io->resource; - struct fsl_mc_device *mc_dev = resource->data; + struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; - if (WARN_ON(resource->type != FSL_MC_POOL_DPMCP)) + if (WARN_ON(!dpmcp_dev)) return -EINVAL; - if (WARN_ON(!mc_dev)) - return -EINVAL; - - error = dpmcp_open(mc_io, mc_dev->obj_desc.id, &token); - if (error < 0) { - dev_err(&mc_dev->dev, "dpmcp_open() failed: %d\n", error); - return error; - } - - error = dpmcp_reset(mc_io, token); + error = dpmcp_reset(mc_io, 0, dpmcp_dev->mc_handle); if (error < 0) { - dev_err(&mc_dev->dev, "dpmcp_reset() failed: %d\n", error); - return error; - } - - error = dpmcp_close(mc_io, token); - if (error < 0) { - dev_err(&mc_dev->dev, "dpmcp_close() failed: %d\n", error); + dev_err(&dpmcp_dev->dev, "dpmcp_reset() failed: %d\n", error); return error; } @@ -481,30 +474,27 @@ static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev) enum fsl_mc_pool_type pool_type; struct fsl_mc_device *mc_bus_dev; struct fsl_mc_bus *mc_bus; - int error = -EINVAL; + int error; if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type))) - goto error; + return -EINVAL; mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); if (WARN_ON(mc_bus_dev->dev.bus != &fsl_mc_bus_type)) - goto error; + return -EINVAL; mc_bus = to_fsl_mc_bus(mc_bus_dev); error = object_type_to_pool_type(mc_dev->obj_desc.type, &pool_type); if (error < 0) - goto error; + return error; error = fsl_mc_resource_pool_add_device(mc_bus, pool_type, mc_dev); if (error < 0) - goto error; + return 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: - - return error; } /** @@ -513,20 +503,20 @@ error: */ static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev) { - int error = -EINVAL; + int error; if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type))) - goto out; + return -EINVAL; - error = fsl_mc_resource_pool_remove_device(mc_dev); - if (error < 0) - goto out; + if (mc_dev->resource) { + error = fsl_mc_resource_pool_remove_device(mc_dev); + if (error < 0) + return error; + } - dev_info(&mc_dev->dev, - "Allocatable MC object device unbound from fsl_mc_allocator driver"); - error = 0; -out: - return error; + dev_dbg(&mc_dev->dev, + "Allocatable MC object device unbound from fsl_mc_allocator driver"); + return 0; } static const struct fsl_mc_device_match_id match_id_table[] = { diff --git a/kernel/drivers/staging/fsl-mc/bus/mc-bus.c b/kernel/drivers/staging/fsl-mc/bus/mc-bus.c index 23512d096..84db55b4d 100644 --- a/kernel/drivers/staging/fsl-mc/bus/mc-bus.c +++ b/kernel/drivers/staging/fsl-mc/bus/mc-bus.c @@ -22,6 +22,8 @@ static struct kmem_cache *mc_dev_cache; +static bool fsl_mc_is_root_dprc(struct device *dev); + /** * fsl_mc_bus_match - device to driver matching callback * @dev: the MC object device structure to match against @@ -39,7 +41,7 @@ static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv) bool major_version_mismatch = false; bool minor_version_mismatch = false; - if (WARN_ON(!fsl_mc_bus_type.dev_root)) + if (WARN_ON(!fsl_mc_bus_exists())) goto out; if (!mc_drv->match_id_table) @@ -50,7 +52,7 @@ static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv) * Only exception is the root DPRC, which is a special case. */ if ((mc_dev->obj_desc.state & DPRC_OBJ_STATE_PLUGGED) == 0 && - &mc_dev->dev != fsl_mc_bus_type.dev_root) + !fsl_mc_is_root_dprc(&mc_dev->dev)) goto out; /* @@ -107,6 +109,8 @@ struct bus_type fsl_mc_bus_type = { }; EXPORT_SYMBOL_GPL(fsl_mc_bus_type); +static atomic_t root_dprc_count = ATOMIC_INIT(0); + static int fsl_mc_driver_probe(struct device *dev) { struct fsl_mc_driver *mc_drv; @@ -206,21 +210,61 @@ void fsl_mc_driver_unregister(struct fsl_mc_driver *mc_driver) } EXPORT_SYMBOL_GPL(fsl_mc_driver_unregister); +/** + * fsl_mc_bus_exists - check if a root dprc exists + */ +bool fsl_mc_bus_exists(void) +{ + return atomic_read(&root_dprc_count) > 0; +} +EXPORT_SYMBOL_GPL(fsl_mc_bus_exists); + +/** +* fsl_mc_get_root_dprc - function to traverse to the root dprc +*/ +static void fsl_mc_get_root_dprc(struct device *dev, + struct device **root_dprc_dev) +{ + if (WARN_ON(!dev)) { + *root_dprc_dev = NULL; + } else if (WARN_ON(dev->bus != &fsl_mc_bus_type)) { + *root_dprc_dev = NULL; + } else { + *root_dprc_dev = dev; + while ((*root_dprc_dev)->parent->bus == &fsl_mc_bus_type) + *root_dprc_dev = (*root_dprc_dev)->parent; + } +} + +/** + * fsl_mc_is_root_dprc - function to check if a given device is a root dprc + */ +static bool fsl_mc_is_root_dprc(struct device *dev) +{ + struct device *root_dprc_dev; + + fsl_mc_get_root_dprc(dev, &root_dprc_dev); + if (!root_dprc_dev) + return false; + else + return dev == root_dprc_dev; +} + static int get_dprc_icid(struct fsl_mc_io *mc_io, - int container_id, uint16_t *icid) + int container_id, u16 *icid) { - uint16_t dprc_handle; + u16 dprc_handle; struct dprc_attributes attr; int error; - error = dprc_open(mc_io, container_id, &dprc_handle); + error = dprc_open(mc_io, 0, container_id, &dprc_handle); if (error < 0) { pr_err("dprc_open() failed: %d\n", error); return error; } memset(&attr, 0, sizeof(attr)); - error = dprc_get_attributes(mc_io, dprc_handle, &attr); + error = dprc_get_attributes(mc_io, 0, dprc_handle, &attr); if (error < 0) { pr_err("dprc_get_attributes() failed: %d\n", error); goto common_cleanup; @@ -230,20 +274,28 @@ static int get_dprc_icid(struct fsl_mc_io *mc_io, error = 0; common_cleanup: - (void)dprc_close(mc_io, dprc_handle); + (void)dprc_close(mc_io, 0, dprc_handle); return error; } -static int translate_mc_addr(uint64_t mc_addr, phys_addr_t *phys_addr) +static int translate_mc_addr(struct fsl_mc_device *mc_dev, + enum dprc_region_type mc_region_type, + u64 mc_offset, phys_addr_t *phys_addr) { int i; - struct fsl_mc *mc = dev_get_drvdata(fsl_mc_bus_type.dev_root->parent); + struct device *root_dprc_dev; + struct fsl_mc *mc; + + fsl_mc_get_root_dprc(&mc_dev->dev, &root_dprc_dev); + if (WARN_ON(!root_dprc_dev)) + return -EINVAL; + mc = dev_get_drvdata(root_dprc_dev->parent); if (mc->num_translation_ranges == 0) { /* * Do identity mapping: */ - *phys_addr = mc_addr; + *phys_addr = mc_offset; return 0; } @@ -251,10 +303,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; } } @@ -270,6 +323,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 dprc_region_type mc_region_type; + + if (strcmp(obj_desc->type, "dprc") == 0 || + strcmp(obj_desc->type, "dpmcp") == 0) { + mc_region_type = DPRC_REGION_TYPE_MC_PORTAL; + } else if (strcmp(obj_desc->type, "dpio") == 0) { + mc_region_type = DPRC_REGION_TYPE_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); @@ -280,6 +349,7 @@ static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev, struct dprc_region_desc region_desc; error = dprc_get_obj_region(mc_bus_dev->mc_io, + 0, mc_bus_dev->mc_handle, obj_desc->type, obj_desc->id, i, ®ion_desc); @@ -289,14 +359,15 @@ 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_dev, mc_region_type, + region_desc.base_offset, ®ions[i].start); if (error < 0) { dev_err(parent_dev, - "Invalid MC address: %#llx\n", - region_desc.base_paddr); + "Invalid MC offset: %#x (for %s.%d\'s region %d)\n", + region_desc.base_offset, + obj_desc->type, obj_desc->id, i); goto error_cleanup_regions; } @@ -387,8 +458,7 @@ int fsl_mc_device_add(struct dprc_obj_desc *obj_desc, mc_io2 = mc_io; - if (!fsl_mc_bus_type.dev_root) - fsl_mc_bus_type.dev_root = &mc_dev->dev; + atomic_inc(&root_dprc_count); } error = get_dprc_icid(mc_io2, obj_desc->id, &mc_dev->icid); @@ -471,8 +541,12 @@ void fsl_mc_device_remove(struct fsl_mc_device *mc_dev) mc_dev->mc_io = NULL; } - if (&mc_dev->dev == fsl_mc_bus_type.dev_root) - fsl_mc_bus_type.dev_root = NULL; + if (fsl_mc_is_root_dprc(&mc_dev->dev)) { + if (atomic_read(&root_dprc_count) > 0) + atomic_dec(&root_dprc_count); + else + WARN_ON(1); + } } if (mc_bus) @@ -487,7 +561,7 @@ static int parse_mc_ranges(struct device *dev, int *mc_addr_cells, int *mc_size_cells, const __be32 **ranges_start, - uint8_t *num_ranges) + u8 *num_ranges) { const __be32 *prop; int range_tuple_cell_count; @@ -535,7 +609,7 @@ static int parse_mc_ranges(struct device *dev, static int get_mc_addr_translation_ranges(struct device *dev, struct fsl_mc_addr_translation_range **ranges, - uint8_t *num_ranges) + u8 *num_ranges) { int error; int paddr_cells; @@ -574,11 +648,13 @@ 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 + + range->end_mc_offset = range->start_mc_offset + of_read_number(cell, mc_size_cells); cell += mc_size_cells; @@ -600,7 +676,7 @@ static int fsl_mc_bus_probe(struct platform_device *pdev) struct fsl_mc_io *mc_io = NULL; int container_id; phys_addr_t mc_portal_phys_addr; - uint32_t mc_portal_size; + u32 mc_portal_size; struct mc_version mc_version; struct resource res; @@ -630,7 +706,7 @@ static int fsl_mc_bus_probe(struct platform_device *pdev) if (error < 0) return error; - error = mc_get_version(mc_io, &mc_version); + error = mc_get_version(mc_io, 0, &mc_version); if (error != 0) { dev_err(&pdev->dev, "mc_get_version() failed with error %d\n", error); @@ -661,7 +737,7 @@ static int fsl_mc_bus_probe(struct platform_device *pdev) if (error < 0) goto error_cleanup_mc_io; - error = dpmng_get_container_id(mc_io, &container_id); + error = dpmng_get_container_id(mc_io, 0, &container_id); if (error < 0) { dev_err(&pdev->dev, "dpmng_get_container_id() failed: %d\n", error); @@ -673,6 +749,7 @@ static int fsl_mc_bus_probe(struct platform_device *pdev) obj_desc.id = container_id; obj_desc.ver_major = DPRC_VER_MAJOR; obj_desc.ver_minor = DPRC_VER_MINOR; + obj_desc.irq_count = 1; obj_desc.region_count = 0; error = fsl_mc_device_add(&obj_desc, mc_io, &pdev->dev, &mc_bus_dev); @@ -695,7 +772,7 @@ static int fsl_mc_bus_remove(struct platform_device *pdev) { struct fsl_mc *mc = platform_get_drvdata(pdev); - if (WARN_ON(&mc->root_mc_bus_dev->dev != fsl_mc_bus_type.dev_root)) + if (WARN_ON(!fsl_mc_is_root_dprc(&mc->root_mc_bus_dev->dev))) return -EINVAL; fsl_mc_device_remove(mc->root_mc_bus_dev); diff --git a/kernel/drivers/staging/fsl-mc/bus/mc-sys.c b/kernel/drivers/staging/fsl-mc/bus/mc-sys.c index 5737f599f..6e1489246 100644 --- a/kernel/drivers/staging/fsl-mc/bus/mc-sys.c +++ b/kernel/drivers/staging/fsl-mc/bus/mc-sys.c @@ -34,15 +34,17 @@ #include "../include/mc-sys.h" #include "../include/mc-cmd.h" +#include "../include/mc.h" #include #include #include #include +#include "dpmcp.h" /** - * Timeout in jiffies to wait for the completion of an MC command + * Timeout in milliseconds to wait for the completion of an MC command */ -#define MC_CMD_COMPLETION_TIMEOUT_JIFFIES (HZ / 2) /* 500 ms */ +#define MC_CMD_COMPLETION_TIMEOUT_MS 500 /* * usleep_range() min and max values used to throttle down polling @@ -52,7 +54,7 @@ #define MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS 500 #define MC_CMD_HDR_READ_CMDID(_hdr) \ - ((uint16_t)mc_dec((_hdr), MC_CMD_HDR_CMDID_O, MC_CMD_HDR_CMDID_S)) + ((u16)mc_dec((_hdr), MC_CMD_HDR_CMDID_O, MC_CMD_HDR_CMDID_S)) /** * Creates an MC I/O object @@ -60,8 +62,8 @@ * @dev: device to be associated with the MC I/O object * @mc_portal_phys_addr: physical address of the MC portal to use * @mc_portal_size: size in bytes of the MC portal - * @resource: Pointer to MC bus object allocator resource associated - * with this MC I/O object or NULL if none. + * @dpmcp-dev: Pointer to the DPMCP object associated with this MC I/O + * object or NULL if none. * @flags: flags for the new MC I/O object * @new_mc_io: Area to return pointer to newly created MC I/O object * @@ -69,10 +71,11 @@ */ int __must_check fsl_create_mc_io(struct device *dev, phys_addr_t mc_portal_phys_addr, - uint32_t mc_portal_size, - struct fsl_mc_resource *resource, - uint32_t flags, struct fsl_mc_io **new_mc_io) + u32 mc_portal_size, + struct fsl_mc_device *dpmcp_dev, + u32 flags, struct fsl_mc_io **new_mc_io) { + int error; struct fsl_mc_io *mc_io; void __iomem *mc_portal_virt_addr; struct resource *res; @@ -85,7 +88,11 @@ int __must_check fsl_create_mc_io(struct device *dev, mc_io->flags = flags; mc_io->portal_phys_addr = mc_portal_phys_addr; mc_io->portal_size = mc_portal_size; - mc_io->resource = resource; + if (flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL) + spin_lock_init(&mc_io->spinlock); + else + mutex_init(&mc_io->mutex); + res = devm_request_mem_region(dev, mc_portal_phys_addr, mc_portal_size, @@ -108,8 +115,18 @@ int __must_check fsl_create_mc_io(struct device *dev, } mc_io->portal_virt_addr = mc_portal_virt_addr; + if (dpmcp_dev) { + error = fsl_mc_io_set_dpmcp(mc_io, dpmcp_dev); + if (error < 0) + goto error_destroy_mc_io; + } + *new_mc_io = mc_io; return 0; + +error_destroy_mc_io: + fsl_destroy_mc_io(mc_io); + return error; } EXPORT_SYMBOL_GPL(fsl_create_mc_io); @@ -120,6 +137,11 @@ EXPORT_SYMBOL_GPL(fsl_create_mc_io); */ void fsl_destroy_mc_io(struct fsl_mc_io *mc_io) { + struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; + + if (dpmcp_dev) + fsl_mc_io_unset_dpmcp(mc_io); + devm_iounmap(mc_io->dev, mc_io->portal_virt_addr); devm_release_mem_region(mc_io->dev, mc_io->portal_phys_addr, @@ -130,6 +152,57 @@ void fsl_destroy_mc_io(struct fsl_mc_io *mc_io) } EXPORT_SYMBOL_GPL(fsl_destroy_mc_io); +int fsl_mc_io_set_dpmcp(struct fsl_mc_io *mc_io, + struct fsl_mc_device *dpmcp_dev) +{ + int error; + + if (WARN_ON(!dpmcp_dev)) + return -EINVAL; + + if (WARN_ON(mc_io->dpmcp_dev)) + return -EINVAL; + + if (WARN_ON(dpmcp_dev->mc_io)) + return -EINVAL; + + error = dpmcp_open(mc_io, + 0, + dpmcp_dev->obj_desc.id, + &dpmcp_dev->mc_handle); + if (error < 0) + return error; + + mc_io->dpmcp_dev = dpmcp_dev; + dpmcp_dev->mc_io = mc_io; + return 0; +} +EXPORT_SYMBOL_GPL(fsl_mc_io_set_dpmcp); + +void fsl_mc_io_unset_dpmcp(struct fsl_mc_io *mc_io) +{ + int error; + struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; + + if (WARN_ON(!dpmcp_dev)) + return; + + if (WARN_ON(dpmcp_dev->mc_io != mc_io)) + return; + + error = dpmcp_close(mc_io, + 0, + dpmcp_dev->mc_handle); + if (error < 0) { + dev_err(&dpmcp_dev->dev, "dpmcp_close() failed: %d\n", + error); + } + + mc_io->dpmcp_dev = NULL; + dpmcp_dev->mc_io = NULL; +} +EXPORT_SYMBOL_GPL(fsl_mc_io_unset_dpmcp); + static int mc_status_to_error(enum mc_cmd_status status) { static const int mc_status_to_error_map[] = { @@ -224,25 +297,20 @@ static inline enum mc_cmd_status mc_read_response(struct mc_command __iomem * } /** - * Sends an command to the MC device using the given MC I/O object + * Waits for the completion of an MC command doing preemptible polling. + * uslepp_range() is called between polling iterations. * * @mc_io: MC I/O object to be used - * @cmd: command to be sent - * - * Returns '0' on Success; Error code otherwise. - * - * NOTE: This function cannot be invoked from from atomic contexts. + * @cmd: command buffer to receive MC response + * @mc_status: MC command completion status */ -int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd) +static int mc_polling_wait_preemptible(struct fsl_mc_io *mc_io, + struct mc_command *cmd, + enum mc_cmd_status *mc_status) { enum mc_cmd_status status; unsigned long jiffies_until_timeout = - jiffies + MC_CMD_COMPLETION_TIMEOUT_JIFFIES; - - /* - * Send command to the MC hardware: - */ - mc_write_command(mc_io->portal_virt_addr, cmd); + jiffies + msecs_to_jiffies(MC_CMD_COMPLETION_TIMEOUT_MS); /* * Wait for response from the MC hardware: @@ -271,6 +339,90 @@ int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd) } } + *mc_status = status; + return 0; +} + +/** + * Waits for the completion of an MC command doing atomic polling. + * udelay() is called between polling iterations. + * + * @mc_io: MC I/O object to be used + * @cmd: command buffer to receive MC response + * @mc_status: MC command completion status + */ +static int mc_polling_wait_atomic(struct fsl_mc_io *mc_io, + struct mc_command *cmd, + enum mc_cmd_status *mc_status) +{ + enum mc_cmd_status status; + unsigned long timeout_usecs = MC_CMD_COMPLETION_TIMEOUT_MS * 1000; + + BUILD_BUG_ON((MC_CMD_COMPLETION_TIMEOUT_MS * 1000) % + MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS != 0); + + for (;;) { + status = mc_read_response(mc_io->portal_virt_addr, cmd); + if (status != MC_CMD_STATUS_READY) + break; + + udelay(MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS); + timeout_usecs -= MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS; + if (timeout_usecs == 0) { + pr_debug("MC command timed out (portal: %#llx, obj handle: %#x, command: %#x)\n", + mc_io->portal_phys_addr, + (unsigned int) + MC_CMD_HDR_READ_TOKEN(cmd->header), + (unsigned int) + MC_CMD_HDR_READ_CMDID(cmd->header)); + + return -ETIMEDOUT; + } + } + + *mc_status = status; + return 0; +} + +/** + * Sends a command to the MC device using the given MC I/O object + * + * @mc_io: MC I/O object to be used + * @cmd: command to be sent + * + * Returns '0' on Success; Error code otherwise. + */ +int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd) +{ + int error; + enum mc_cmd_status status; + unsigned long irq_flags = 0; + + if (WARN_ON(in_irq() && + !(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL))) + return -EINVAL; + + if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL) + spin_lock_irqsave(&mc_io->spinlock, irq_flags); + else + mutex_lock(&mc_io->mutex); + + /* + * Send command to the MC hardware: + */ + mc_write_command(mc_io->portal_virt_addr, cmd); + + /* + * Wait for response from the MC hardware: + */ + if (!(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)) + error = mc_polling_wait_preemptible(mc_io, cmd, &status); + else + error = mc_polling_wait_atomic(mc_io, cmd, &status); + + if (error < 0) + goto common_exit; + if (status != MC_CMD_STATUS_OK) { pr_debug("MC command failed: portal: %#llx, obj handle: %#x, command: %#x, status: %s (%#x)\n", mc_io->portal_phys_addr, @@ -279,9 +431,17 @@ int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd) mc_status_to_string(status), (unsigned int)status); - return mc_status_to_error(status); + error = mc_status_to_error(status); + goto common_exit; } - return 0; + error = 0; +common_exit: + if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL) + spin_unlock_irqrestore(&mc_io->spinlock, irq_flags); + else + mutex_unlock(&mc_io->mutex); + + return error; } EXPORT_SYMBOL(mc_send_command); -- cgit 1.2.3-korg