diff mbox series

[net-next,3/4] bnx2x: Add support for idlechk tests.

Message ID 1593699029-18937-4-git-send-email-skalluru@marvell.com
State Changes Requested
Delegated to: David Miller
Headers show
Series bnx2x: Perform IdleChk dump. | expand

Commit Message

Sudarsana Reddy Kalluru July 2, 2020, 2:10 p.m. UTC
The patch adds driver implementation for performing the idlechk tests.

Signed-off-by: Sudarsana Reddy Kalluru <skalluru@marvell.com>
Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
---
 drivers/net/ethernet/broadcom/bnx2x/bnx2x.h        |   3 +
 .../net/ethernet/broadcom/bnx2x/bnx2x_self_test.c  | 266 ++++++++++++++++++++-
 2 files changed, 267 insertions(+), 2 deletions(-)

Comments

kernel test robot July 2, 2020, 8:46 p.m. UTC | #1
Hi Sudarsana,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on net-next/master]

url:    https://github.com/0day-ci/linux/commits/Sudarsana-Reddy-Kalluru/bnx2x-Perform-IdleChk-dump/20200702-221259
base:   https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git 23212a70077311396cda2823d627317c25e6e5d1
config: arm-allyesconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=arm 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All error/warnings (new ones prefixed by >>):

   In file included from arch/arm/include/asm/irqflags.h:7,
                    from include/linux/irqflags.h:16,
                    from arch/arm/include/asm/bitops.h:28,
                    from include/linux/bitops.h:29,
                    from include/linux/kernel.h:12,
                    from drivers/net/ethernet/broadcom/bnx2x/bnx2x_self_test.c:2:
   drivers/net/ethernet/broadcom/bnx2x/bnx2x_self_test.c: In function 'bnx2x_idle_chk7':
>> arch/arm/include/asm/ptrace.h:112:23: error: expected identifier before '(' token
     112 | #define predicate(x)  ((x) & 0xf0000000)
         |                       ^
>> drivers/net/ethernet/broadcom/bnx2x/bnx2x_self_test.c:3021:12: note: in expansion of macro 'predicate'
    3021 |   if (rec->predicate(&rec->pred_args)) {
         |            ^~~~~~~~~
   drivers/net/ethernet/broadcom/bnx2x/bnx2x_self_test.c: In function 'bnx2x_idle_chk':
>> arch/arm/include/asm/ptrace.h:112:23: error: expected identifier before '(' token
     112 | #define predicate(x)  ((x) & 0xf0000000)
         |                       ^
   drivers/net/ethernet/broadcom/bnx2x/bnx2x_self_test.c:3075:12: note: in expansion of macro 'predicate'
    3075 |    if (rec.predicate(&rec.pred_args)) {
         |            ^~~~~~~~~
>> arch/arm/include/asm/ptrace.h:112:23: error: expected identifier before '(' token
     112 | #define predicate(x)  ((x) & 0xf0000000)
         |                       ^
   drivers/net/ethernet/broadcom/bnx2x/bnx2x_self_test.c:3090:13: note: in expansion of macro 'predicate'
    3090 |     if (rec.predicate(&rec.pred_args)) {
         |             ^~~~~~~~~
>> arch/arm/include/asm/ptrace.h:112:23: error: expected identifier before '(' token
     112 | #define predicate(x)  ((x) & 0xf0000000)
         |                       ^
   drivers/net/ethernet/broadcom/bnx2x/bnx2x_self_test.c:3106:12: note: in expansion of macro 'predicate'
    3106 |    if (rec.predicate(&rec.pred_args)) {
         |            ^~~~~~~~~
>> arch/arm/include/asm/ptrace.h:112:23: error: expected identifier before '(' token
     112 | #define predicate(x)  ((x) & 0xf0000000)
         |                       ^
   drivers/net/ethernet/broadcom/bnx2x/bnx2x_self_test.c:3122:13: note: in expansion of macro 'predicate'
    3122 |     if (rec.predicate(&rec.pred_args)) {
         |             ^~~~~~~~~
>> arch/arm/include/asm/ptrace.h:112:23: error: expected identifier before '(' token
     112 | #define predicate(x)  ((x) & 0xf0000000)
         |                       ^
   drivers/net/ethernet/broadcom/bnx2x/bnx2x_self_test.c:3142:13: note: in expansion of macro 'predicate'
    3142 |     if (rec.predicate(&rec.pred_args)) {
         |             ^~~~~~~~~
   In file included from drivers/net/ethernet/broadcom/bnx2x/bnx2x_self_test.c:4:
   At top level:
   drivers/net/ethernet/broadcom/bnx2x/bnx2x.h:2436:18: warning: 'dmae_reg_go_c' defined but not used [-Wunused-const-variable=]
    2436 | static const u32 dmae_reg_go_c[] = {
         |                  ^~~~~~~~~~~~~

vim +/predicate +3021 drivers/net/ethernet/broadcom/bnx2x/bnx2x_self_test.c

  2986	
  2987	/* specific test for cfc info ram and cid cam */
  2988	static void bnx2x_idle_chk7(struct bnx2x *bp,
  2989				    struct st_record *rec, char *message)
  2990	{
  2991		int i;
  2992	
  2993		/* iterate through lcids */
  2994		for (i = 0; i < rec->loop; i++) {
  2995			/* make sure cam entry is valid (bit 0) */
  2996			if ((REG_RD(bp, (rec->reg2 + i * 4)) & 0x1) != 0x1)
  2997				continue;
  2998	
  2999			/* get connection type (multiple reads due to widebus) */
  3000			REG_RD(bp, (rec->reg1 + i * rec->incr));
  3001			REG_RD(bp, (rec->reg1 + i * rec->incr + 4));
  3002			rec->pred_args.val1 =
  3003				REG_RD(bp, (rec->reg1 + i * rec->incr + 8));
  3004			REG_RD(bp, (rec->reg1 + i * rec->incr + 12));
  3005	
  3006			/* obtain connection type */
  3007			if (is_e1 || is_e1h) {
  3008				/* E1 E1H (bits 4..7) */
  3009				rec->pred_args.val1 &= 0x78;
  3010				rec->pred_args.val1 >>= 3;
  3011			} else {
  3012				/* E2 E3A0 E3B0 (bits 26..29) */
  3013				rec->pred_args.val1 &= 0x1E000000;
  3014				rec->pred_args.val1 >>= 25;
  3015			}
  3016	
  3017			/* get activity counter value */
  3018			rec->pred_args.val2 = REG_RD(bp, rec->reg3 + i * 4);
  3019	
  3020			/* validate ac value is legal for con_type at idle state */
> 3021			if (rec->predicate(&rec->pred_args)) {
  3022				snprintf(message, MAX_FAIL_MSG,
  3023					 "%s. Values are 0x%x 0x%x\n", rec->fail_msg,
  3024					 rec->pred_args.val1, rec->pred_args.val2);
  3025				bnx2x_self_test_log(bp, rec->severity, message);
  3026			}
  3027		}
  3028	}
  3029	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff mbox series

Patch

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index 4f5b2b8..3a1af3c 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -1979,6 +1979,9 @@  struct bnx2x_func_init_params {
 
 #define skip_queue(bp, idx)	(NO_FCOE(bp) && IS_FCOE_IDX(idx))
 
+/*self test*/
+int bnx2x_idle_chk(struct bnx2x *bp);
+
 /**
  * bnx2x_set_mac_one - configure a single MAC address
  *
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_self_test.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_self_test.c
index ea71fd5..4f218881 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_self_test.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_self_test.c
@@ -18,7 +18,11 @@ 
 #define MAX_FAIL_MSG 256
 
 /* statistics and error reporting */
-static int idle_chk_errors;
+static int idle_chk_errors, idle_chk_warnings;
+
+/* masks for all chip types */
+static int is_e1, is_e1h, is_e2, is_e3a0, is_e3b0;
+
 
 /* struct for the argument list for a predicate in the self test databasei */
 struct st_pred_args {
@@ -30,7 +34,7 @@  struct st_pred_args {
 	u32 imm4; /* 4th value in predicate condition, left-to-right */
 };
 
-/*struct representing self test record - a single test*/
+/* struct representing self test record - a single test */
 struct st_record {
 	u8 chip_mask;
 	u8 macro;
@@ -2920,3 +2924,261 @@  struct st_record st_database[ST_DB_LINES] = {
 	"NIG: PBF IF5 FIFO is not empty",
 	{NA, NA, 1, NA, NA, NA} },
 };
+
+/* handle self test fails according to severity and type */
+static void bnx2x_self_test_log(struct bnx2x *bp, u8 severity, char *message)
+{
+	switch (severity) {
+	case IDLE_CHK_ERROR:
+		BNX2X_ERR("ERROR %s", message);
+		idle_chk_errors++;
+		break;
+	case IDLE_CHK_ERROR_NO_TRAFFIC:
+		DP(NETIF_MSG_HW, "INFO %s", message);
+		break;
+	case IDLE_CHK_WARNING:
+		DP(NETIF_MSG_HW, "WARNING %s", message);
+		idle_chk_warnings++;
+		break;
+	}
+}
+
+/* specific test for QM rd/wr pointers and rd/wr banks */
+static void bnx2x_idle_chk6(struct bnx2x *bp,
+			    struct st_record *rec, char *message)
+{
+	u32 rd_ptr, wr_ptr, rd_bank, wr_bank;
+	int i;
+
+	for (i = 0; i < rec->loop; i++) {
+		/* read regs */
+		rec->pred_args.val1 =
+			REG_RD(bp, rec->reg1 + i * rec->incr);
+		rec->pred_args.val2 =
+			REG_RD(bp, rec->reg1 + i * rec->incr + 4);
+
+		/* calc read and write pointers */
+		rd_ptr = ((rec->pred_args.val1 & 0x3FFFFFC0) >> 6);
+		wr_ptr = ((((rec->pred_args.val1 & 0xC0000000) >> 30) & 0x3) |
+			((rec->pred_args.val2 & 0x3FFFFF) << 2));
+
+		/* perfrom pointer test */
+		if (rd_ptr != wr_ptr) {
+			snprintf(message, MAX_FAIL_MSG,
+				 "QM: PTRTBL entry %d- rd_ptr is not equal to wr_ptr. Values are 0x%x and 0x%x\n",
+				 i, rd_ptr, wr_ptr);
+			bnx2x_self_test_log(bp, rec->severity, message);
+		}
+
+		/* calculate read and write banks */
+		rd_bank = ((rec->pred_args.val1 & 0x30) >> 4);
+		wr_bank = (rec->pred_args.val1 & 0x03);
+
+		/* perform bank test */
+		if (rd_bank != wr_bank) {
+			snprintf(message, MAX_FAIL_MSG,
+				 "QM: PTRTBL entry %d - rd_bank is not equal to wr_bank. Values are 0x%x 0x%x\n",
+				 i, rd_bank, wr_bank);
+			bnx2x_self_test_log(bp, rec->severity, message);
+		}
+	}
+}
+
+/* specific test for cfc info ram and cid cam */
+static void bnx2x_idle_chk7(struct bnx2x *bp,
+			    struct st_record *rec, char *message)
+{
+	int i;
+
+	/* iterate through lcids */
+	for (i = 0; i < rec->loop; i++) {
+		/* make sure cam entry is valid (bit 0) */
+		if ((REG_RD(bp, (rec->reg2 + i * 4)) & 0x1) != 0x1)
+			continue;
+
+		/* get connection type (multiple reads due to widebus) */
+		REG_RD(bp, (rec->reg1 + i * rec->incr));
+		REG_RD(bp, (rec->reg1 + i * rec->incr + 4));
+		rec->pred_args.val1 =
+			REG_RD(bp, (rec->reg1 + i * rec->incr + 8));
+		REG_RD(bp, (rec->reg1 + i * rec->incr + 12));
+
+		/* obtain connection type */
+		if (is_e1 || is_e1h) {
+			/* E1 E1H (bits 4..7) */
+			rec->pred_args.val1 &= 0x78;
+			rec->pred_args.val1 >>= 3;
+		} else {
+			/* E2 E3A0 E3B0 (bits 26..29) */
+			rec->pred_args.val1 &= 0x1E000000;
+			rec->pred_args.val1 >>= 25;
+		}
+
+		/* get activity counter value */
+		rec->pred_args.val2 = REG_RD(bp, rec->reg3 + i * 4);
+
+		/* validate ac value is legal for con_type at idle state */
+		if (rec->predicate(&rec->pred_args)) {
+			snprintf(message, MAX_FAIL_MSG,
+				 "%s. Values are 0x%x 0x%x\n", rec->fail_msg,
+				 rec->pred_args.val1, rec->pred_args.val2);
+			bnx2x_self_test_log(bp, rec->severity, message);
+		}
+	}
+}
+
+/* self test procedure
+ * scan auto-generated database
+ * for each line:
+ * 1.	compare chip mask
+ * 2.	determine type (according to maro number)
+ * 3.	read registers
+ * 4.	call predicate
+ * 5.	collate results and statistics
+ */
+int bnx2x_idle_chk(struct bnx2x *bp)
+{
+	u16 i;				/* loop counter */
+	u16 st_ind;			/* self test database access index */
+	struct st_record rec;		/* current record variable */
+	char message[MAX_FAIL_MSG];	/* message to log */
+
+	/*init stats*/
+	idle_chk_errors = 0;
+	idle_chk_warnings = 0;
+
+	/*create masks for all chip types*/
+	is_e1	= CHIP_IS_E1(bp);
+	is_e1h	= CHIP_IS_E1H(bp);
+	is_e2	= CHIP_IS_E2(bp);
+	is_e3a0	= CHIP_IS_E3A0(bp);
+	is_e3b0	= CHIP_IS_E3B0(bp);
+
+	/*database main loop*/
+	for (st_ind = 0; st_ind < ST_DB_LINES; st_ind++) {
+		rec = st_database[st_ind];
+
+		/*check if test applies to chip*/
+		if (!((rec.chip_mask & IDLE_CHK_E1) && is_e1) &&
+		    !((rec.chip_mask & IDLE_CHK_E1H) && is_e1h) &&
+		    !((rec.chip_mask & IDLE_CHK_E2) && is_e2) &&
+		    !((rec.chip_mask & IDLE_CHK_E3A0) && is_e3a0) &&
+		    !((rec.chip_mask & IDLE_CHK_E3B0) && is_e3b0))
+			continue;
+
+		/* identify macro */
+		switch (rec.macro) {
+		case 1:
+			/* read single reg and call predicate */
+			rec.pred_args.val1 = REG_RD(bp, rec.reg1);
+			DP(BNX2X_MSG_IDLE, "mac1 add %x\n", rec.reg1);
+			if (rec.predicate(&rec.pred_args)) {
+				snprintf(message, sizeof(message),
+					 "%s.Value is 0x%x\n", rec.fail_msg,
+					 rec.pred_args.val1);
+				bnx2x_self_test_log(bp, rec.severity, message);
+			}
+			break;
+		case 2:
+			/* read repeatedly starting from reg1 and call
+			 * predicate after each read
+			 */
+			for (i = 0; i < rec.loop; i++) {
+				rec.pred_args.val1 =
+					REG_RD(bp, rec.reg1 + i * rec.incr);
+				DP(BNX2X_MSG_IDLE, "mac2 add %x\n", rec.reg1);
+				if (rec.predicate(&rec.pred_args)) {
+					snprintf(message, sizeof(message),
+						 "%s. Value is 0x%x in loop %d\n",
+						 rec.fail_msg,
+						 rec.pred_args.val1, i);
+					bnx2x_self_test_log(bp, rec.severity,
+							    message);
+				}
+			}
+			break;
+		case 3:
+			/* read two regs and call predicate */
+			rec.pred_args.val1 = REG_RD(bp, rec.reg1);
+			rec.pred_args.val2 = REG_RD(bp, rec.reg2);
+			DP(BNX2X_MSG_IDLE, "mac3 add1 %x add2 %x\n",
+			   rec.reg1, rec.reg2);
+			if (rec.predicate(&rec.pred_args)) {
+				snprintf(message, sizeof(message),
+					 "%s. Values are 0x%x 0x%x\n",
+					 rec.fail_msg, rec.pred_args.val1,
+					 rec.pred_args.val2);
+				bnx2x_self_test_log(bp, rec.severity, message);
+			}
+			break;
+		case 4:
+			/*unused to-date*/
+			for (i = 0; i < rec.loop; i++) {
+				rec.pred_args.val1 =
+					REG_RD(bp, rec.reg1 + i * rec.incr);
+				rec.pred_args.val2 =
+					(REG_RD(bp,
+						rec.reg2 + i * rec.incr)) >> 1;
+				if (rec.predicate(&rec.pred_args)) {
+					snprintf(message, sizeof(message),
+						 "%s. Values are 0x%x 0x%x in loop %d\n",
+						 rec.fail_msg,
+						 rec.pred_args.val1,
+						 rec.pred_args.val2, i);
+					bnx2x_self_test_log(bp, rec.severity,
+							    message);
+				}
+			}
+			break;
+		case 5:
+			/* compare two regs, pending
+			 * the value of a condition reg
+			 */
+			rec.pred_args.val1 = REG_RD(bp, rec.reg1);
+			rec.pred_args.val2 = REG_RD(bp, rec.reg2);
+			DP(BNX2X_MSG_IDLE, "mac3 add1 %x add2 %x add3 %x\n",
+			   rec.reg1, rec.reg2, rec.reg3);
+			if (REG_RD(bp, rec.reg3) != 0) {
+				if (rec.predicate(&rec.pred_args)) {
+					snprintf(message, sizeof(message),
+						 "%s. Values are 0x%x 0x%x\n",
+						 rec.fail_msg,
+						 rec.pred_args.val1,
+						 rec.pred_args.val2);
+					bnx2x_self_test_log(bp, rec.severity,
+							    message);
+				}
+			}
+			break;
+		case 6:
+			/* compare read and write pointers
+			 * and read and write banks in QM
+			 */
+			bnx2x_idle_chk6(bp, &rec, message);
+			break;
+		case 7:
+			/* compare cfc info cam with cid cam */
+			bnx2x_idle_chk7(bp, &rec, message);
+			break;
+		default:
+			DP(BNX2X_MSG_IDLE,
+			   "unknown macro in self test data base. macro %d line %d",
+			   rec.macro, st_ind);
+		}
+	}
+
+	/* abort if interface is not running */
+	if (!netif_running(bp->dev))
+		return idle_chk_errors;
+
+	/* return value accorindg to statistics */
+	if (idle_chk_errors == 0) {
+		DP(BNX2X_MSG_IDLE,
+		   "completed successfully (logged %d warnings)\n",
+		   idle_chk_warnings);
+	} else {
+		BNX2X_ERR("failed (with %d errors, %d warnings)\n",
+			  idle_chk_errors, idle_chk_warnings);
+	}
+	return idle_chk_errors;
+}