Skip to contentSkip to conversation

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

PATCH Superseded Prabhakar Kushwaha 2 participants 15 messages Jun 10, 2015 – Jun 11, 2015

Subsystems (3)

v1 of 4 Superseded Latest is v4 →

lore
Share & tools
lore
#0 lore raw

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

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

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

---
 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 3/13 drivers/fsl-mc: Autoload AOIP image from NOR flash

Quoted 7 lines · 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

Prabhakar,

Do we need this feature? It was written for bring-up. AIOP image should be loaded by Linux later for normal use.

York

#4 lore raw

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

Quoted 17 lines

-----Original Message-----
From: Sun York-R58495
Sent: Wednesday, June 10, 2015 8:06 PM
To: Kushwaha Prabhakar-B32579; u-boot at lists.denx.de
Cc: Rivera Jose-B46482
Subject: Re: [PATCH 03/13] drivers/fsl-mc: Autoload AOIP image from NOR flash

Quoted 5 lines · 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

Quoted 8 lines
Quoted 2 lines

Prabhakar,

Do we need this feature? It was written for bring-up. AIOP image should be loaded by Linux later for normal use.

I have no visibility when AIOP loader will be available in Linux. I am not seeing any plan of completing in next 1month or so. This is the reason I am having this feature. It is under #ifdef. If required it can be disabled..

--prabhakar

#5 lore raw

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

---
 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
#6 lore raw

PATCH 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]>
---
 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
#7 lore raw

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

---
 drivers/net/fsl-mc/mc.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/net/fsl-mc/mc.c +6 -1
index 2094595..c4406c6 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 = 1;
+		goto out;
+	}
 
 	if (MC_VER_MINOR != mc_ver_info.minor)
 		printf("fsl-mc: WARNING: Firmware minor version mismatch (found: %d, expected: %d)\n",
Signature · 1 line
1.9.1
#8 lore raw

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

---
 .../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 c4406c6..8bb8f7b 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
#9 lore raw

PATCH 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

---
 drivers/net/fsl-mc/mc.c | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)
drivers/net/fsl-mc/mc.c +36 -0
index 8bb8f7b..2820883 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
#10 lore raw

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

---
 arch/arm/cpu/armv8/fsl-lsch3/fdt.c        | 108 ++++++++++++++++++++++++++++++
 arch/arm/include/asm/arch-fsl-lsch3/fdt.h |   9 +++
 drivers/pci/pcie_layerscape.c             |  62 +++++++++++++++++
 3 files changed, 179 insertions(+)
 create mode 100644 arch/arm/include/asm/arch-fsl-lsch3/fdt.h
arch/arm/cpu/armv8/fsl-lsch3/fdt.c +108 -0
index b9fd559..a9d96d8 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,111 @@ 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 */
+	fdt_fixup_smmu_pcie(blob);
+}
+
 void ft_cpu_setup(void *blob, bd_t *bd)
 {
 #ifdef CONFIG_MP
@@ -76,4 +182,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 +9 -0
new file mode 100644
index 0000000..92b1e5f
@@ -0,0 +1,9 @@
+/*
+ * 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);
drivers/pci/pcie_layerscape.c +62 -0

71 lines not on this page · raw message

Signature · 1 line
1.9.1
#11 lore raw

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

---
 drivers/net/ldpaa_eth/ldpaa_eth.c | 26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)
drivers/net/ldpaa_eth/ldpaa_eth.c +24 -2
index 5636511..2716f6c 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,18 @@ 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));
+
+	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 +281,16 @@ 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);
+	do {
+		/* Release buffer into the QBMAN */
+		err = qbman_swp_release(swp, &releasedesc, &buffer_start, 1);
+	} while (err == -EBUSY);
+
+	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 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.

---
 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 2716f6c..adb964c 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 = -1;
+			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 = -1;
+			debug("No DQRR entries\n");
+			break;
 		}
 	}
 
Signature · 1 line
1.9.1
#13 lore raw

PATCH 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

---
 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 adb964c..839e78a 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 = -1;
-			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;
@@ -282,12 +190,6 @@ static int ldpaa_eth_tx(struct eth_device *net_dev, void *buf, int len)
 	if (err < 0)
 		goto error;
 
-	mdelay(1);
-
-	err = ldpaa_eth_pull_dequeue_tx_conf(priv);
-	if (err < 0)
-		printf("error Tx Conf frame\n");
-
 	return err;
 
 error:
@@ -305,7 +207,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;
 
@@ -376,21 +277,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);
@@ -657,6 +548,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 13/13 driver/ldpaa_eth:Avoid infinite loop in QBMAN buf release

In reply to Prabhakar Kushwaha

Change infinite loop mechanism to timer based polling.

---
 drivers/net/ldpaa_eth/ldpaa_eth.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)
drivers/net/ldpaa_eth/ldpaa_eth.c +11 -2
index 839e78a..fe8f189 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 (get_timer(time_start) >= timeo)
+		printf("Rx frame: QBMAN buffer release fails\n");
+
 	return;
 }
 
@@ -195,11 +202,13 @@ static int ldpaa_eth_tx(struct eth_device *net_dev, void *buf, int len)
 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 (err == -EBUSY);
+	} while (get_timer(time_start) < timeo && err == -EBUSY);
 
+	printf("TX data: QBMAN buffer release fails\n");
 	return err;
 }
 
Signature · 1 line
1.9.1