chelsio: tabulate the update of the statistic counters

Let's try to avoid some code duplication.

- cxgb2
  The data are contiguous. Use plain memcpy.

- ixf1010/pm3393/vsc7326
  The cast of &mac->stats to (u64 *) is not wonderful but it is not clear
  if it is worth to add an ad-hoc union under the struct cmac_statistics.

vsc7326_reg.h suggests that more statistics could be available.

Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
diff --git a/drivers/net/chelsio/ixf1010.c b/drivers/net/chelsio/ixf1010.c
index c40a88d..10b2a9a 100644
--- a/drivers/net/chelsio/ixf1010.c
+++ b/drivers/net/chelsio/ixf1010.c
@@ -145,48 +145,61 @@
 	t1_tpi_write(mac->adapter, REG_PORT_ENABLE, val);
 }
 
-#define RMON_UPDATE(mac, name, stat_name) \
-	t1_tpi_read((mac)->adapter, MACREG(mac, REG_##name), &val); \
-	(mac)->stats.stat_name += val;
-
 /*
  * Read the current values of the RMON counters and add them to the cumulative
  * port statistics.  The HW RMON counters are cleared by this operation.
  */
 static void port_stats_update(struct cmac *mac)
 {
-	u32 val;
+	static struct {
+		unsigned int reg;
+		unsigned int offset;
+	} hw_stats[] = {
 
-	/* Rx stats */
-	RMON_UPDATE(mac, RxOctetsTotalOK, RxOctetsOK);
-	RMON_UPDATE(mac, RxOctetsBad, RxOctetsBad);
-	RMON_UPDATE(mac, RxUCPkts, RxUnicastFramesOK);
-	RMON_UPDATE(mac, RxMCPkts, RxMulticastFramesOK);
-	RMON_UPDATE(mac, RxBCPkts, RxBroadcastFramesOK);
-	RMON_UPDATE(mac, RxJumboPkts, RxJumboFramesOK);
-	RMON_UPDATE(mac, RxFCSErrors, RxFCSErrors);
-	RMON_UPDATE(mac, RxAlignErrors, RxAlignErrors);
-	RMON_UPDATE(mac, RxLongErrors, RxFrameTooLongErrors);
-	RMON_UPDATE(mac, RxVeryLongErrors, RxFrameTooLongErrors);
-	RMON_UPDATE(mac, RxPauseMacControlCounter, RxPauseFrames);
-	RMON_UPDATE(mac, RxDataErrors, RxDataErrors);
-	RMON_UPDATE(mac, RxJabberErrors, RxJabberErrors);
-	RMON_UPDATE(mac, RxRuntErrors, RxRuntErrors);
-	RMON_UPDATE(mac, RxShortErrors, RxRuntErrors);
-	RMON_UPDATE(mac, RxSequenceErrors, RxSequenceErrors);
-	RMON_UPDATE(mac, RxSymbolErrors, RxSymbolErrors);
+#define HW_STAT(name, stat_name) \
+	{ REG_##name, \
+	  (&((struct cmac_statistics *)NULL)->stat_name) - (u64 *)NULL }
 
-	/* Tx stats (skip collision stats as we are full-duplex only) */
-	RMON_UPDATE(mac, TxOctetsTotalOK, TxOctetsOK);
-	RMON_UPDATE(mac, TxOctetsBad, TxOctetsBad);
-	RMON_UPDATE(mac, TxUCPkts, TxUnicastFramesOK);
-	RMON_UPDATE(mac, TxMCPkts, TxMulticastFramesOK);
-	RMON_UPDATE(mac, TxBCPkts, TxBroadcastFramesOK);
-	RMON_UPDATE(mac, TxJumboPkts, TxJumboFramesOK);
-	RMON_UPDATE(mac, TxPauseFrames, TxPauseFrames);
-	RMON_UPDATE(mac, TxExcessiveLengthDrop, TxLengthErrors);
-	RMON_UPDATE(mac, TxUnderrun, TxUnderrun);
-	RMON_UPDATE(mac, TxCRCErrors, TxFCSErrors);
+		/* Rx stats */
+		HW_STAT(RxOctetsTotalOK, RxOctetsOK),
+		HW_STAT(RxOctetsBad, RxOctetsBad),
+		HW_STAT(RxUCPkts, RxUnicastFramesOK),
+		HW_STAT(RxMCPkts, RxMulticastFramesOK),
+		HW_STAT(RxBCPkts, RxBroadcastFramesOK),
+		HW_STAT(RxJumboPkts, RxJumboFramesOK),
+		HW_STAT(RxFCSErrors, RxFCSErrors),
+		HW_STAT(RxAlignErrors, RxAlignErrors),
+		HW_STAT(RxLongErrors, RxFrameTooLongErrors),
+		HW_STAT(RxVeryLongErrors, RxFrameTooLongErrors),
+		HW_STAT(RxPauseMacControlCounter, RxPauseFrames),
+		HW_STAT(RxDataErrors, RxDataErrors),
+		HW_STAT(RxJabberErrors, RxJabberErrors),
+		HW_STAT(RxRuntErrors, RxRuntErrors),
+		HW_STAT(RxShortErrors, RxRuntErrors),
+		HW_STAT(RxSequenceErrors, RxSequenceErrors),
+		HW_STAT(RxSymbolErrors, RxSymbolErrors),
+
+		/* Tx stats (skip collision stats as we are full-duplex only) */
+		HW_STAT(TxOctetsTotalOK, TxOctetsOK),
+		HW_STAT(TxOctetsBad, TxOctetsBad),
+		HW_STAT(TxUCPkts, TxUnicastFramesOK),
+		HW_STAT(TxMCPkts, TxMulticastFramesOK),
+		HW_STAT(TxBCPkts, TxBroadcastFramesOK),
+		HW_STAT(TxJumboPkts, TxJumboFramesOK),
+		HW_STAT(TxPauseFrames, TxPauseFrames),
+		HW_STAT(TxExcessiveLengthDrop, TxLengthErrors),
+		HW_STAT(TxUnderrun, TxUnderrun),
+		HW_STAT(TxCRCErrors, TxFCSErrors)
+	}, *p = hw_stats;
+	u64 *stats = (u64 *) &mac->stats;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(hw_stats); i++) {
+		u32 val;
+
+		t1_tpi_read(mac->adapter, MACREG(mac, p->reg), &val);
+		stats[p->offset] += val;
+	}
 }
 
 /* No-op interrupt operation as this MAC does not support interrupts */
@@ -390,6 +403,10 @@
 	return 0;
 }
 
+#define RMON_UPDATE(mac, name, stat_name) \
+	t1_tpi_read((mac)->adapter, MACREG(mac, REG_##name), &val); \
+	(mac)->stats.stat_name += val;
+
 /*
  * This function is called periodically to accumulate the current values of the
  * RMON counters into the port statistics.  Since the counters are only 32 bits