[U-Boot] [PATCH 01/13][v4] drivers/fsl-mc: Make MC boot error messages more readable

From: "J. German Rivera" German.Rivera@freescale.com
Make it easier for the user to notice when the MC firmware had problems booting.
Signed-off-by: J. German Rivera German.Rivera@freescale.com Signed-off-by: Prabhakar Kushwaha prabhakar@freescale.com --- Changes for v2: Sending as it is for patchset Changes for v3: Sending as it is for patchset Changes for v4: Sending as it is for patchset
drivers/net/fsl-mc/mc.c | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-)
diff --git a/drivers/net/fsl-mc/mc.c b/drivers/net/fsl-mc/mc.c index f4a050a..d02da9d 100644 --- a/drivers/net/fsl-mc/mc.c +++ b/drivers/net/fsl-mc/mc.c @@ -224,13 +224,13 @@ static int load_mc_dpc(u64 mc_ram_addr, size_t mc_ram_size) * Don't return with error here, since the MC firmware can * still boot without a DPC */ - printf("fsl-mc: WARNING: No DPC image found\n"); + printf("\nfsl-mc: WARNING: No DPC image found"); return 0; }
dpc_size = fdt_totalsize(dpc_fdt_hdr); if (dpc_size > CONFIG_SYS_LS_MC_DPC_MAX_LENGTH) { - printf("fsl-mc: ERROR: Bad DPC image (too large: %d)\n", + printf("\nfsl-mc: ERROR: Bad DPC image (too large: %d)\n", dpc_size); return -EINVAL; } @@ -278,13 +278,13 @@ static int load_mc_dpl(u64 mc_ram_addr, size_t mc_ram_size)
error = fdt_check_header(dpl_fdt_hdr); if (error != 0) { - printf("fsl-mc: ERROR: Bad DPL image (bad header)\n"); + printf("\nfsl-mc: ERROR: Bad DPL image (bad header)\n"); return error; }
dpl_size = fdt_totalsize(dpl_fdt_hdr); if (dpl_size > CONFIG_SYS_LS_MC_DPL_MAX_LENGTH) { - printf("fsl-mc: ERROR: Bad DPL image (too large: %d)\n", + printf("\nfsl-mc: ERROR: Bad DPL image (too large: %d)\n", dpl_size); return -EINVAL; } @@ -329,7 +329,6 @@ static int wait_for_mc(bool booting_mc, u32 *final_reg_gsr) struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
dmb(); - debug("Polling mc_ccsr_regs->reg_gsr ...\n"); assert(timeout_ms > 0); for (;;) { udelay(1000); /* throttle polling */ @@ -344,10 +343,7 @@ static int wait_for_mc(bool booting_mc, u32 *final_reg_gsr) }
if (timeout_ms == 0) { - if (booting_mc) - printf("fsl-mc: timeout booting management complex firmware\n"); - else - printf("fsl-mc: timeout deploying data path layout\n"); + printf("ERROR: timeout\n");
/* TODO: Get an error status from an MC CCSR register */ return -ETIMEDOUT; @@ -360,15 +356,13 @@ static int wait_for_mc(bool booting_mc, u32 *final_reg_gsr) * appropriate errno, so that the status property is set to * failure in the fsl,dprc device tree node. */ - if (booting_mc) { - printf("fsl-mc: WARNING: Firmware booted with error (GSR: %#x)\n", - reg_gsr); - } else { - printf("fsl-mc: WARNING: Data path layout deployed with error (GSR: %#x)\n", - reg_gsr); - } + printf("WARNING: Firmware returned an error (GSR: %#x)\n", + reg_gsr); + } else { + printf("SUCCESS\n"); }
+ *final_reg_gsr = reg_gsr; return 0; } @@ -464,7 +458,7 @@ int mc_init(void) */ out_le32(&mc_ccsr_regs->reg_gsr, 0xDD00);
- printf("\nfsl-mc: Booting Management Complex ...\n"); + printf("\nfsl-mc: Booting Management Complex ... ");
/* * Deassert reset and release MC core 0 to run @@ -517,10 +511,11 @@ int mc_init(void) * Tell the MC to deploy the DPL: */ out_le32(&mc_ccsr_regs->reg_gsr, 0x0); - printf("\nfsl-mc: Deploying data path layout ...\n"); + printf("fsl-mc: Deploying data path layout ... "); error = wait_for_mc(false, ®_gsr); if (error != 0) goto out; + out: if (error != 0) mc_boot_status = -error;

Flush buffer before releasing to BMan after TX_conf to ensure, the core does not have any cachelines that the WRIOP will DMA to.
Signed-off-by: Prabhakar Kushwaha prabhakar@freescale.com --- Changes for v2: Sending as it is for patchset Changes for v3: Sending as it is for patchset Changes for v4: Sending as it is for patchset
drivers/net/ldpaa_eth/ldpaa_eth.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.c b/drivers/net/ldpaa_eth/ldpaa_eth.c index d4be1ba..5636511 100644 --- a/drivers/net/ldpaa_eth/ldpaa_eth.c +++ b/drivers/net/ldpaa_eth/ldpaa_eth.c @@ -153,6 +153,7 @@ static void ldpaa_eth_tx_conf(struct ldpaa_eth_priv *priv, } }
+ flush_dcache_range(fd_addr, fd_addr + LDPAA_ETH_RX_BUFFER_SIZE); qbman_release_desc_clear(&releasedesc); qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid); do {

From: "J. German Rivera" German.Rivera@freescale.com
Load AIOP image from NOR flash into DDR so that the MC firmware the MC fw can start it at boot time
Signed-off-by: J. German Rivera German.Rivera@freescale.com Signed-off-by: Prabhakar Kushwaha prabhakar@freescale.com --- Changes for v2: Sending as it is for patchset Changes for v3: Sending as it is for patchset Changes for v4: Sending as it is for patchset
drivers/net/fsl-mc/mc.c | 23 +++++++++++++++++++++++ include/configs/ls2085a_common.h | 2 ++ include/configs/ls2085aqds.h | 2 ++ include/configs/ls2085ardb.h | 2 ++ 4 files changed, 29 insertions(+)
diff --git a/drivers/net/fsl-mc/mc.c b/drivers/net/fsl-mc/mc.c index d02da9d..2b38b50 100644 --- a/drivers/net/fsl-mc/mc.c +++ b/drivers/net/fsl-mc/mc.c @@ -321,6 +321,23 @@ static unsigned long get_mc_boot_timeout_ms(void) return timeout_ms; }
+#ifdef CONFIG_SYS_LS_MC_AIOP_IMG_IN_NOR +static int load_mc_aiop_img(u64 mc_ram_addr, size_t mc_ram_size) +{ + void *aiop_img; + + /* + * Load the MC AIOP image in the MC private DRAM block: + */ + + aiop_img = (void *)CONFIG_SYS_LS_MC_AIOP_IMG_ADDR; + mc_copy_image("MC AIOP image", + (u64)aiop_img, CONFIG_SYS_LS_MC_AIOP_IMG_MAX_LENGTH, + mc_ram_addr + CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET); + + return 0; +} +#endif static int wait_for_mc(bool booting_mc, u32 *final_reg_gsr) { u32 reg_gsr; @@ -440,6 +457,12 @@ int mc_init(void) if (error != 0) goto out;
+#ifdef CONFIG_SYS_LS_MC_AIOP_IMG_IN_NOR + error = load_mc_aiop_img(mc_ram_addr, mc_ram_size); + if (error != 0) + goto out; +#endif + debug("mc_ccsr_regs %p\n", mc_ccsr_regs); dump_mc_ccsr_regs(mc_ccsr_regs);
diff --git a/include/configs/ls2085a_common.h b/include/configs/ls2085a_common.h index cf51909..d095151 100644 --- a/include/configs/ls2085a_common.h +++ b/include/configs/ls2085a_common.h @@ -174,6 +174,8 @@ unsigned long long get_qixis_addr(void); #define CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET 0x00F00000 #define CONFIG_SYS_LS_MC_DPL_MAX_LENGTH 0x20000 #define CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET 0x00F20000 +#define CONFIG_SYS_LS_MC_AIOP_IMG_MAX_LENGTH 0x200000 +#define CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET 0x07000000
/* * Carve out a DDR region which will not be used by u-boot/Linux diff --git a/include/configs/ls2085aqds.h b/include/configs/ls2085aqds.h index 731eca2..3d9655d 100644 --- a/include/configs/ls2085aqds.h +++ b/include/configs/ls2085aqds.h @@ -261,6 +261,8 @@ unsigned long get_board_ddr_clk(void); #define CONFIG_SYS_LS_MC_DPC_ADDR 0x580800000ULL
#define CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS 5000 +#define CONFIG_SYS_LS_MC_AIOP_IMG_IN_NOR +#define CONFIG_SYS_LS_MC_AIOP_IMG_ADDR 0x580900000ULL
/* * I2C diff --git a/include/configs/ls2085ardb.h b/include/configs/ls2085ardb.h index a0f0f6c..9f0a96f 100644 --- a/include/configs/ls2085ardb.h +++ b/include/configs/ls2085ardb.h @@ -234,6 +234,8 @@ unsigned long get_board_sys_clk(void); #define CONFIG_SYS_LS_MC_DPC_ADDR 0x580800000ULL
#define CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS 5000 +#define CONFIG_SYS_LS_MC_AIOP_IMG_IN_NOR +#define CONFIG_SYS_LS_MC_AIOP_IMG_ADDR 0x580900000ULL
/* * I2C

Update flibs changes to mc-0.6.0.1 for dpmang, dprc, dpni and dpio objects Also rename qbman_portal_ce/ci_paddr to qbman_portal_ce/ci_offset in dpio_attr. These are now offsets from the SoC QBMan portals base.
Signed-off-by: J. German Rivera German.Rivera@freescale.com Signed-off-by: Prabhakar Kushwaha prabhakar@freescale.com --- Changes for v2: Sending as it is for patchset Changes for v3: Sending as it is for patchset Changes for v4: Sending as it is for patchset
drivers/net/fsl-mc/dpni.c | 2 +- drivers/net/fsl-mc/mc.c | 12 ++-- include/fsl-mc/fsl_dpio.h | 32 ++++------ include/fsl-mc/fsl_dpmng.h | 2 +- include/fsl-mc/fsl_dpni.h | 144 ++++++++++++++++++++++++++++++++++++++------- include/fsl-mc/fsl_dprc.h | 64 +++++++++++++++++--- include/fsl-mc/fsl_mc.h | 1 + 7 files changed, 199 insertions(+), 58 deletions(-)
diff --git a/drivers/net/fsl-mc/dpni.c b/drivers/net/fsl-mc/dpni.c index b384401..7bc2504 100644 --- a/drivers/net/fsl-mc/dpni.c +++ b/drivers/net/fsl-mc/dpni.c @@ -313,7 +313,7 @@ int dpni_set_counter(struct fsl_mc_io *mc_io,
int dpni_set_link_cfg(struct fsl_mc_io *mc_io, uint16_t token, - struct dpni_link_cfg *cfg) + const struct dpni_link_cfg *cfg) { struct mc_command cmd = { 0 };
diff --git a/drivers/net/fsl-mc/mc.c b/drivers/net/fsl-mc/mc.c index 2b38b50..2094595 100644 --- a/drivers/net/fsl-mc/mc.c +++ b/drivers/net/fsl-mc/mc.c @@ -610,14 +610,16 @@ int dpio_init(struct dprc_obj_desc obj_desc) printf("dpio_enable() failed %d\n", err); goto err_get_enable; } - debug("ce_paddr=0x%llx, ci_paddr=0x%llx, portalid=%d, prios=%d\n", - attr.qbman_portal_ce_paddr, - attr.qbman_portal_ci_paddr, + debug("ce_offset=0x%llx, ci_offset=0x%llx, portalid=%d, prios=%d\n", + attr.qbman_portal_ce_offset, + attr.qbman_portal_ci_offset, attr.qbman_portal_id, attr.num_priorities);
- p_des.cena_bar = (void *)attr.qbman_portal_ce_paddr; - p_des.cinh_bar = (void *)attr.qbman_portal_ci_paddr; + p_des.cena_bar = (void *)(SOC_QBMAN_PORTALS_BASE_ADDR + + attr.qbman_portal_ce_offset); + p_des.cinh_bar = (void *)(SOC_QBMAN_PORTALS_BASE_ADDR + + attr.qbman_portal_ci_offset);
dflt_dpio->sw_portal = qbman_swp_init(&p_des); if (dflt_dpio->sw_portal == NULL) { diff --git a/include/fsl-mc/fsl_dpio.h b/include/fsl-mc/fsl_dpio.h index e84b419..e779909 100644 --- a/include/fsl-mc/fsl_dpio.h +++ b/include/fsl-mc/fsl_dpio.h @@ -8,8 +8,8 @@ #define _FSL_DPIO_H
/* DPIO Version */ -#define DPIO_VER_MAJOR 2 -#define DPIO_VER_MINOR 1 +#define DPIO_VER_MAJOR 3 +#define DPIO_VER_MINOR 0
/* Command IDs */ #define DPIO_CMDID_CLOSE 0x800 @@ -31,8 +31,8 @@ do { \ MC_RSP_OP(cmd, 0, 32, 16, uint16_t, attr->qbman_portal_id);\ MC_RSP_OP(cmd, 0, 48, 8, uint8_t, attr->num_priorities);\ MC_RSP_OP(cmd, 0, 56, 4, enum dpio_channel_mode, attr->channel_mode);\ - MC_RSP_OP(cmd, 1, 0, 64, uint64_t, attr->qbman_portal_ce_paddr);\ - MC_RSP_OP(cmd, 2, 0, 64, uint64_t, attr->qbman_portal_ci_paddr);\ + MC_RSP_OP(cmd, 1, 0, 64, uint64_t, attr->qbman_portal_ce_offset);\ + MC_RSP_OP(cmd, 2, 0, 64, uint64_t, attr->qbman_portal_ci_offset);\ MC_RSP_OP(cmd, 3, 0, 16, uint16_t, attr->version.major);\ MC_RSP_OP(cmd, 3, 16, 16, uint16_t, attr->version.minor);\ } while (0) @@ -42,6 +42,7 @@ do { \ */
struct fsl_mc_io; + /** * dpio_open() - Open a control session for the specified object * @mc_io: Pointer to MC portal's I/O object @@ -61,18 +62,9 @@ struct fsl_mc_io; int dpio_open(struct fsl_mc_io *mc_io, int dpio_id, uint16_t *token);
/** - * dpio_open() - Open a control session for the specified object + * dpio_close() - Close the control session of the object * @mc_io: Pointer to MC portal's I/O object - * @dpio_id: DPIO 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 dpio_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. + * @token: Token of DPIO object * * Return: '0' on Success; Error code otherwise. */ @@ -121,10 +113,8 @@ int dpio_reset(struct fsl_mc_io *mc_io, uint16_t token); * struct dpio_attr - Structure representing DPIO attributes * @id: DPIO object ID * @version: DPIO version - * @qbman_portal_ce_paddr: Physical address of the software portal - * cache-enabled area - * @qbman_portal_ci_paddr: Physical address of the software portal - * cache-inhibited area + * @qbman_portal_ce_offset: offset of the software portal cache-enabled area + * @qbman_portal_ci_offset: offset of the software portal cache-inhibited area * @qbman_portal_id: Software portal ID * @channel_mode: Notification channel mode * @num_priorities: Number of priorities for the notification channel (1-8); @@ -141,8 +131,8 @@ struct dpio_attr { uint16_t major; uint16_t minor; } version; - uint64_t qbman_portal_ce_paddr; - uint64_t qbman_portal_ci_paddr; + uint64_t qbman_portal_ce_offset; + uint64_t qbman_portal_ci_offset; uint16_t qbman_portal_id; enum dpio_channel_mode channel_mode; uint8_t num_priorities; diff --git a/include/fsl-mc/fsl_dpmng.h b/include/fsl-mc/fsl_dpmng.h index 986e7c8..6feb292 100644 --- a/include/fsl-mc/fsl_dpmng.h +++ b/include/fsl-mc/fsl_dpmng.h @@ -14,7 +14,7 @@ struct fsl_mc_io; /** * Management Complex firmware version information */ -#define MC_VER_MAJOR 6 +#define MC_VER_MAJOR 7 #define MC_VER_MINOR 0
/** diff --git a/include/fsl-mc/fsl_dpni.h b/include/fsl-mc/fsl_dpni.h index 67c087d..26b67f0 100644 --- a/include/fsl-mc/fsl_dpni.h +++ b/include/fsl-mc/fsl_dpni.h @@ -7,7 +7,7 @@ #define _FSL_DPNI_H
/* DPNI Version */ -#define DPNI_VER_MAJOR 4 +#define DPNI_VER_MAJOR 5 #define DPNI_VER_MINOR 0
/* Command IDs */ @@ -78,7 +78,7 @@ do { \ MC_RSP_OP(cmd, 0, 32, 8, uint8_t, attr->max_tcs); \ MC_RSP_OP(cmd, 0, 40, 8, uint8_t, attr->max_senders); \ MC_RSP_OP(cmd, 0, 48, 8, enum net_prot, attr->start_hdr); \ - MC_RSP_OP(cmd, 1, 0, 64, uint64_t, attr->options); \ + MC_RSP_OP(cmd, 1, 0, 32, uint32_t, attr->options); \ MC_RSP_OP(cmd, 2, 0, 8, uint8_t, attr->max_unicast_filters); \ MC_RSP_OP(cmd, 2, 8, 8, uint8_t, attr->max_multicast_filters);\ MC_RSP_OP(cmd, 2, 16, 8, uint8_t, attr->max_vlan_filters); \ @@ -98,7 +98,9 @@ do { \ MC_RSP_OP(cmd, 4, 16, 16, uint16_t, \ attr->ipr_cfg.min_frag_size_ipv4); \ MC_RSP_OP(cmd, 4, 32, 16, uint16_t, \ - attr->ipr_cfg.min_frag_size_ipv6); \ + attr->ipr_cfg.min_frag_size_ipv6);\ + MC_RSP_OP(cmd, 4, 48, 8, uint8_t, attr->max_policers); \ + MC_RSP_OP(cmd, 4, 56, 8, uint8_t, attr->max_congestion_ctrl); \ MC_RSP_OP(cmd, 5, 0, 16, uint16_t, \ attr->ipr_cfg.max_open_frames_ipv4); \ MC_RSP_OP(cmd, 5, 16, 16, uint16_t, \ @@ -208,7 +210,7 @@ do { \ /* cmd, param, offset, width, type, arg_name */ #define DPNI_CMD_SET_LINK_CFG(cmd, cfg) \ do { \ - MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->rate);\ + MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->rate);\ MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->options);\ } while (0)
@@ -216,7 +218,7 @@ do { \ #define DPNI_RSP_GET_LINK_STATE(cmd, state) \ do { \ MC_RSP_OP(cmd, 0, 32, 1, int, state->up);\ - MC_RSP_OP(cmd, 1, 0, 64, uint64_t, state->rate);\ + MC_RSP_OP(cmd, 1, 0, 32, uint32_t, state->rate);\ MC_RSP_OP(cmd, 2, 0, 64, uint64_t, state->options);\ } while (0)
@@ -326,6 +328,13 @@ do { \ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->user_ctx); \ MC_CMD_OP(cmd, 2, 16, 8, uint8_t, tc_id); \ MC_CMD_OP(cmd, 2, 32, 32, uint32_t, cfg->options); \ + MC_CMD_OP(cmd, 3, 0, 4, enum dpni_flc_type, cfg->flc_cfg.flc_type); \ + MC_CMD_OP(cmd, 3, 4, 4, enum dpni_stash_size, \ + cfg->flc_cfg.frame_data_size);\ + MC_CMD_OP(cmd, 3, 8, 4, enum dpni_stash_size, \ + cfg->flc_cfg.flow_context_size);\ + MC_CMD_OP(cmd, 3, 32, 32, uint32_t, cfg->flc_cfg.options);\ + MC_CMD_OP(cmd, 4, 0, 64, uint64_t, cfg->flc_cfg.flow_context);\ } while (0)
/* cmd, param, offset, width, type, arg_name */ @@ -343,6 +352,13 @@ do { \ MC_RSP_OP(cmd, 0, 40, 2, enum dpni_dest, attr->dest_cfg.dest_type); \ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, attr->user_ctx); \ MC_RSP_OP(cmd, 2, 32, 32, uint32_t, attr->fqid); \ + MC_RSP_OP(cmd, 3, 0, 4, enum dpni_flc_type, attr->flc_cfg.flc_type); \ + MC_RSP_OP(cmd, 3, 4, 4, enum dpni_stash_size, \ + attr->flc_cfg.frame_data_size);\ + MC_RSP_OP(cmd, 3, 8, 4, enum dpni_stash_size, \ + attr->flc_cfg.flow_context_size);\ + MC_RSP_OP(cmd, 3, 32, 32, uint32_t, attr->flc_cfg.options);\ + MC_RSP_OP(cmd, 4, 0, 64, uint64_t, attr->flc_cfg.flow_context);\ } while (0)
enum net_prot { @@ -399,7 +415,8 @@ enum net_prot { NET_PROT_DUMMY_LAST };
-/* Data Path Network Interface API +/** + * Data Path Network Interface API * Contains initialization APIs and runtime control APIs for DPNI */
@@ -545,6 +562,8 @@ int dpni_reset(struct fsl_mc_io *mc_io, uint16_t token); * @max_qos_entries: if 'max_tcs > 1', declares the maximum entries in QoS table * @max_qos_key_size: Maximum key size for the QoS look-up * @max_dist_key_size: Maximum key size for the distribution look-up + * @max_policers: Maximum number of policers; + * @max_congestion_ctrl: Maximum number of congestion control groups (CGs); * @ipr_cfg: IP reassembly configuration */ struct dpni_attr { @@ -559,7 +578,7 @@ struct dpni_attr { uint16_t minor; } version; enum net_prot start_hdr; - uint64_t options; + uint32_t options; uint8_t max_senders; uint8_t max_tcs; uint8_t max_dist_per_tc[DPNI_MAX_TC]; @@ -569,8 +588,11 @@ struct dpni_attr { uint8_t max_qos_entries; uint8_t max_qos_key_size; uint8_t max_dist_key_size; + uint8_t max_policers; + uint8_t max_congestion_ctrl; struct dpni_ipr_cfg ipr_cfg; }; + /** * dpni_get_attributes() - Retrieve DPNI attributes. * @mc_io: Pointer to MC portal's I/O objec @@ -634,6 +656,7 @@ struct dpni_buffer_layout { int dpni_get_rx_buffer_layout(struct fsl_mc_io *mc_io, uint16_t token, struct dpni_buffer_layout *layout); + /** * dpni_set_rx_buffer_layout() - Set Rx buffer layout configuration. * @mc_io: Pointer to MC portal's I/O object @@ -661,19 +684,19 @@ int dpni_get_tx_buffer_layout(struct fsl_mc_io *mc_io, struct dpni_buffer_layout *layout);
/** - * @brief Set Tx buffer layout configuration. - * - * @param[in] mc_io Pointer to MC portal's I/O object - * @param[in] token Token of DPNI object - * @param[in] layout Buffer layout configuration + * dpni_set_tx_buffer_layout() - Set Tx buffer layout configuration. + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPNI object + * @layout: Buffer layout configuration * - * @returns '0' on Success; Error code otherwise. + * Return: '0' on Success; Error code otherwise. * * @warning Allowed only when DPNI is disabled */ int dpni_set_tx_buffer_layout(struct fsl_mc_io *mc_io, uint16_t token, const struct dpni_buffer_layout *layout); + /** * dpni_get_tx_conf_buffer_layout() - Retrieve Tx confirmation buffer layout * attributes. @@ -686,6 +709,7 @@ int dpni_set_tx_buffer_layout(struct fsl_mc_io *mc_io, int dpni_get_tx_conf_buffer_layout(struct fsl_mc_io *mc_io, uint16_t token, struct dpni_buffer_layout *layout); + /** * dpni_set_tx_conf_buffer_layout() - Set Tx confirmation buffer layout * configuration. @@ -700,15 +724,16 @@ int dpni_get_tx_conf_buffer_layout(struct fsl_mc_io *mc_io, int dpni_set_tx_conf_buffer_layout(struct fsl_mc_io *mc_io, uint16_t token, const struct dpni_buffer_layout *layout); + /** - * dpni_get_spid() - Get the AIOP storage profile ID associated with the DPNI + * dpni_get_qdid() - Get the Queuing Destination ID (QDID) that should be used + * for enqueue operations * @mc_io: Pointer to MC portal's I/O object * @token: Token of DPNI object - * @spid: Returned aiop storage-profile ID + * @qdid: Returned virtual QDID value that should be used as an argument + * in all enqueue operations * * Return: '0' on Success; Error code otherwise. - * - * @warning Only relevant for DPNI that belongs to AIOP container. */ int dpni_get_qdid(struct fsl_mc_io *mc_io, uint16_t token, uint16_t *qdid);
@@ -781,13 +806,23 @@ int dpni_set_counter(struct fsl_mc_io *mc_io, uint16_t token, enum dpni_counter counter, uint64_t value); + +/* Enable auto-negotiation */ +#define DPNI_LINK_OPT_AUTONEG 0x0000000000000001ULL +/* Enable half-duplex mode */ +#define DPNI_LINK_OPT_HALF_DUPLEX 0x0000000000000002ULL +/* Enable pause frames */ +#define DPNI_LINK_OPT_PAUSE 0x0000000000000004ULL +/* Enable a-symmetric pause frames */ +#define DPNI_LINK_OPT_ASYM_PAUSE 0x0000000000000008ULL + /** * struct - Structure representing DPNI link configuration * @rate: Rate * @options: Mask of available options; use 'DPNI_LINK_OPT_<X>' values */ struct dpni_link_cfg { - uint64_t rate; + uint32_t rate; uint64_t options; };
@@ -801,7 +836,7 @@ struct dpni_link_cfg { */ int dpni_set_link_cfg(struct fsl_mc_io *mc_io, uint16_t token, - struct dpni_link_cfg *cfg); + const struct dpni_link_cfg *cfg);
/** * struct dpni_link_state - Structure representing DPNI link state @@ -810,7 +845,7 @@ int dpni_set_link_cfg(struct fsl_mc_io *mc_io, * @up: Link state; '0' for down, '1' for up */ struct dpni_link_state { - uint64_t rate; + uint32_t rate; uint64_t options; int up; }; @@ -838,6 +873,7 @@ int dpni_get_link_state(struct fsl_mc_io *mc_io, int dpni_set_primary_mac_addr(struct fsl_mc_io *mc_io, uint16_t token, const uint8_t mac_addr[6]); + /** * dpni_get_primary_mac_addr() - Get the primary MAC address * @mc_io: Pointer to MC portal's I/O object @@ -849,6 +885,7 @@ int dpni_set_primary_mac_addr(struct fsl_mc_io *mc_io, int dpni_get_primary_mac_addr(struct fsl_mc_io *mc_io, uint16_t token, uint8_t mac_addr[6]); + /** * dpni_add_mac_addr() - Add MAC address filter * @mc_io: Pointer to MC portal's I/O object @@ -875,7 +912,7 @@ int dpni_remove_mac_addr(struct fsl_mc_io *mc_io,
/** * enum dpni_dest - DPNI destination types - * DPNI_DEST_NONE: Unassigned destination; The queue is set in parked mode and + * @DPNI_DEST_NONE: Unassigned destination; The queue is set in parked mode and * does not generate FQDAN notifications; user is expected to * dequeue from the queue based on polling or other user-defined * method @@ -906,12 +943,69 @@ struct dpni_dest_cfg { uint8_t priority; };
+/** + * enum dpni_flc_type - DPNI FLC types + * @DPNI_FLC_USER_DEFINED: select the FLC to be used for user defined value + * @DPNI_FLC_STASH: select the FLC to be used for stash control + */ +enum dpni_flc_type { + DPNI_FLC_USER_DEFINED = 0, + DPNI_FLC_STASH = 1, +}; + +/** + * enum dpni_stash_size - DPNI FLC stashing size + * @DPNI_STASH_SIZE_0B: no stash + * @DPNI_STASH_SIZE_64B: stashes 64 bytes + * @DPNI_STASH_SIZE_128B: stashes 128 bytes + * @DPNI_STASH_SIZE_192B: stashes 192 bytes + */ +enum dpni_stash_size { + DPNI_STASH_SIZE_0B = 0, + DPNI_STASH_SIZE_64B = 1, + DPNI_STASH_SIZE_128B = 2, + DPNI_STASH_SIZE_192B = 3, +}; + +/* DPNI FLC stash options */ + +/* stashes the whole annotation area (up to 192 bytes) */ +#define DPNI_FLC_STASH_FRAME_ANNOTATION 0x00000001 + +/** + * struct dpni_flc_cfg - Structure representing DPNI FLC configuration + * @flc_type: FLC type + * @options: Mask of available options; + * use 'DPNI_FLC_STASH_<X>' values + * @frame_data_size: Size of frame data to be stashed + * @flow_context_size: Size of flow context to be stashed + * @flow_context: 1. In case flc_type is 'DPNI_FLC_USER_DEFINED': + * this value will be provided in the frame descriptor + * (FD[FLC]) + * 2. In case flc_type is 'DPNI_FLC_STASH': + * this value will be I/O virtual address of the + * flow-context; + * Must be cacheline-aligned and DMA-able memory + */ +struct dpni_flc_cfg { + enum dpni_flc_type flc_type; + uint32_t options; + enum dpni_stash_size frame_data_size; + enum dpni_stash_size flow_context_size; + uint64_t flow_context; +}; + /* DPNI queue modification options */
/* Select to modify the user's context associated with the queue */ #define DPNI_QUEUE_OPT_USER_CTX 0x00000001 /* Select to modify the queue's destination */ #define DPNI_QUEUE_OPT_DEST 0x00000002 +/** Select to modify the flow-context parameters; + * not applicable for Tx-conf/Err queues as the FD comes from the user + */ +#define DPNI_QUEUE_OPT_FLC 0x00000004 +
/** * struct dpni_queue_cfg - Structure representing queue configuration @@ -922,11 +1016,17 @@ struct dpni_dest_cfg { * is contained in 'options' * @dest_cfg: Queue destination parameters; * valid only if 'DPNI_QUEUE_OPT_DEST' is contained in 'options' + * @flc_cfg: Flow context configuration; in case the TC's distribution + * is either NONE or HASH the FLC's settings of flow#0 are used. + * in the case of FS (flow-steering) the flow's FLC settings + * are used. + * valid only if 'DPNI_QUEUE_OPT_FLC' is contained in 'options' */ struct dpni_queue_cfg { uint32_t options; uint64_t user_ctx; struct dpni_dest_cfg dest_cfg; + struct dpni_flc_cfg flc_cfg; };
/** @@ -934,11 +1034,13 @@ struct dpni_queue_cfg { * @user_ctx: User context value provided in the frame descriptor of each * dequeued frame * @dest_cfg: Queue destination configuration + * @flc_cfg: Flow context configuration * @fqid: Virtual fqid value to be used for dequeue operations */ struct dpni_queue_attr { uint64_t user_ctx; struct dpni_dest_cfg dest_cfg; + struct dpni_flc_cfg flc_cfg; uint32_t fqid; };
diff --git a/include/fsl-mc/fsl_dprc.h b/include/fsl-mc/fsl_dprc.h index f837e89..26a4598 100644 --- a/include/fsl-mc/fsl_dprc.h +++ b/include/fsl-mc/fsl_dprc.h @@ -10,7 +10,7 @@ #define _FSL_DPRC_H
/* DPRC Version */ -#define DPRC_VER_MAJOR 2 +#define DPRC_VER_MAJOR 4 #define DPRC_VER_MINOR 0
/* Command IDs */ @@ -88,6 +88,22 @@ do { \ MC_RSP_OP(cmd, 4, 40, 8, char, obj_desc->type[13]);\ MC_RSP_OP(cmd, 4, 48, 8, char, obj_desc->type[14]);\ MC_RSP_OP(cmd, 4, 56, 8, char, obj_desc->type[15]);\ + MC_RSP_OP(cmd, 5, 0, 8, char, obj_desc->label[0]);\ + MC_RSP_OP(cmd, 5, 8, 8, char, obj_desc->label[1]);\ + MC_RSP_OP(cmd, 5, 16, 8, char, obj_desc->label[2]);\ + MC_RSP_OP(cmd, 5, 24, 8, char, obj_desc->label[3]);\ + MC_RSP_OP(cmd, 5, 32, 8, char, obj_desc->label[4]);\ + MC_RSP_OP(cmd, 5, 40, 8, char, obj_desc->label[5]);\ + MC_RSP_OP(cmd, 5, 48, 8, char, obj_desc->label[6]);\ + MC_RSP_OP(cmd, 5, 56, 8, char, obj_desc->label[7]);\ + MC_RSP_OP(cmd, 6, 0, 8, char, obj_desc->label[8]);\ + MC_RSP_OP(cmd, 6, 8, 8, char, obj_desc->label[9]);\ + MC_RSP_OP(cmd, 6, 16, 8, char, obj_desc->label[10]);\ + MC_RSP_OP(cmd, 6, 24, 8, char, obj_desc->label[11]);\ + MC_RSP_OP(cmd, 6, 32, 8, char, obj_desc->label[12]);\ + MC_RSP_OP(cmd, 6, 40, 8, char, obj_desc->label[13]);\ + MC_RSP_OP(cmd, 6, 48, 8, char, obj_desc->label[14]);\ + MC_RSP_OP(cmd, 6, 56, 8, char, obj_desc->label[15]);\ } while (0)
/* cmd, param, offset, width, type, arg_name */ @@ -175,11 +191,33 @@ do { \ /* param, offset, width, type, arg_name */ #define DPRC_RSP_GET_OBJ_REGION(cmd, region_desc) \ do { \ - MC_RSP_OP(cmd, 1, 0, 64, uint64_t, region_desc->base_paddr);\ + MC_RSP_OP(cmd, 1, 0, 64, uint64_t, region_desc->base_offset);\ MC_RSP_OP(cmd, 2, 0, 32, uint32_t, region_desc->size); \ } while (0)
/* cmd, param, offset, width, type, arg_name */ +#define DPRC_CMD_SET_OBJ_LABEL(cmd, obj_index, label) \ +do { \ + MC_CMD_OP(cmd, 0, 0, 32, int, obj_index); \ + MC_CMD_OP(cmd, 1, 0, 8, char, label[0]);\ + MC_CMD_OP(cmd, 1, 8, 8, char, label[1]);\ + MC_CMD_OP(cmd, 1, 16, 8, char, label[2]);\ + MC_CMD_OP(cmd, 1, 24, 8, char, label[3]);\ + MC_CMD_OP(cmd, 1, 32, 8, char, label[4]);\ + MC_CMD_OP(cmd, 1, 40, 8, char, label[5]);\ + MC_CMD_OP(cmd, 1, 48, 8, char, label[6]);\ + MC_CMD_OP(cmd, 1, 56, 8, char, label[7]);\ + MC_CMD_OP(cmd, 2, 0, 8, char, label[8]);\ + MC_CMD_OP(cmd, 2, 8, 8, char, label[9]);\ + MC_CMD_OP(cmd, 2, 16, 8, char, label[10]);\ + MC_CMD_OP(cmd, 2, 24, 8, char, label[11]);\ + MC_CMD_OP(cmd, 2, 32, 8, char, label[12]);\ + MC_CMD_OP(cmd, 2, 40, 8, char, label[13]);\ + MC_CMD_OP(cmd, 2, 48, 8, char, label[14]);\ + MC_CMD_OP(cmd, 2, 56, 8, char, label[15]);\ +} while (0) + +/* cmd, param, offset, width, type, arg_name */ #define DPRC_CMD_CONNECT(cmd, endpoint1, endpoint2) \ do { \ MC_CMD_OP(cmd, 0, 0, 32, int, endpoint1->id); \ @@ -294,6 +332,7 @@ do { \ /* Data Path Resource Container API * Contains DPRC API for managing and querying DPAA resources */ + struct fsl_mc_io;
/** @@ -366,7 +405,7 @@ int dprc_close(struct fsl_mc_io *mc_io, uint16_t token); /* Object initialization allowed - software context associated with this * container is allowed to invoke object initialization operations. */ -#define DPRC_CFG_OPT_OBJ_CREATE_ALLOWED 0x00000004 +#define DPRC_CFG_OPT_OBJ_CREATE_ALLOWED 0x00000004
/* Topology change allowed - software context associated with this * container is allowed to invoke topology operations, such as attach/detach @@ -389,11 +428,13 @@ int dprc_close(struct fsl_mc_io *mc_io, uint16_t token); * @portal_id: Portal ID; if set to 'DPRC_GET_PORTAL_ID_FROM_POOL', a free * portal ID is allocated by the DPRC * @options: Combination of 'DPRC_CFG_OPT_<X>' options + * @label: Object's label */ struct dprc_cfg { uint16_t icid; int portal_id; uint64_t options; + char label[16]; };
/** @@ -484,6 +525,7 @@ int dprc_get_obj_count(struct fsl_mc_io *mc_io, uint16_t token, int *obj_count); * @irq_count: Number of interrupts supported by the object * @region_count: Number of mappable regions supported by the object * @state: Object state: combination of DPRC_OBJ_STATE_ states + * @label: Object label */ struct dprc_obj_desc { char type[16]; @@ -494,6 +536,7 @@ struct dprc_obj_desc { uint8_t irq_count; uint8_t region_count; uint32_t state; + char label[16]; };
/** @@ -516,8 +559,8 @@ int dprc_get_obj(struct fsl_mc_io *mc_io, struct dprc_obj_desc *obj_desc);
/** - * dprc_get_res_count() - Obtains the number of free resources that are assigned - * to this container, by pool type + * 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 * @token: Token of DPRC object * @type: pool type @@ -574,11 +617,14 @@ int dprc_get_res_ids(struct fsl_mc_io *mc_io,
/** * struct dprc_region_desc - Mappable region descriptor - * @base_paddr: Region base physical address + * @base_offset: Region offset from region's base address. + * For DPMCP and DPRC objects, region base is offset from SoC MC portals + * base address; For DPIO, region base is offset from SoC QMan portals + * base address * @size: Region size (in bytes) */ struct dprc_region_desc { - uint64_t base_paddr; + uint64_t base_offset; uint32_t size; };
@@ -642,8 +688,8 @@ int dprc_disconnect(struct fsl_mc_io *mc_io, /** * dprc_get_connection() - Get connected endpoint and link status if connection * exists. -* @mc_io Pointer to MC portal's I/O object -* @token Token of DPRC object +* @mc_io Pointer to MC portal's I/O object +* @token Token of DPRC object * @endpoint1 Endpoint 1 configuration parameters * @endpoint2 Returned endpoint 2 configuration parameters * @state: Returned link state: 1 - link is up, 0 - link is down diff --git a/include/fsl-mc/fsl_mc.h b/include/fsl-mc/fsl_mc.h index ec24415..0e799f5 100644 --- a/include/fsl-mc/fsl_mc.h +++ b/include/fsl-mc/fsl_mc.h @@ -27,6 +27,7 @@ (MCFAPR_PL_MASK | MCFAPR_BMT_MASK)
#define SOC_MC_PORTALS_BASE_ADDR ((void __iomem *)0x00080C000000) +#define SOC_QBMAN_PORTALS_BASE_ADDR ((void __iomem *)0x000818000000) #define SOC_MC_PORTAL_STRIDE 0x10000
#define SOC_MC_PORTAL_ADDR(_portal_id) \

Update qbman driver - As per latest available qbman driver - Use of atomic APIs
Signed-off-by: Prabhakar Kushwaha prabhakar@freescale.com CC: Geoff Thorpe Geoff.Thorpe@freescale.com CC: Haiying Wang Haiying.Wang@freescale.com CC: Roy Pledge Roy.Pledge@freescale.com --- Changes for v2: Sending as it is for patchset Changes for v3: Sending as it is for patchset Changes for v4: Sending as it is for patchset
drivers/net/fsl-mc/dpio/qbman_portal.c | 66 ++++++++++++++++++--------------- drivers/net/fsl-mc/dpio/qbman_portal.h | 22 ++++++++--- drivers/net/fsl-mc/dpio/qbman_private.h | 2 +- 3 files changed, 53 insertions(+), 37 deletions(-)
diff --git a/drivers/net/fsl-mc/dpio/qbman_portal.c b/drivers/net/fsl-mc/dpio/qbman_portal.c index dd2a7de..5fa8d95 100644 --- a/drivers/net/fsl-mc/dpio/qbman_portal.c +++ b/drivers/net/fsl-mc/dpio/qbman_portal.c @@ -64,7 +64,7 @@ enum qbman_sdqcr_fc { struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) { int ret; - struct qbman_swp *p = kmalloc(sizeof(*p), GFP_KERNEL); + struct qbman_swp *p = malloc(sizeof(struct qbman_swp));
if (!p) return NULL; @@ -77,7 +77,7 @@ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) qb_attr_code_encode(&code_sdqcr_dct, &p->sdq, qbman_sdqcr_dct_prio_ics); qb_attr_code_encode(&code_sdqcr_fc, &p->sdq, qbman_sdqcr_fc_up_to_3); qb_attr_code_encode(&code_sdqcr_tok, &p->sdq, 0xbb); - p->vdq.busy = 0; /* TODO: convert to atomic_t */ + atomic_set(&p->vdq.busy, 1); p->vdq.valid_bit = QB_VALID_BIT; p->dqrr.next_idx = 0; p->dqrr.valid_bit = QB_VALID_BIT; @@ -165,7 +165,6 @@ static struct qb_attr_code code_eq_qd_bin = QB_CODE(4, 0, 16); static struct qb_attr_code code_eq_qd_pri = QB_CODE(4, 16, 4); static struct qb_attr_code code_eq_rsp_stash = QB_CODE(5, 16, 1); static struct qb_attr_code code_eq_rsp_lo = QB_CODE(6, 0, 32); -static struct qb_attr_code code_eq_rsp_hi = QB_CODE(7, 0, 32);
enum qbman_eq_cmd_e { /* No enqueue, primarily for plugging ORP gaps for dropped frames */ @@ -197,8 +196,7 @@ void qbman_eq_desc_set_response(struct qbman_eq_desc *d, { uint32_t *cl = qb_cl(d);
- qb_attr_code_encode(&code_eq_rsp_lo, cl, lower32(storage_phys)); - qb_attr_code_encode(&code_eq_rsp_hi, cl, upper32(storage_phys)); + qb_attr_code_encode_64(&code_eq_rsp_lo, (uint64_t *)cl, storage_phys); qb_attr_code_encode(&code_eq_rsp_stash, cl, !!stash); }
@@ -253,7 +251,6 @@ static struct qb_attr_code code_pull_numframes = QB_CODE(0, 8, 4); static struct qb_attr_code code_pull_token = QB_CODE(0, 16, 8); static struct qb_attr_code code_pull_dqsource = QB_CODE(1, 0, 24); static struct qb_attr_code code_pull_rsp_lo = QB_CODE(2, 0, 32); -static struct qb_attr_code code_pull_rsp_hi = QB_CODE(3, 0, 32);
enum qb_pull_dt_e { qb_pull_dt_channel, @@ -282,8 +279,7 @@ void qbman_pull_desc_set_storage(struct qbman_pull_desc *d, } qb_attr_code_encode(&code_pull_rls, cl, 1); qb_attr_code_encode(&code_pull_stash, cl, !!stash); - qb_attr_code_encode(&code_pull_rsp_lo, cl, lower32(storage_phys)); - qb_attr_code_encode(&code_pull_rsp_hi, cl, upper32(storage_phys)); + qb_attr_code_encode_64(&code_pull_rsp_lo, (uint64_t *)cl, storage_phys); }
void qbman_pull_desc_set_numframes(struct qbman_pull_desc *d, uint8_t numframes) @@ -316,10 +312,10 @@ int qbman_swp_pull(struct qbman_swp *s, struct qbman_pull_desc *d) uint32_t *p; uint32_t *cl = qb_cl(d);
- /* TODO: convert to atomic_t */ - if (s->vdq.busy) + if (!atomic_dec_and_test(&s->vdq.busy)) { + atomic_inc(&s->vdq.busy); return -EBUSY; - s->vdq.busy = 1; + } s->vdq.storage = *(void **)&cl[4]; s->vdq.token = qb_attr_code_decode(&code_pull_token, cl); p = qbman_cena_write_start(&s->sys, QBMAN_CENA_SWP_VDQCR); @@ -359,36 +355,44 @@ const struct ldpaa_dq *qbman_swp_dqrr_next(struct qbman_swp *s) { uint32_t verb; uint32_t response_verb; - const struct ldpaa_dq *dq = qbman_cena_read(&s->sys, - QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)); - const uint32_t *p = qb_cl(dq); + uint32_t flags; + const struct ldpaa_dq *dq; + const uint32_t *p;
+ dq = qbman_cena_read(&s->sys, QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)); + p = qb_cl(dq); verb = qb_attr_code_decode(&code_dqrr_verb, p); - /* If the valid-bit isn't of the expected polarity, nothing there */ + + /* If the valid-bit isn't of the expected polarity, nothing there. Note, + * in the DQRR reset bug workaround, we shouldn't need to skip these + * check, because we've already determined that a new entry is available + * and we've invalidated the cacheline before reading it, so the + * valid-bit behaviour is repaired and should tell us what we already + * knew from reading PI. + */ if ((verb & QB_VALID_BIT) != s->dqrr.valid_bit) { qbman_cena_invalidate_prefetch(&s->sys, - QBMAN_CENA_SWP_DQRR( - s->dqrr.next_idx)); + QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)); return NULL; } /* There's something there. Move "next_idx" attention to the next ring * entry (and prefetch it) before returning what we found. */ s->dqrr.next_idx++; - s->dqrr.next_idx &= 3; /* Wrap around at 4 */ + s->dqrr.next_idx &= QBMAN_DQRR_SIZE - 1; /* Wrap around at 4 */ /* TODO: it's possible to do all this without conditionals, optimise it * later. */ if (!s->dqrr.next_idx) s->dqrr.valid_bit ^= QB_VALID_BIT; - /* VDQCR "no longer busy" hook - if VDQCR shows "busy" and this is a - * VDQCR result, mark it as non-busy. */ - if (s->vdq.busy) { - uint32_t flags = ldpaa_dq_flags(dq); - - response_verb = qb_attr_code_decode(&code_dqrr_response, &verb); - if ((response_verb == QBMAN_DQRR_RESPONSE_DQ) && - (flags & LDPAA_DQ_STAT_VOLATILE)) - s->vdq.busy = 0; - } + + /* If this is the final response to a volatile dequeue command + indicate that the vdq is no longer busy */ + flags = ldpaa_dq_flags(dq); + response_verb = qb_attr_code_decode(&code_dqrr_response, &verb); + if ((response_verb == QBMAN_DQRR_RESPONSE_DQ) && + (flags & LDPAA_DQ_STAT_VOLATILE) && + (flags & LDPAA_DQ_STAT_EXPIRED)) + atomic_inc(&s->vdq.busy); + qbman_cena_invalidate_prefetch(&s->sys, QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)); return dq; @@ -448,8 +452,10 @@ int qbman_dq_entry_has_newtoken(struct qbman_swp *s, * reset "busy". We instead base the decision on whether the current * result is sitting at the first 'storage' location of the busy * command. */ - if (s->vdq.busy && (s->vdq.storage == dq)) - s->vdq.busy = 0; + if (s->vdq.storage == dq) { + s->vdq.storage = NULL; + atomic_inc(&s->vdq.busy); + } return 1; }
diff --git a/drivers/net/fsl-mc/dpio/qbman_portal.h b/drivers/net/fsl-mc/dpio/qbman_portal.h index bb67c3b..86e2c3a 100644 --- a/drivers/net/fsl-mc/dpio/qbman_portal.h +++ b/drivers/net/fsl-mc/dpio/qbman_portal.h @@ -14,6 +14,10 @@ /* Management command result codes */ #define QBMAN_MC_RSLT_OK 0xf0
+/* TBD: as of QBMan 4.1, DQRR will be 8 rather than 4! */ +#define QBMAN_DQRR_SIZE 4 + + /* --------------------- */ /* portal data structure */ /* --------------------- */ @@ -48,14 +52,13 @@ struct qbman_swp { * to whether or not a command can be submitted, not whether or * not a previously-submitted command is still executing. In * other words, once proof is seen that the previously-submitted - * command is executing, "vdq" is no longer "busy". TODO: - * convert this to "atomic_t" so that it is thread-safe (without - * locking). */ - int busy; + * command is executing, "vdq" is no longer "busy". + */ + atomic_t busy; uint32_t valid_bit; /* 0x00 or 0x80 */ /* We need to determine when vdq is no longer busy. This depends * on whether the "busy" (last-submitted) dequeue command is - * targetting DQRR or main-memory, and detected is based on the + * targeting DQRR or main-memory, and detected is based on the * presence of the dequeue command's "token" showing up in * dequeue entries in DQRR or main-memory (respectively). Debug * builds will, when submitting vdq commands, verify that the @@ -127,6 +130,7 @@ static inline uint32_t qb_attr_code_decode(const struct qb_attr_code *code, return d32_uint32_t(code->lsoffset, code->width, cacheline[code->word]); }
+ /* encode a field to a cacheline */ static inline void qb_attr_code_encode(const struct qb_attr_code *code, uint32_t *cacheline, uint32_t val) @@ -136,6 +140,12 @@ static inline void qb_attr_code_encode(const struct qb_attr_code *code, | e32_uint32_t(code->lsoffset, code->width, val); }
+static inline void qb_attr_code_encode_64(const struct qb_attr_code *code, + uint64_t *cacheline, uint64_t val) +{ + cacheline[code->word / 2] = val; +} + /* ---------------------- */ /* Descriptors/cachelines */ /* ---------------------- */ @@ -144,7 +154,7 @@ static inline void qb_attr_code_encode(const struct qb_attr_code *code, * a "descriptor" type that the caller can instantiate however they like. * Ultimately though, it is just a cacheline of binary storage (or something * smaller when it is known that the descriptor doesn't need all 64 bytes) for - * holding pre-formatted pieces of harware commands. The performance-critical + * holding pre-formatted pieces of hardware commands. The performance-critical * code can then copy these descriptors directly into hardware command * registers more efficiently than trying to construct/format commands * on-the-fly. The API user sees the descriptor as an array of 32-bit words in diff --git a/drivers/net/fsl-mc/dpio/qbman_private.h b/drivers/net/fsl-mc/dpio/qbman_private.h index 2d2556b..f1f16b8 100644 --- a/drivers/net/fsl-mc/dpio/qbman_private.h +++ b/drivers/net/fsl-mc/dpio/qbman_private.h @@ -9,7 +9,7 @@ #include <errno.h> #include <asm/io.h> #include <linux/types.h> -#include <linux/compat.h> +#include <asm/atomic.h> #include <malloc.h> #include <fsl-mc/fsl_qbman_base.h>

Management complex major version should match to the firmware present in flash.
Return error during mismatch of major version.
Signed-off-by: Prabhakar Kushwaha prabhakar@freescale.com --- Changes for v2: Sending as it is for patchset Changes for v3: Incorporated Joe Hershberger's comments - Use ENODEV instead of "1" Changes for v4: Incorporated Joe Hershberger's comments - Use -ENODEV
drivers/net/fsl-mc/mc.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/net/fsl-mc/mc.c b/drivers/net/fsl-mc/mc.c index 2094595..b2babfb 100644 --- a/drivers/net/fsl-mc/mc.c +++ b/drivers/net/fsl-mc/mc.c @@ -518,9 +518,14 @@ int mc_init(void) goto out; }
- if (MC_VER_MAJOR != mc_ver_info.major) + if (MC_VER_MAJOR != mc_ver_info.major) { printf("fsl-mc: ERROR: Firmware major version mismatch (found: %d, expected: %d)\n", mc_ver_info.major, MC_VER_MAJOR); + printf("fsl-mc: Update the Management Complex firmware\n"); + + error = -ENODEV; + goto out; + }
if (MC_VER_MINOR != mc_ver_info.minor) printf("fsl-mc: WARNING: Firmware minor version mismatch (found: %d, expected: %d)\n", @@ -541,7 +546,7 @@ int mc_init(void)
out: if (error != 0) - mc_boot_status = -error; + mc_boot_status = error; else mc_boot_status = 0;

Hi Prabhakar,
On Thu, Jul 2, 2015 at 12:59 AM, Prabhakar Kushwaha prabhakar@freescale.com wrote:
Management complex major version should match to the firmware present in flash.
Return error during mismatch of major version.
Signed-off-by: Prabhakar Kushwaha prabhakar@freescale.com
Acked-by: Joe Hershberger joe.hershberger@ni.com

From: Stuart Yoder stuart.yoder@freescale.com
Stream IDs on ls2085a devices are not hardwired and are programmed by sw. There are a limited number of stream IDs available, and the partitioning of them is scenario dependent. This header defines the partitioning between legacy, PCI, and DPAA2 devices.
Signed-off-by: Stuart Yoder stuart.yoder@freescale.com Signed-off-by: Prabhakar Kushwaha prabhakar@freescale.com --- Changes for v2: Sending as it is for patchset Changes for v3: Sending as it is for patchset Changes for v4: Sending as it is for patchset
.../include/asm/arch-fsl-lsch3/ls2085a_stream_id.h | 64 ++++++++++++++++++++++ drivers/net/fsl-mc/mc.c | 2 +- include/configs/ls2085a_common.h | 1 + include/fsl-mc/fsl_mc.h | 4 -- 4 files changed, 66 insertions(+), 5 deletions(-) create mode 100644 arch/arm/include/asm/arch-fsl-lsch3/ls2085a_stream_id.h
diff --git a/arch/arm/include/asm/arch-fsl-lsch3/ls2085a_stream_id.h b/arch/arm/include/asm/arch-fsl-lsch3/ls2085a_stream_id.h new file mode 100644 index 0000000..5c94530 --- /dev/null +++ b/arch/arm/include/asm/arch-fsl-lsch3/ls2085a_stream_id.h @@ -0,0 +1,64 @@ +/* + * Copyright 2014 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + * + */ +#ifndef __FSL_STREAM_ID_H +#define __FSL_STREAM_ID_H + +/* Stream IDs on ls2085a devices are not hardwired and are + * programmed by sw. There are a limited number of stream IDs + * available, and the partitioning of them is scenario dependent. + * This header defines the partitioning between legacy, PCI, + * and DPAA2 devices. + * + * This partitiong can be customized in this file depending + * on the specific hardware config-- e.g. perhaps not all + * PEX controllers are in use. + * + * On LS2085 stream IDs are programmed in AMQ registers (32-bits) for + * each of the different bus masters. The relationship between + * the AMQ registers and stream IDs is defined in the table below: + * AMQ bit streamID bit + * --------------------------- + * PL[18] 9 + * BMT[17] 8 + * VA[16] 7 + * [15] - + * ICID[14:7] - + * ICID[6:0] 6-0 + * ---------------------------- + */ + +#define AMQ_PL_MASK (0x1 << 18) /* priviledge bit */ +#define AMQ_BMT_MASK (0x1 << 17) /* bypass bit */ + +#define FSL_INVALID_STREAM_ID 0 + +#define FSL_BYPASS_AMQ (AMQ_PL_MASK | AMQ_BMT_MASK) + +/* legacy devices */ +#define FSL_USB1_STREAM_ID 1 +#define FSL_USB2_STREAM_ID 2 +#define FSL_SDMMC_STREAM_ID 3 +#define FSL_SATA1_STREAM_ID 4 +#define FSL_SATA2_STREAM_ID 5 +#define FSL_DMA_STREAM_ID 6 + +/* PCI - programmed in PEXn_LUT by OS */ +/* 4 IDs per controller */ +#define FSL_PEX1_STREAM_ID_START 7 +#define FSL_PEX1_STREAM_ID_END 10 +#define FSL_PEX2_STREAM_ID_START 11 +#define FSL_PEX2_STREAM_ID_END 14 +#define FSL_PEX3_STREAM_ID_START 15 +#define FSL_PEX3_STREAM_ID_END 18 +#define FSL_PEX4_STREAM_ID_START 19 +#define FSL_PEX4_STREAM_ID_END 22 + +/* DPAA2 - set in MC DPC and alloced by MC */ +#define FSL_DPAA2_STREAM_ID_START 23 +#define FSL_DPAA2_STREAM_ID_END 63 + +#endif diff --git a/drivers/net/fsl-mc/mc.c b/drivers/net/fsl-mc/mc.c index b2babfb..8e26fa4 100644 --- a/drivers/net/fsl-mc/mc.c +++ b/drivers/net/fsl-mc/mc.c @@ -474,7 +474,7 @@ int mc_init(void) out_le32(&mc_ccsr_regs->reg_mcfbalr, reg_mcfbalr); out_le32(&mc_ccsr_regs->reg_mcfbahr, (u32)(mc_ram_aligned_base_addr >> 32)); - out_le32(&mc_ccsr_regs->reg_mcfapr, MCFAPR_BYPASS_ICID_MASK); + out_le32(&mc_ccsr_regs->reg_mcfapr, FSL_BYPASS_AMQ);
/* * Tell the MC that we want delayed DPL deployment. diff --git a/include/configs/ls2085a_common.h b/include/configs/ls2085a_common.h index d095151..5248e2a 100644 --- a/include/configs/ls2085a_common.h +++ b/include/configs/ls2085a_common.h @@ -19,6 +19,7 @@ #define CONFIG_ARM_ERRATA_828024 #define CONFIG_ARM_ERRATA_826974
+#include <asm/arch-fsl-lsch3/ls2085a_stream_id.h> #include <asm/arch-fsl-lsch3/config.h> #if (defined(CONFIG_SYS_FSL_SRDS_1) || defined(CONFIG_SYS_FSL_SRDS_2)) #define CONFIG_SYS_HAS_SERDES diff --git a/include/fsl-mc/fsl_mc.h b/include/fsl-mc/fsl_mc.h index 0e799f5..9106f25 100644 --- a/include/fsl-mc/fsl_mc.h +++ b/include/fsl-mc/fsl_mc.h @@ -21,10 +21,6 @@ #define GCR1_M2_DE_RST BIT(14) #define GCR1_M_ALL_DE_RST (GCR1_M1_DE_RST | GCR1_M2_DE_RST) #define GSR_FS_MASK 0x3fffffff -#define MCFAPR_PL_MASK (0x1 << 18) -#define MCFAPR_BMT_MASK (0x1 << 17) -#define MCFAPR_BYPASS_ICID_MASK \ - (MCFAPR_PL_MASK | MCFAPR_BMT_MASK)
#define SOC_MC_PORTALS_BASE_ADDR ((void __iomem *)0x00080C000000) #define SOC_QBMAN_PORTALS_BASE_ADDR ((void __iomem *)0x000818000000)

From: Stuart Yoder stuart.yoder@freescale.com
delete any existing ICID pools in the DPC and create a new one based on the stream ID partitioning for the SoC
Signed-off-by: Stuart Yoder stuart.yoder@freescale.com Signed-off-by: Prabhakar Kushwaha prabhakar@freescale.com --- Changes for v2: Sending as it is for patchset Changes for v3: Sending as it is for patchset Changes for v4: Sending as it is for patchset
drivers/net/fsl-mc/mc.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+)
diff --git a/drivers/net/fsl-mc/mc.c b/drivers/net/fsl-mc/mc.c index 8e26fa4..62a68c2 100644 --- a/drivers/net/fsl-mc/mc.c +++ b/drivers/net/fsl-mc/mc.c @@ -3,8 +3,11 @@ * * SPDX-License-Identifier: GPL-2.0+ */ +#include <common.h> #include <errno.h> #include <asm/io.h> +#include <libfdt.h> +#include <fdt_support.h> #include <fsl-mc/fsl_mc.h> #include <fsl-mc/fsl_mc_sys.h> #include <fsl-mc/fsl_mc_private.h> @@ -185,6 +188,36 @@ static int calculate_mc_private_ram_params(u64 mc_private_ram_start_addr, return 0; }
+static int mc_fixup_dpc(u64 dpc_addr) +{ + void *blob = (void *)dpc_addr; + int nodeoffset; + + /* delete any existing ICID pools */ + nodeoffset = fdt_path_offset(blob, "/resources/icid_pools"); + if (fdt_del_node(blob, nodeoffset) < 0) + printf("\nfsl-mc: WARNING: could not delete ICID pool\n"); + + /* add a new pool */ + nodeoffset = fdt_path_offset(blob, "/resources"); + if (nodeoffset < 0) { + printf("\nfsl-mc: ERROR: DPC is missing /resources\n"); + return -EINVAL; + } + nodeoffset = fdt_add_subnode(blob, nodeoffset, "icid_pools"); + nodeoffset = fdt_add_subnode(blob, nodeoffset, "icid_pool@0"); + do_fixup_by_path_u32(blob, "/resources/icid_pools/icid_pool@0", + "base_icid", FSL_DPAA2_STREAM_ID_START, 1); + do_fixup_by_path_u32(blob, "/resources/icid_pools/icid_pool@0", + "num", + FSL_DPAA2_STREAM_ID_END - + FSL_DPAA2_STREAM_ID_START + 1, 1); + + flush_dcache_range(dpc_addr, dpc_addr + fdt_totalsize(blob)); + + return 0; +} + static int load_mc_dpc(u64 mc_ram_addr, size_t mc_ram_size) { u64 mc_dpc_offset; @@ -239,6 +272,9 @@ static int load_mc_dpc(u64 mc_ram_addr, size_t mc_ram_size) (u64)dpc_fdt_hdr, dpc_size, mc_ram_addr + mc_dpc_offset); #endif /* not defined CONFIG_SYS_LS_MC_DPC_IN_DDR */
+ if (mc_fixup_dpc(mc_ram_addr + mc_dpc_offset)) + return -EINVAL; + dump_ram_words("DPC", (void *)(mc_ram_addr + mc_dpc_offset)); return 0; }

From: Stuart Yoder stuart.yoder@freescale.com
This patch adds the infrastructure to update device tree nodes to convey SMMU stream IDs in the device tree. Fixups are implemented for PCI controllers initially.
Signed-off-by: Stuart Yoder stuart.yoder@freescale.com Signed-off-by: Prabhakar Kushwaha prabhakar@freescale.com --- changes for v2 - define in fdt_fixup_smmu_pcie in fdt.h - put fdt_fixup_smmu_pcie in CONFIG_PCI Changes for v3: Sending as it is for patchset Changes for v4: Sending as it is for patchset
arch/arm/cpu/armv8/fsl-lsch3/fdt.c | 110 ++++++++++++++++++++++++++++++ arch/arm/include/asm/arch-fsl-lsch3/fdt.h | 10 +++ drivers/pci/pcie_layerscape.c | 62 +++++++++++++++++ 3 files changed, 182 insertions(+) create mode 100644 arch/arm/include/asm/arch-fsl-lsch3/fdt.h
diff --git a/arch/arm/cpu/armv8/fsl-lsch3/fdt.c b/arch/arm/cpu/armv8/fsl-lsch3/fdt.c index b9fd559..567c419 100644 --- a/arch/arm/cpu/armv8/fsl-lsch3/fdt.c +++ b/arch/arm/cpu/armv8/fsl-lsch3/fdt.c @@ -7,6 +7,7 @@ #include <common.h> #include <libfdt.h> #include <fdt_support.h> +#include <asm/arch-fsl-lsch3/fdt.h> #ifdef CONFIG_FSL_ESDHC #include <fsl_esdhc.h> #endif @@ -58,6 +59,113 @@ void ft_fixup_cpu(void *blob) } #endif
+/* + * the burden is on the the caller to not request a count + * exceeding the bounds of the stream_ids[] array + */ +void alloc_stream_ids(int start_id, int count, u32 *stream_ids, int max_cnt) +{ + int i; + + if (count > max_cnt) { + printf("\n%s: ERROR: max per-device stream ID count exceed\n", + __func__); + return; + } + + for (i = 0; i < count; i++) + stream_ids[i] = start_id++; +} + +/* + * This function updates the mmu-masters property on the SMMU + * node as per the SMMU binding-- phandle and list of stream IDs + * for each MMU master. + */ +void append_mmu_masters(void *blob, const char *smmu_path, + const char *master_name, u32 *stream_ids, int count) +{ + u32 phandle; + int smmu_nodeoffset; + int master_nodeoffset; + int i; + + /* get phandle of mmu master device */ + master_nodeoffset = fdt_path_offset(blob, master_name); + if (master_nodeoffset < 0) { + printf("\n%s: ERROR: master not found\n", __func__); + return; + } + phandle = fdt_get_phandle(blob, master_nodeoffset); + if (!phandle) { /* if master has no phandle, create one */ + phandle = fdt_create_phandle(blob, master_nodeoffset); + if (!phandle) { + printf("\n%s: ERROR: unable to create phandle\n", + __func__); + return; + } + } + + /* append it to mmu-masters */ + smmu_nodeoffset = fdt_path_offset(blob, smmu_path); + if (fdt_appendprop_u32(blob, smmu_nodeoffset, "mmu-masters", + phandle) < 0) { + printf("\n%s: ERROR: unable to update SMMU node\n", __func__); + return; + } + + /* for each stream ID, append to mmu-masters */ + for (i = 0; i < count; i++) { + fdt_appendprop_u32(blob, smmu_nodeoffset, "mmu-masters", + stream_ids[i]); + } + + /* fix up #stream-id-cells with stream ID count */ + if (fdt_setprop_u32(blob, master_nodeoffset, "#stream-id-cells", + count) < 0) + printf("\n%s: ERROR: unable to update #stream-id-cells\n", + __func__); +} + + +/* + * The info below summarizes how streamID partitioning works + * for ls2085a and how it is conveyed to the OS via the device tree. + * + * -non-PCI legacy, platform devices (USB, SD/MMC, SATA, DMA) + * -all legacy devices get a unique ICID assigned and programmed in + * their AMQR registers by u-boot + * -u-boot updates the hardware device tree with streamID properties + * for each platform/legacy device (smmu-masters property) + * + * -PCIe + * -for each PCI controller that is active (as per RCW settings), + * u-boot will allocate a range of ICID and convey that to Linux via + * the device tree (smmu-masters property) + * + * -DPAA2 + * -u-boot will allocate a range of ICIDs to be used by the Management + * Complex for containers and will set these values in the MC DPC image. + * -the MC is responsible for allocating and setting up ICIDs + * for all DPAA2 devices. + * + */ +static void fdt_fixup_smmu(void *blob) +{ + int nodeoffset; + + nodeoffset = fdt_path_offset(blob, "/iommu@5000000"); + if (nodeoffset < 0) { + printf("\n%s: WARNING: no SMMU node found\n", __func__); + return; + } + + /* fixup for all PCI controllers */ +#ifdef CONFIG_PCI + fdt_fixup_smmu_pcie(blob); +#endif +} + void ft_cpu_setup(void *blob, bd_t *bd) { #ifdef CONFIG_MP @@ -76,4 +184,6 @@ void ft_cpu_setup(void *blob, bd_t *bd) #if defined(CONFIG_FSL_ESDHC) fdt_fixup_esdhc(blob, bd); #endif + + fdt_fixup_smmu(blob); } diff --git a/arch/arm/include/asm/arch-fsl-lsch3/fdt.h b/arch/arm/include/asm/arch-fsl-lsch3/fdt.h new file mode 100644 index 0000000..21d20fb --- /dev/null +++ b/arch/arm/include/asm/arch-fsl-lsch3/fdt.h @@ -0,0 +1,10 @@ +/* + * Copyright 2015 Freescale Semiconductor + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +void alloc_stream_ids(int start_id, int count, u32 *stream_ids, int max_cnt); +void append_mmu_masters(void *blob, const char *smmu_path, + const char *master_name, u32 *stream_ids, int count); +void fdt_fixup_smmu_pcie(void *blob); diff --git a/drivers/pci/pcie_layerscape.c b/drivers/pci/pcie_layerscape.c index 402c519..3ef4975 100644 --- a/drivers/pci/pcie_layerscape.c +++ b/drivers/pci/pcie_layerscape.c @@ -11,6 +11,7 @@ #include <asm/io.h> #include <errno.h> #include <malloc.h> +#include <asm/arch-fsl-lsch3/fdt.h>
#ifndef CONFIG_SYS_PCI_MEMORY_BUS #define CONFIG_SYS_PCI_MEMORY_BUS CONFIG_SYS_SDRAM_BASE @@ -528,3 +529,64 @@ void ft_pci_setup(void *blob, bd_t *bd) { } #endif + +#ifdef CONFIG_LS2085A + +void pcie_set_available_streamids(void *blob, const char *pcie_path, + u32 *stream_ids, int count) +{ + int nodeoffset; + int i; + + nodeoffset = fdt_path_offset(blob, pcie_path); + if (nodeoffset < 0) { + printf("\n%s: ERROR: unable to update PCIe node\n", __func__); + return; + } + + /* for each stream ID, append to mmu-masters */ + for (i = 0; i < count; i++) { + fdt_appendprop_u32(blob, nodeoffset, "available-stream-ids", + stream_ids[i]); + } +} + +#define MAX_STREAM_IDS 4 +void fdt_fixup_smmu_pcie(void *blob) +{ + int count; + u32 stream_ids[MAX_STREAM_IDS]; + + #ifdef CONFIG_PCIE1 + /* PEX1 stream ID fixup */ + count = FSL_PEX1_STREAM_ID_END - FSL_PEX1_STREAM_ID_START + 1; + alloc_stream_ids(FSL_PEX1_STREAM_ID_START, count, stream_ids, + MAX_STREAM_IDS); + pcie_set_available_streamids(blob, "/pcie@3400000", stream_ids, count); + #endif + + #ifdef CONFIG_PCIE2 + /* PEX2 stream ID fixup */ + count = FSL_PEX2_STREAM_ID_END - FSL_PEX2_STREAM_ID_START + 1; + alloc_stream_ids(FSL_PEX2_STREAM_ID_START, count, stream_ids, + MAX_STREAM_IDS); + pcie_set_available_streamids(blob, "/pcie@3500000", stream_ids, count); + #endif + + #ifdef CONFIG_PCIE3 + /* PEX3 stream ID fixup */ + count = FSL_PEX3_STREAM_ID_END - FSL_PEX3_STREAM_ID_START + 1; + alloc_stream_ids(FSL_PEX3_STREAM_ID_START, count, stream_ids, + MAX_STREAM_IDS); + pcie_set_available_streamids(blob, "/pcie@3600000", stream_ids, count); + #endif + + #ifdef CONFIG_PCIE4 + /* PEX4 stream ID fixup */ + count = FSL_PEX4_STREAM_ID_END - FSL_PEX4_STREAM_ID_START + 1; + alloc_stream_ids(FSL_PEX4_STREAM_ID_START, count, stream_ids, + MAX_STREAM_IDS); + pcie_set_available_streamids(blob, "/pcie@3700000", stream_ids, count); + #endif +} +#endif

Do not immediately return if the enqueue function returns -EBUSY; re-try mulitple times.
if timeout occures, release the buffer.
Signed-off-by: Prabhakar Kushwaha prabhakar@freescale.com --- Changes for v2: Sending as it is for patchset Changes for v3: Incorporated Joe Hershberger's comments - Squash with "driver/ldpaa_eth:Avoid infinite loop in QBMAN buf release" - use err instead of calling get_timer() again Changes for v4: Incorporated Joe Hershberger's comments - unsquashed from "driver/ldpaa_eth:Avoid infinite loop in QBMAN buf release" - Avoided infinte loop from v2 version
drivers/net/ldpaa_eth/ldpaa_eth.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.c b/drivers/net/ldpaa_eth/ldpaa_eth.c index 5636511..82c0ce7 100644 --- a/drivers/net/ldpaa_eth/ldpaa_eth.c +++ b/drivers/net/ldpaa_eth/ldpaa_eth.c @@ -221,8 +221,11 @@ static int ldpaa_eth_tx(struct eth_device *net_dev, void *buf, int len) struct dpaa_fd fd; u64 buffer_start; int data_offset, err; + u32 timeo = (CONFIG_SYS_HZ * 10) / 1000; + u32 time_start; struct qbman_swp *swp = dflt_dpio->sw_portal; struct qbman_eq_desc ed; + struct qbman_release_desc releasedesc;
/* Setup the FD fields */ memset(&fd, 0, sizeof(fd)); @@ -258,9 +261,20 @@ static int ldpaa_eth_tx(struct eth_device *net_dev, void *buf, int len) qbman_eq_desc_clear(&ed); qbman_eq_desc_set_no_orp(&ed, 0); qbman_eq_desc_set_qd(&ed, priv->tx_qdid, priv->tx_flow_id, 0); - err = qbman_swp_enqueue(swp, &ed, (const struct qbman_fd *)(&fd)); - if (err < 0) + + time_start = get_timer(0); + + while (get_timer(time_start) < timeo) { + err = qbman_swp_enqueue(swp, &ed, + (const struct qbman_fd *)(&fd)); + if (err != -EBUSY) + break; + } + + if (err < 0) { printf("error enqueueing Tx frame\n"); + goto error; + }
mdelay(1);
@@ -269,6 +283,20 @@ static int ldpaa_eth_tx(struct eth_device *net_dev, void *buf, int len) printf("error Tx Conf frame\n");
return err; + +error: + qbman_release_desc_clear(&releasedesc); + qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid); + time_start = get_timer(0); + do { + /* Release buffer into the QBMAN */ + err = qbman_swp_release(swp, &releasedesc, &buffer_start, 1); + } while (get_timer(time_start) < timeo && err == -EBUSY); + + if (err == -EBUSY) + printf("TX data: QBMAN buffer release fails\n"); + + return err; }
static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd)

Hi Prabhakar,
On Thu, Jul 2, 2015 at 12:59 AM, Prabhakar Kushwaha prabhakar@freescale.com wrote:
Do not immediately return if the enqueue function returns -EBUSY; re-try mulitple times.
if timeout occures, release the buffer.
Signed-off-by: Prabhakar Kushwaha prabhakar@freescale.com
Acked-by: Joe Hershberger joe.hershberger@ni.com

Volatile command does not return frame immidiately, need to wait till a frame is available in DQRR. Ideally it should be a blocking call.
Add timeout handling for DQRR frame instead of retry counter.
Signed-off-by: Prabhakar Kushwaha prabhakar@freescale.com Acked-by: Joe Hershberger joe.hershberger@ni.com --- Changes for v2: Sending as it is for patchset Changes for v3: Incorporated Joe Hershberger's comments - Use err variable instead of err = 1 Changes for v4: Sending as it is for patchset
drivers/net/ldpaa_eth/ldpaa_eth.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-)
diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.c b/drivers/net/ldpaa_eth/ldpaa_eth.c index 82c0ce7..cc949f5 100644 --- a/drivers/net/ldpaa_eth/ldpaa_eth.c +++ b/drivers/net/ldpaa_eth/ldpaa_eth.c @@ -77,7 +77,9 @@ static int ldpaa_eth_pull_dequeue_rx(struct eth_device *dev) struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)dev->priv; const struct ldpaa_dq *dq; const struct dpaa_fd *fd; - int i = 5, err = 0, status, loop = 20; + int i = 5, err = 0, status; + u32 timeo = (CONFIG_SYS_HZ * 2) / 1000; + u32 time_start; static struct qbman_pull_desc pulldesc; struct qbman_swp *swp = dflt_dpio->sw_portal;
@@ -92,13 +94,11 @@ static int ldpaa_eth_pull_dequeue_rx(struct eth_device *dev) continue; }
- do { - loop--; - dq = qbman_swp_dqrr_next(swp); + time_start = get_timer(0);
- if (!loop) - break; - } while (!dq); + do { + dq = qbman_swp_dqrr_next(swp); + } while (get_timer(time_start) < timeo && !dq);
if (dq) { /* Check for valid frame. If not sent a consume @@ -121,6 +121,10 @@ static int ldpaa_eth_pull_dequeue_rx(struct eth_device *dev) ldpaa_eth_rx(priv, fd); qbman_swp_dqrr_consume(swp, dq); break; + } else { + err = -ENODATA; + debug("No DQRR entries\n"); + break; } }
@@ -167,7 +171,9 @@ static int ldpaa_eth_pull_dequeue_tx_conf(struct ldpaa_eth_priv *priv) const struct ldpaa_dq *dq; const struct dpaa_fd *fd; int err = 0; - int i = 5, status, loop = 20; + int i = 5, status; + u32 timeo = (CONFIG_SYS_HZ * 10) / 1000; + u32 time_start; static struct qbman_pull_desc pulldesc; struct qbman_swp *swp = dflt_dpio->sw_portal;
@@ -182,13 +188,11 @@ static int ldpaa_eth_pull_dequeue_tx_conf(struct ldpaa_eth_priv *priv) continue; }
- do { - loop--; - dq = qbman_swp_dqrr_next(swp); + time_start = get_timer(0);
- if (!loop) - break; - } while (!dq); + do { + dq = qbman_swp_dqrr_next(swp); + } while (get_timer(time_start) < timeo && !dq);
if (dq) { /* Check for valid frame. If not sent a consume @@ -209,6 +213,10 @@ static int ldpaa_eth_pull_dequeue_tx_conf(struct ldpaa_eth_priv *priv) ldpaa_eth_tx_conf(priv, fd); qbman_swp_dqrr_consume(swp, dq); break; + } else { + err = -ENODATA; + debug("No DQRR entries\n"); + break; } }

Polling of TX conf frames is not a mandatory option. Packets can be transferred via WRIOP without TX conf frame.
Configure ldpaa_eth driver to use TX path without confirmation frame
Signed-off-by: Prabhakar Kushwaha prabhakar@freescale.com Acked-by: Joe Hershberger joe.hershberger@ni.com --- Changes for v2: Sending as it is for patchset Changes for v3: Sending as it is for patchset Changes for v4: Sending as it is for patchset
drivers/net/ldpaa_eth/ldpaa_eth.c | 114 ++------------------------------------ drivers/net/ldpaa_eth/ldpaa_eth.h | 1 - 2 files changed, 4 insertions(+), 111 deletions(-)
diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.c b/drivers/net/ldpaa_eth/ldpaa_eth.c index cc949f5..6de5f30 100644 --- a/drivers/net/ldpaa_eth/ldpaa_eth.c +++ b/drivers/net/ldpaa_eth/ldpaa_eth.c @@ -112,7 +112,7 @@ static int ldpaa_eth_pull_dequeue_rx(struct eth_device *dev) debug("No frame delivered\n");
qbman_swp_dqrr_consume(swp, dq); - break; + continue; }
fd = ldpaa_dq_fd(dq); @@ -131,98 +131,6 @@ static int ldpaa_eth_pull_dequeue_rx(struct eth_device *dev) return err; }
-static void ldpaa_eth_tx_conf(struct ldpaa_eth_priv *priv, - const struct dpaa_fd *fd) -{ - uint64_t fd_addr; - struct ldpaa_fas *fas; - uint32_t status, err; - struct qbman_release_desc releasedesc; - struct qbman_swp *swp = dflt_dpio->sw_portal; - - fd_addr = ldpaa_fd_get_addr(fd); - - - debug("TX Conf frame:data addr=0x%p\n", (u64 *)fd_addr); - - /* Check the status from the Frame Annotation */ - if (fd->simple.frc & LDPAA_FD_FRC_FASV) { - fas = (struct ldpaa_fas *) - ((uint8_t *)(fd_addr) + - priv->buf_layout.private_data_size); - status = le32_to_cpu(fas->status); - if (status & LDPAA_ETH_TXCONF_ERR_MASK) { - printf("TxConf frame error(s): 0x%08x\n", - status & LDPAA_ETH_TXCONF_ERR_MASK); - } - } - - flush_dcache_range(fd_addr, fd_addr + LDPAA_ETH_RX_BUFFER_SIZE); - qbman_release_desc_clear(&releasedesc); - qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid); - do { - /* Release buffer into the QBMAN */ - err = qbman_swp_release(swp, &releasedesc, &fd_addr, 1); - } while (err == -EBUSY); -} - -static int ldpaa_eth_pull_dequeue_tx_conf(struct ldpaa_eth_priv *priv) -{ - const struct ldpaa_dq *dq; - const struct dpaa_fd *fd; - int err = 0; - int i = 5, status; - u32 timeo = (CONFIG_SYS_HZ * 10) / 1000; - u32 time_start; - static struct qbman_pull_desc pulldesc; - struct qbman_swp *swp = dflt_dpio->sw_portal; - - while (--i) { - qbman_pull_desc_clear(&pulldesc); - qbman_pull_desc_set_numframes(&pulldesc, 1); - qbman_pull_desc_set_fq(&pulldesc, priv->tx_conf_fqid); - - err = qbman_swp_pull(swp, &pulldesc); - if (err < 0) { - printf("Dequeue TX conf frames error:0x%08x\n", err); - continue; - } - - time_start = get_timer(0); - - do { - dq = qbman_swp_dqrr_next(swp); - } while (get_timer(time_start) < timeo && !dq); - - if (dq) { - /* Check for valid frame. If not sent a consume - * confirmation to QBMAN otherwise give it to NADK - * application and then send consume confirmation to - * QBMAN. - */ - status = (uint8_t)ldpaa_dq_flags(dq); - if ((status & LDPAA_DQ_STAT_VALIDFRAME) == 0) { - debug("Dequeue TX conf frames:"); - debug("No frame is delivered\n"); - - qbman_swp_dqrr_consume(swp, dq); - break; - } - fd = ldpaa_dq_fd(dq); - - ldpaa_eth_tx_conf(priv, fd); - qbman_swp_dqrr_consume(swp, dq); - break; - } else { - err = -ENODATA; - debug("No DQRR entries\n"); - break; - } - } - - return err; -} - static int ldpaa_eth_tx(struct eth_device *net_dev, void *buf, int len) { struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; @@ -284,12 +192,6 @@ static int ldpaa_eth_tx(struct eth_device *net_dev, void *buf, int len) goto error; }
- mdelay(1); - - err = ldpaa_eth_pull_dequeue_tx_conf(priv); - if (err < 0) - printf("error Tx Conf frame\n"); - return err;
error: @@ -311,7 +213,6 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) { struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; struct dpni_queue_attr rx_queue_attr; - struct dpni_tx_flow_attr tx_flow_attr; uint8_t mac_addr[6]; int err;
@@ -382,21 +283,11 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) goto err_qdid; }
- err = dpni_get_tx_flow(dflt_mc_io, priv->dpni_handle, priv->tx_flow_id, - &tx_flow_attr); - if (err) { - printf("dpni_get_tx_flow() failed\n"); - goto err_tx_flow; - } - - priv->tx_conf_fqid = tx_flow_attr.conf_err_attr.queue_attr.fqid; - if (!priv->phydev->link) printf("%s: No link.\n", priv->phydev->dev->name);
return priv->phydev->link ? 0 : -1;
-err_tx_flow: err_qdid: err_rx_flow: dpni_disable(dflt_mc_io, priv->dpni_handle); @@ -663,6 +554,9 @@ static int ldpaa_dpni_bind(struct ldpaa_eth_priv *priv) priv->tx_flow_id = DPNI_NEW_FLOW_ID; memset(&dflt_tx_flow, 0, sizeof(dflt_tx_flow));
+ dflt_tx_flow.options = DPNI_TX_FLOW_OPT_ONLY_TX_ERROR; + dflt_tx_flow.conf_err_cfg.use_default_queue = 0; + dflt_tx_flow.conf_err_cfg.errors_only = 1; err = dpni_set_tx_flow(dflt_mc_io, priv->dpni_handle, &priv->tx_flow_id, &dflt_tx_flow); if (err) { diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.h b/drivers/net/ldpaa_eth/ldpaa_eth.h index 3107ab6..b4ef700 100644 --- a/drivers/net/ldpaa_eth/ldpaa_eth.h +++ b/drivers/net/ldpaa_eth/ldpaa_eth.h @@ -128,7 +128,6 @@ struct ldpaa_eth_priv {
uint32_t rx_dflt_fqid; uint16_t tx_qdid; - uint32_t tx_conf_fqid; uint16_t tx_flow_id;
enum ldpaa_eth_type type; /* 1G or 10G ethernet */

Change infinite loop mechanism to timer based polling for QBMAN release in ldpaa_eth_rx.
Signed-off-by: Prabhakar Kushwaha prabhakar@freescale.com --- Changes for v2: Sending as it is for patchset Changes for v3: Squashed with other patch Changes for v4: reverted the squash and only have rx path
drivers/net/ldpaa_eth/ldpaa_eth.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.c b/drivers/net/ldpaa_eth/ldpaa_eth.c index 6de5f30..50ca6e4 100644 --- a/drivers/net/ldpaa_eth/ldpaa_eth.c +++ b/drivers/net/ldpaa_eth/ldpaa_eth.c @@ -31,6 +31,8 @@ static void ldpaa_eth_rx(struct ldpaa_eth_priv *priv, uint32_t fd_length; struct ldpaa_fas *fas; uint32_t status, err; + u32 timeo = (CONFIG_SYS_HZ * 2) / 1000; + u32 time_start; struct qbman_release_desc releasedesc; struct qbman_swp *swp = dflt_dpio->sw_portal;
@@ -65,10 +67,15 @@ error: flush_dcache_range(fd_addr, fd_addr + LDPAA_ETH_RX_BUFFER_SIZE); qbman_release_desc_clear(&releasedesc); qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid); + time_start = get_timer(0); do { /* Release buffer into the QBMAN */ err = qbman_swp_release(swp, &releasedesc, &fd_addr, 1); - } while (err == -EBUSY); + } while (get_timer(time_start) < timeo && err == -EBUSY); + + if (err == -EBUSY) + printf("Rx frame: QBMAN buffer release fails\n"); + return; }

On 07/01/2015 10:58 PM, Prabhakar Kushwaha wrote:
From: "J. German Rivera" German.Rivera@freescale.com
Make it easier for the user to notice when the MC firmware had problems booting.
Signed-off-by: J. German Rivera German.Rivera@freescale.com Signed-off-by: Prabhakar Kushwaha prabhakar@freescale.com
Changes for v2: Sending as it is for patchset Changes for v3: Sending as it is for patchset Changes for v4: Sending as it is for patchset
This set (v4) is applied to u-boot-fsl-qoriq master branch.
York
participants (3)
-
Joe Hershberger
-
Prabhakar Kushwaha
-
York Sun