Skip to contentSkip to conversation

drivers/fsl-mc: Make MC boot error messages more readable

PATCH New Prabhakar Kushwaha 3 participants 16 messages Jul 2, 2015 – Jul 20, 2015

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH v4 1/13 drivers/fsl-mc: Make MC boot error messages more readable

From: "J. German Rivera" <[email protected]>

Make it easier for the user to notice when the MC firmware had problems booting.

---
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(-)
drivers/net/fsl-mc/mc.c +13 -18
index f4a050a..d02da9d 100644
@@ -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, &reg_gsr);
 	if (error != 0)
 		goto out;
+
 out:
 	if (error != 0)
 		mc_boot_status = -error;
Signature · 1 line
1.9.1
#1 lore raw

PATCH v4 2/13 driver/ldpaa_eth:Flush buffer before seeding BMAN after TX_conf

Flush buffer before releasing to BMan after TX_conf to ensure, the core does not have any cachelines that the WRIOP will DMA to.

---
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(+)
drivers/net/ldpaa_eth/ldpaa_eth.c +1 -0
index d4be1ba..5636511 100644
@@ -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 {
Signature · 1 line
1.9.1
#2 lore raw

PATCH v4 3/13 drivers/fsl-mc: Autoload AOIP image from NOR flash

In reply to Prabhakar Kushwaha

From: "J. German Rivera" <[email protected]>

Load AIOP image from NOR flash into DDR so that the MC firmware the MC fw can start it at boot time

---
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(+)
drivers/net/fsl-mc/mc.c +23 -0
index d02da9d..2b38b50 100644
@@ -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);
 
include/configs/ls2085a_common.h +2 -0
index cf51909..d095151 100644
@@ -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
include/configs/ls2085aqds.h +2 -0
index 731eca2..3d9655d 100644
@@ -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
include/configs/ls2085ardb.h +2 -0
index a0f0f6c..9f0a96f 100644
@@ -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
Signature · 1 line
1.9.1
#3 lore raw

PATCH v4 4/13 drivers: fsl-mc: Update flibs to mc-0.6.0.1

In reply to Prabhakar Kushwaha

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.

---
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(-)
drivers/net/fsl-mc/dpni.c +1 -1
index b384401..7bc2504 100644
@@ -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 };
 
drivers/net/fsl-mc/mc.c +7 -5
index 2b38b50..2094595 100644
@@ -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) {
include/fsl-mc/fsl_dpio.h +11 -21
index e84b419..e779909 100644
@@ -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;
include/fsl-mc/fsl_dpmng.h +1 -1
index 986e7c8..6feb292 100644
@@ -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
 
 /**
include/fsl-mc/fsl_dpni.h +123 -21

324 lines not on this page · raw message

include/fsl-mc/fsl_dprc.h +55 -9

142 lines not on this page · raw message

include/fsl-mc/fsl_mc.h +1 -0
index ec24415..0e799f5 100644
@@ -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) \
Signature · 1 line
1.9.1
#4 lore raw

PATCH v4 5/13 drivers: fsl-mc: Update qbman driver

In reply to Prabhakar Kushwaha

Update qbman driver
- As per latest available qbman driver
- Use of atomic APIs

CC Geoff Thorpe <[email protected]>
CC Haiying Wang <[email protected]>
CC Roy Pledge <[email protected]>

---
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(-)
drivers/net/fsl-mc/dpio/qbman_portal.c +36 -30
index dd2a7de..5fa8d95 100644
@@ -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;
 }
 
drivers/net/fsl-mc/dpio/qbman_portal.h +16 -6
index bb67c3b..86e2c3a 100644
@@ -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
drivers/net/fsl-mc/dpio/qbman_private.h +1 -1
index 2d2556b..f1f16b8 100644
@@ -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>
 
Signature · 1 line
1.9.1
#5 lore raw

PATCH v4 6/13 drivers: fsl-mc: Return error for major version mismatch

In reply to Prabhakar Kushwaha

Management complex major version should match to the firmware present in flash.

Return error during mismatch of major version.

---
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(-)
drivers/net/fsl-mc/mc.c +7 -2
index 2094595..b2babfb 100644
@@ -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;
 
Signature · 1 line
1.9.1
#7 lore raw

PATCH v4 7/13 armv8/fsl-lsch3: partition stream IDs

In reply to Prabhakar Kushwaha

From: Stuart Yoder <[email protected]>

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.

---
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
arch/arm/include/asm/arch-fsl-lsch3/ls2085a_stream_id.h new file +64 -0
new file mode 100644
index 0000000..5c94530
@@ -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
drivers/net/fsl-mc/mc.c +1 -1
index b2babfb..8e26fa4 100644
@@ -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.
include/configs/ls2085a_common.h +1 -0
index d095151..5248e2a 100644
@@ -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
include/fsl-mc/fsl_mc.h +0 -4
index 0e799f5..9106f25 100644
@@ -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)
Signature · 1 line
1.9.1
#8 lore raw

PATCH v4 8/13 drivers/fsl-mc: dynamically create ICID pool in DPC

In reply to Prabhakar Kushwaha

From: Stuart Yoder <[email protected]>

delete any existing ICID pools in the DPC and create a new one based on the stream ID partitioning for the SoC

---
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(+)
drivers/net/fsl-mc/mc.c +36 -0
index 8e26fa4..62a68c2 100644
@@ -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 at 0");
+	do_fixup_by_path_u32(blob, "/resources/icid_pools/icid_pool at 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;
 }
Signature · 1 line
1.9.1
#9 lore raw

PATCH v4 9/13 armv8/fsl-lsch3: device tree fixups for PCI stream IDs

In reply to Prabhakar Kushwaha

From: Stuart Yoder <[email protected]>

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.

---
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
arch/arm/cpu/armv8/fsl-lsch3/fdt.c +110 -0
index b9fd559..567c419 100644
@@ -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);
 }
arch/arm/include/asm/arch-fsl-lsch3/fdt.h new file +10 -0
new file mode 100644
index 0000000..21d20fb
@@ -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);
drivers/pci/pcie_layerscape.c +62 -0

71 lines not on this page · raw message

Signature · 1 line
1.9.1
#10 lore raw

PATCH v4 10/13 driver/ldpaa_eth: Retry enqueue if portal was busy

In reply to Prabhakar Kushwaha

Do not immediately return if the enqueue function returns -EBUSY; re-try mulitple times.

if timeout occures, release the buffer.

---
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(-)
drivers/net/ldpaa_eth/ldpaa_eth.c +30 -2
index 5636511..82c0ce7 100644
@@ -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)
Signature · 1 line
1.9.1
#12 lore raw

PATCH v4 11/13 driver/ldpaa_eth: Add timeout handling DQRR entry read

In reply to Prabhakar Kushwaha

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.

---
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(-)
drivers/net/ldpaa_eth/ldpaa_eth.c +22 -14
index 82c0ce7..cc949f5 100644
@@ -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;
 		}
 	}
 
Signature · 1 line
1.9.1
#13 lore raw

PATCH v4 12/13 driver/ldpaa_eth: Avoid TX conf frames

In reply to Prabhakar Kushwaha

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

---
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(-)
drivers/net/ldpaa_eth/ldpaa_eth.c +4 -110
index cc949f5..6de5f30 100644
@@ -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) {
drivers/net/ldpaa_eth/ldpaa_eth.h +0 -1
index 3107ab6..b4ef700 100644
@@ -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 */
Signature · 1 line
1.9.1
#14 lore raw

PATCH v4 13/13 driver/ldpaa_eth:Avoid infinite loop in ldpaa_eth_rx

In reply to Prabhakar Kushwaha

Change infinite loop mechanism to timer based polling for QBMAN release in ldpaa_eth_rx.

---
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(-)
drivers/net/ldpaa_eth/ldpaa_eth.c +8 -1
index 6de5f30..50ca6e4 100644
@@ -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;
 }
 
Signature · 1 line
1.9.1
#15 lore raw

PATCH v4 1/13 drivers/fsl-mc: Make MC boot error messages more readable

In reply to Prabhakar Kushwaha
Quoted 11 lines · Prabhakar Kushwaha

From: "J. German Rivera" <[email protected]>

Make it easier for the user to notice when the MC firmware had problems booting.

---
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