Netdev List
 help / color / mirror / Atom feed
* [PATCH 6/7] bnx2x: move fp->disable_tpa to ->flags
From: Michal Schmidt @ 2011-08-30 14:30 UTC (permalink / raw)
  To: netdev; +Cc: vladz, dmitry, eilong, Michal Schmidt
In-Reply-To: <1314714646-3642-1-git-send-email-mschmidt@redhat.com>

Store the boolean fp->disable_tpa in a more general 'flags' field.
Later more flags will be added.

Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
---
 drivers/net/ethernet/broadcom/bnx2x/bnx2x.h      |    3 +-
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c  |   31 ++++++++++------------
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h  |    2 +-
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c |    4 +-
 4 files changed, 19 insertions(+), 21 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index c0d2d9c..02fa7a7 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -477,6 +477,8 @@ struct bnx2x_fastpath {
 	u8			cl_qzone_id;
 	u8			fw_sb_id;	/* status block number in FW */
 	u8			igu_sb_id;	/* status block number in HW */
+	u8			flags;
+#define FP_TPA			(1 << 0)	/* TPA enabled */
 
 	u16			rx_bd_prod;
 	u16			rx_bd_cons;
@@ -491,7 +493,6 @@ struct bnx2x_fastpath {
 
 	/* TPA related */
 	struct bnx2x_agg_info	tpa_info[ETH_MAX_AGGREGATION_QUEUES_E1H_E2];
-	u8			disable_tpa;
 #ifdef BNX2X_STOP_ON_ERROR
 	u64			tpa_queue_used;
 #endif
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index fe5be0c..d45aaa5 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -60,15 +60,12 @@ static inline void bnx2x_bz_fp(struct bnx2x *bp, int index)
 
 	/*
 	 * set the tpa flag for each queue. The tpa flag determines the queue
-	 * minimal size so it must be set prior to queue memory allocation
+	 * minimal size so it must be set prior to queue memory allocation.
+	 *
+	 * We don't want TPA on an FCoE L2 ring.
 	 */
-	fp->disable_tpa = ((bp->flags & TPA_ENABLE_FLAG) == 0);
-
-#ifdef BCM_CNIC
-	/* We don't want TPA on an FCoE L2 ring */
-	if (IS_FCOE_FP(fp))
-		fp->disable_tpa = 1;
-#endif
+	if ((bp->flags & TPA_ENABLE_FLAG) && !IS_FCOE_FP(fp))
+		fp->flags = FP_TPA;
 }
 
 /**
@@ -634,9 +631,9 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
 		if (!CQE_TYPE_FAST(cqe_fp_type)) {
 #ifdef BNX2X_STOP_ON_ERROR
 			/* sanity check */
-			if (fp->disable_tpa)
+			if (!(fp->flags & FP_TPA))
 				BNX2X_ERR("START/STOP packet while "
-					  "disable_tpa type %x\n",
+					  "TPA disabled, type %x\n",
 					  CQE_TYPE(cqe_fp_type));
 #endif
 
@@ -993,7 +990,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
 		DP(NETIF_MSG_IFUP,
 		   "mtu %d  rx_buf_size %d\n", bp->dev->mtu, fp->rx_buf_size);
 
-		if (!fp->disable_tpa) {
+		if (fp->flags & FP_TPA) {
 			/* Fill the per-aggregtion pool */
 			for (i = 0; i < max_agg_queues; i++) {
 				struct bnx2x_agg_info *tpa_info =
@@ -1009,7 +1006,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
 						  "disabling TPA on this "
 						  "queue!\n", j);
 					bnx2x_free_tpa_pool(bp, fp, i);
-					fp->disable_tpa = 1;
+					fp->flags &= ~FP_TPA;
 					break;
 				}
 				dma_unmap_addr_set(first_buf, mapping, 0);
@@ -1036,7 +1033,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
 								ring_prod);
 					bnx2x_free_tpa_pool(bp, fp,
 							    max_agg_queues);
-					fp->disable_tpa = 1;
+					fp->flags &= ~FP_TPA;
 					ring_prod = 0;
 					break;
 				}
@@ -1130,7 +1127,7 @@ static void bnx2x_free_rx_skbs(struct bnx2x *bp)
 
 		bnx2x_free_rx_bds(fp);
 
-		if (!fp->disable_tpa)
+		if (fp->flags & FP_TPA)
 			bnx2x_free_tpa_pool(bp, fp, CHIP_IS_E1(bp) ?
 					    ETH_MAX_AGGREGATION_QUEUES_E1 :
 					    ETH_MAX_AGGREGATION_QUEUES_E1H_E2);
@@ -1724,7 +1721,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 	/*
 	 * Zero fastpath structures preserving invariants like napi, which are
 	 * allocated only once, fp index, max_cos, bp pointer.
-	 * Also set fp->disable_tpa.
+	 * Also set fp->flags.
 	 */
 	for_each_queue(bp, i)
 		bnx2x_bz_fp(bp, i);
@@ -3182,8 +3179,8 @@ alloc_mem_err:
 	 * In these cases we disable the queue
 	 * Min size is different for OOO, TPA and non-TPA queues
 	 */
-	if (ring_size < (fp->disable_tpa ?
-				MIN_RX_SIZE_NONTPA : MIN_RX_SIZE_TPA)) {
+	if (ring_size < ((fp->flags & FP_TPA) ? MIN_RX_SIZE_TPA :
+						MIN_RX_SIZE_NONTPA)) {
 			/* release memory allocated for this queue */
 			bnx2x_free_fp_mem_at(bp, index);
 			return -ENOMEM;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
index 54d50b7..14b3658 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
@@ -1013,7 +1013,7 @@ static inline void bnx2x_free_rx_sge_range(struct bnx2x *bp,
 {
 	int i;
 
-	if (fp->disable_tpa)
+	if (!(fp->flags & FP_TPA))
 		return;
 
 	for (i = 0; i < last; i++)
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 617a072..7bc6944 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -2709,7 +2709,7 @@ static unsigned long bnx2x_get_q_flags(struct bnx2x *bp,
 	if (IS_FCOE_FP(fp))
 		__set_bit(BNX2X_Q_FLG_FCOE, &flags);
 
-	if (!fp->disable_tpa) {
+	if (fp->flags & FP_TPA) {
 		__set_bit(BNX2X_Q_FLG_TPA, &flags);
 		__set_bit(BNX2X_Q_FLG_TPA_IPV6, &flags);
 	}
@@ -2750,7 +2750,7 @@ static void bnx2x_pf_rx_q_prep(struct bnx2x *bp,
 	u16 sge_sz = 0;
 	u16 tpa_agg_size = 0;
 
-	if (!fp->disable_tpa) {
+	if (fp->flags & FP_TPA) {
 		pause->sge_th_hi = 250;
 		pause->sge_th_lo = 150;
 		tpa_agg_size = min_t(u32,
-- 
1.7.6

^ permalink raw reply related

* [PATCH 5/7] bnx2x: do not set TPA flags and features in bnx2x_init_bp
From: Michal Schmidt @ 2011-08-30 14:30 UTC (permalink / raw)
  To: netdev; +Cc: vladz, dmitry, eilong, Michal Schmidt
In-Reply-To: <1314714646-3642-1-git-send-email-mschmidt@redhat.com>

The .ndo_{set,fix}_features callbacks are sufficient.

Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
---
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c |    9 ---------
 1 files changed, 0 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 64314f7..617a072 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -9752,15 +9752,6 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
 					"must load devices in order!\n");
 
 	bp->multi_mode = multi_mode;
-
-	/* Set TPA flags */
-	if (disable_tpa) {
-		bp->flags &= ~TPA_ENABLE_FLAG;
-		bp->dev->features &= ~NETIF_F_LRO;
-	} else {
-		bp->flags |= TPA_ENABLE_FLAG;
-		bp->dev->features |= NETIF_F_LRO;
-	}
 	bp->disable_tpa = disable_tpa;
 
 	if (CHIP_IS_E1(bp))
-- 
1.7.6

^ permalink raw reply related

* [PATCH 4/7] bnx2x: simplify TPA sanity check
From: Michal Schmidt @ 2011-08-30 14:30 UTC (permalink / raw)
  To: netdev; +Cc: vladz, dmitry, eilong, Michal Schmidt
In-Reply-To: <1314714646-3642-1-git-send-email-mschmidt@redhat.com>

In the TPA branch we already know the CQE type is either START or STOP.
No need to test for that. Even if the type were to differ, we wouldn't
want to suppress the error message.

Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
---
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index f1fea58..fe5be0c 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -634,9 +634,7 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
 		if (!CQE_TYPE_FAST(cqe_fp_type)) {
 #ifdef BNX2X_STOP_ON_ERROR
 			/* sanity check */
-			if (fp->disable_tpa &&
-			    (CQE_TYPE_START(cqe_fp_type) ||
-			     CQE_TYPE_STOP(cqe_fp_type)))
+			if (fp->disable_tpa)
 				BNX2X_ERR("START/STOP packet while "
 					  "disable_tpa type %x\n",
 					  CQE_TYPE(cqe_fp_type));
-- 
1.7.6

^ permalink raw reply related

* [PATCH 3/7] bnx2x: decrease indentation in bnx2x_rx_int()
From: Michal Schmidt @ 2011-08-30 14:30 UTC (permalink / raw)
  To: netdev; +Cc: vladz, dmitry, eilong, Michal Schmidt
In-Reply-To: <1314714646-3642-1-git-send-email-mschmidt@redhat.com>

For better readability decrease the indentation in bnx2x_rx_int().
'else' is unnecessary when the positive branch ends with a 'goto'.

Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
---
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c |  194 +++++++++++------------
 1 files changed, 92 insertions(+), 102 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 448e301..f1fea58 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -624,135 +624,125 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
 		if (unlikely(CQE_TYPE_SLOW(cqe_fp_type))) {
 			bnx2x_sp_event(fp, cqe);
 			goto next_cqe;
+		}
 
 		/* this is an rx packet */
-		} else {
-			rx_buf = &fp->rx_buf_ring[bd_cons];
-			skb = rx_buf->skb;
-			prefetch(skb);
+		rx_buf = &fp->rx_buf_ring[bd_cons];
+		skb = rx_buf->skb;
+		prefetch(skb);
 
-			if (!CQE_TYPE_FAST(cqe_fp_type)) {
+		if (!CQE_TYPE_FAST(cqe_fp_type)) {
 #ifdef BNX2X_STOP_ON_ERROR
-				/* sanity check */
-				if (fp->disable_tpa &&
-				    (CQE_TYPE_START(cqe_fp_type) ||
-				     CQE_TYPE_STOP(cqe_fp_type)))
-					BNX2X_ERR("START/STOP packet while "
-						  "disable_tpa type %x\n",
-						  CQE_TYPE(cqe_fp_type));
+			/* sanity check */
+			if (fp->disable_tpa &&
+			    (CQE_TYPE_START(cqe_fp_type) ||
+			     CQE_TYPE_STOP(cqe_fp_type)))
+				BNX2X_ERR("START/STOP packet while "
+					  "disable_tpa type %x\n",
+					  CQE_TYPE(cqe_fp_type));
 #endif
 
-				if (CQE_TYPE_START(cqe_fp_type)) {
-					u16 queue = cqe_fp->queue_index;
-					DP(NETIF_MSG_RX_STATUS,
-					   "calling tpa_start on queue %d\n",
-					   queue);
+			if (CQE_TYPE_START(cqe_fp_type)) {
+				u16 queue = cqe_fp->queue_index;
+				DP(NETIF_MSG_RX_STATUS,
+				   "calling tpa_start on queue %d\n", queue);
 
-					bnx2x_tpa_start(fp, queue, skb,
-							bd_cons, bd_prod,
-							cqe_fp);
+				bnx2x_tpa_start(fp, queue, skb,
+						bd_cons, bd_prod, cqe_fp);
 
-					/* Set Toeplitz hash for LRO skb */
-					bnx2x_set_skb_rxhash(bp, cqe, skb);
+				/* Set Toeplitz hash for LRO skb */
+				bnx2x_set_skb_rxhash(bp, cqe, skb);
 
-					goto next_rx;
+				goto next_rx;
 
-				} else {
-					u16 queue =
-						cqe->end_agg_cqe.queue_index;
-					DP(NETIF_MSG_RX_STATUS,
-					   "calling tpa_stop on queue %d\n",
-					   queue);
+			} else {
+				u16 queue =
+					cqe->end_agg_cqe.queue_index;
+				DP(NETIF_MSG_RX_STATUS,
+				   "calling tpa_stop on queue %d\n", queue);
 
-					bnx2x_tpa_stop(bp, fp, queue,
-						       &cqe->end_agg_cqe,
-						       comp_ring_cons);
+				bnx2x_tpa_stop(bp, fp, queue, &cqe->end_agg_cqe,
+					       comp_ring_cons);
 #ifdef BNX2X_STOP_ON_ERROR
-					if (bp->panic)
-						return 0;
+				if (bp->panic)
+					return 0;
 #endif
 
-					bnx2x_update_sge_prod(fp, cqe_fp);
-					goto next_cqe;
-				}
+				bnx2x_update_sge_prod(fp, cqe_fp);
+				goto next_cqe;
 			}
-			/* non TPA */
-			len = le16_to_cpu(cqe_fp->pkt_len);
-			pad = cqe_fp->placement_offset;
-			dma_sync_single_for_cpu(&bp->pdev->dev,
+		}
+		/* non TPA */
+		len = le16_to_cpu(cqe_fp->pkt_len);
+		pad = cqe_fp->placement_offset;
+		dma_sync_single_for_cpu(&bp->pdev->dev,
 					dma_unmap_addr(rx_buf, mapping),
-						       pad + RX_COPY_THRESH,
-						       DMA_FROM_DEVICE);
-			prefetch(((char *)(skb)) + L1_CACHE_BYTES);
+					pad + RX_COPY_THRESH, DMA_FROM_DEVICE);
+		prefetch(((char *)(skb)) + L1_CACHE_BYTES);
 
-			/* is this an error packet? */
-			if (unlikely(cqe_fp_flags & ETH_RX_ERROR_FALGS)) {
+		/* is this an error packet? */
+		if (unlikely(cqe_fp_flags & ETH_RX_ERROR_FALGS)) {
+			DP(NETIF_MSG_RX_ERR, "ERROR  flags %x  rx packet %u\n",
+			   cqe_fp_flags, sw_comp_cons);
+			fp->eth_q_stats.rx_err_discard_pkt++;
+			goto reuse_rx;
+		}
+
+		/*
+		 * Since we don't have a jumbo ring,
+		 * copy small packets if mtu > 1500
+		 */
+		if ((bp->dev->mtu > ETH_MAX_PACKET_SIZE) &&
+		    (len <= RX_COPY_THRESH)) {
+			struct sk_buff *new_skb;
+
+			new_skb = netdev_alloc_skb(bp->dev, len + pad);
+			if (new_skb == NULL) {
 				DP(NETIF_MSG_RX_ERR,
-				   "ERROR  flags %x  rx packet %u\n",
-				   cqe_fp_flags, sw_comp_cons);
-				fp->eth_q_stats.rx_err_discard_pkt++;
+				   "ERROR  packet dropped "
+				   "because of alloc failure\n");
+				fp->eth_q_stats.rx_skb_alloc_failed++;
 				goto reuse_rx;
 			}
 
-			/* Since we don't have a jumbo ring
-			 * copy small packets if mtu > 1500
-			 */
-			if ((bp->dev->mtu > ETH_MAX_PACKET_SIZE) &&
-			    (len <= RX_COPY_THRESH)) {
-				struct sk_buff *new_skb;
-
-				new_skb = netdev_alloc_skb(bp->dev, len + pad);
-				if (new_skb == NULL) {
-					DP(NETIF_MSG_RX_ERR,
-					   "ERROR  packet dropped "
-					   "because of alloc failure\n");
-					fp->eth_q_stats.rx_skb_alloc_failed++;
-					goto reuse_rx;
-				}
-
-				/* aligned copy */
-				skb_copy_from_linear_data_offset(skb, pad,
-						    new_skb->data + pad, len);
-				skb_reserve(new_skb, pad);
-				skb_put(new_skb, len);
+			/* aligned copy */
+			skb_copy_from_linear_data_offset(skb, pad,
+						new_skb->data + pad, len);
+			skb_reserve(new_skb, pad);
+			skb_put(new_skb, len);
 
-				bnx2x_reuse_rx_skb(fp, bd_cons, bd_prod);
+			bnx2x_reuse_rx_skb(fp, bd_cons, bd_prod);
 
-				skb = new_skb;
+			skb = new_skb;
 
-			} else
-			if (likely(bnx2x_alloc_rx_skb(bp, fp, bd_prod) == 0)) {
-				dma_unmap_single(&bp->pdev->dev,
-					dma_unmap_addr(rx_buf, mapping),
-						 fp->rx_buf_size,
-						 DMA_FROM_DEVICE);
-				skb_reserve(skb, pad);
-				skb_put(skb, len);
+		} else if (likely(bnx2x_alloc_rx_skb(bp, fp, bd_prod) == 0)) {
+			dma_unmap_single(&bp->pdev->dev,
+					 dma_unmap_addr(rx_buf, mapping),
+					 fp->rx_buf_size, DMA_FROM_DEVICE);
+			skb_reserve(skb, pad);
+			skb_put(skb, len);
 
-			} else {
-				DP(NETIF_MSG_RX_ERR,
-				   "ERROR  packet dropped because "
-				   "of alloc failure\n");
-				fp->eth_q_stats.rx_skb_alloc_failed++;
+		} else {
+			DP(NETIF_MSG_RX_ERR,
+			   "ERROR  packet dropped because of alloc failure\n");
+			fp->eth_q_stats.rx_skb_alloc_failed++;
 reuse_rx:
-				bnx2x_reuse_rx_skb(fp, bd_cons, bd_prod);
-				goto next_rx;
-			}
-
-			skb->protocol = eth_type_trans(skb, bp->dev);
+			bnx2x_reuse_rx_skb(fp, bd_cons, bd_prod);
+			goto next_rx;
+		}
 
-			/* Set Toeplitz hash for a none-LRO skb */
-			bnx2x_set_skb_rxhash(bp, cqe, skb);
+		skb->protocol = eth_type_trans(skb, bp->dev);
 
-			skb_checksum_none_assert(skb);
+		/* Set Toeplitz hash for a none-LRO skb */
+		bnx2x_set_skb_rxhash(bp, cqe, skb);
 
-			if (bp->dev->features & NETIF_F_RXCSUM) {
+		skb_checksum_none_assert(skb);
 
-				if (likely(BNX2X_RX_CSUM_OK(cqe)))
-					skb->ip_summed = CHECKSUM_UNNECESSARY;
-				else
-					fp->eth_q_stats.hw_csum_err++;
-			}
+		if (bp->dev->features & NETIF_F_RXCSUM) {
+			if (likely(BNX2X_RX_CSUM_OK(cqe)))
+				skb->ip_summed = CHECKSUM_UNNECESSARY;
+			else
+				fp->eth_q_stats.hw_csum_err++;
 		}
 
 		skb_record_rx_queue(skb, fp->index);
-- 
1.7.6

^ permalink raw reply related

* [PATCH 2/7] bnx2x: remove the 'leading' arguments
From: Michal Schmidt @ 2011-08-30 14:30 UTC (permalink / raw)
  To: netdev; +Cc: vladz, dmitry, eilong, Michal Schmidt
In-Reply-To: <1314714646-3642-1-git-send-email-mschmidt@redhat.com>

Whether a queue is leading can be deduced from its index.

Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
---
 drivers/net/ethernet/broadcom/bnx2x/bnx2x.h      |    1 +
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c  |    2 +-
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h  |    4 +---
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c |   21 +++++++++------------
 4 files changed, 12 insertions(+), 16 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index 735e491..c0d2d9c 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -531,6 +531,7 @@ struct bnx2x_fastpath {
 
 #define IS_ETH_FP(fp)			(fp->index < \
 					 BNX2X_NUM_ETH_QUEUES(fp->bp))
+#define IS_LEADING_FP(fp)		((fp)->index == 0)
 #ifdef BCM_CNIC
 #define IS_FCOE_FP(fp)			(fp->index == FCOE_IDX)
 #define IS_FCOE_IDX(idx)		((idx) == FCOE_IDX)
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 5c3eb17..448e301 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -1881,7 +1881,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 #endif
 
 	for_each_nondefault_queue(bp, i) {
-		rc = bnx2x_setup_queue(bp, &bp->fp[i], 0);
+		rc = bnx2x_setup_queue(bp, &bp->fp[i]);
 		if (rc)
 			LOAD_ERROR_EXIT(bp, load_error4);
 	}
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
index 5b1f9b5..54d50b7 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
@@ -109,11 +109,9 @@ void bnx2x__init_func_obj(struct bnx2x *bp);
  *
  * @bp:		driver handle
  * @fp:		pointer to the fastpath structure
- * @leading:	boolean
  *
  */
-int bnx2x_setup_queue(struct bnx2x *bp, struct bnx2x_fastpath *fp,
-		       bool leading);
+int bnx2x_setup_queue(struct bnx2x *bp, struct bnx2x_fastpath *fp);
 
 /**
  * bnx2x_setup_leading - bring up a leading eth queue.
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index e7b584b..64314f7 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -2697,9 +2697,8 @@ static inline unsigned long bnx2x_get_common_flags(struct bnx2x *bp,
 	return flags;
 }
 
-static inline unsigned long bnx2x_get_q_flags(struct bnx2x *bp,
-					      struct bnx2x_fastpath *fp,
-					      bool leading)
+static unsigned long bnx2x_get_q_flags(struct bnx2x *bp,
+				       struct bnx2x_fastpath *fp)
 {
 	unsigned long flags = 0;
 
@@ -2715,7 +2714,7 @@ static inline unsigned long bnx2x_get_q_flags(struct bnx2x *bp,
 		__set_bit(BNX2X_Q_FLG_TPA_IPV6, &flags);
 	}
 
-	if (leading) {
+	if (IS_LEADING_FP(fp)) {
 		__set_bit(BNX2X_Q_FLG_LEADING_RSS, &flags);
 		__set_bit(BNX2X_Q_FLG_MCAST, &flags);
 	}
@@ -6966,7 +6965,7 @@ int bnx2x_set_eth_mac(struct bnx2x *bp, bool set)
 
 int bnx2x_setup_leading(struct bnx2x *bp)
 {
-	return bnx2x_setup_queue(bp, &bp->fp[0], 1);
+	return bnx2x_setup_queue(bp, &bp->fp[0]);
 }
 
 /**
@@ -7177,10 +7176,10 @@ static inline void bnx2x_pf_q_prep_init(struct bnx2x *bp,
 			&bp->context.vcxt[fp->txdata[cos].cid].eth;
 }
 
-int bnx2x_setup_tx_only(struct bnx2x *bp, struct bnx2x_fastpath *fp,
+static int bnx2x_setup_tx_only(struct bnx2x *bp, struct bnx2x_fastpath *fp,
 			struct bnx2x_queue_state_params *q_params,
 			struct bnx2x_queue_setup_tx_only_params *tx_only_params,
-			int tx_index, bool leading)
+			int tx_index)
 {
 	memset(tx_only_params, 0, sizeof(*tx_only_params));
 
@@ -7216,14 +7215,12 @@ int bnx2x_setup_tx_only(struct bnx2x *bp, struct bnx2x_fastpath *fp,
  *
  * @bp:		driver handle
  * @fp:		pointer to fastpath
- * @leading:	is leading
  *
  * This function performs 2 steps in a Queue state machine
  *      actually: 1) RESET->INIT 2) INIT->SETUP
  */
 
-int bnx2x_setup_queue(struct bnx2x *bp, struct bnx2x_fastpath *fp,
-		       bool leading)
+int bnx2x_setup_queue(struct bnx2x *bp, struct bnx2x_fastpath *fp)
 {
 	struct bnx2x_queue_state_params q_params = {0};
 	struct bnx2x_queue_setup_params *setup_params =
@@ -7264,7 +7261,7 @@ int bnx2x_setup_queue(struct bnx2x *bp, struct bnx2x_fastpath *fp,
 	memset(setup_params, 0, sizeof(*setup_params));
 
 	/* Set QUEUE flags */
-	setup_params->flags = bnx2x_get_q_flags(bp, fp, leading);
+	setup_params->flags = bnx2x_get_q_flags(bp, fp);
 
 	/* Set general SETUP parameters */
 	bnx2x_pf_q_prep_general(bp, fp, &setup_params->gen_params,
@@ -7293,7 +7290,7 @@ int bnx2x_setup_queue(struct bnx2x *bp, struct bnx2x_fastpath *fp,
 
 		/* prepare and send tx-only ramrod*/
 		rc = bnx2x_setup_tx_only(bp, fp, &q_params,
-					  tx_only_params, tx_index, leading);
+					  tx_only_params, tx_index);
 		if (rc) {
 			BNX2X_ERR("Queue(%d.%d) TX_ONLY_SETUP failed\n",
 				  fp->index, tx_index);
-- 
1.7.6

^ permalink raw reply related

* [PATCH 1/7] bnx2x: remove unused fields in struct bnx2x_func_init_params
From: Michal Schmidt @ 2011-08-30 14:30 UTC (permalink / raw)
  To: netdev; +Cc: vladz, dmitry, eilong, Michal Schmidt
In-Reply-To: <1314714646-3642-1-git-send-email-mschmidt@redhat.com>

func_flgs is not used for anything. The only flag that's ever checked
(FUNC_FLG_SPQ) is always set. The other flags are never read.

fw_stat_map is not used at all.

Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
---
 drivers/net/ethernet/broadcom/bnx2x/bnx2x.h      |   15 ++-------------
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c |   18 +++---------------
 2 files changed, 5 insertions(+), 28 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index f127768..735e491 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -1490,24 +1490,13 @@ extern int num_queues;
 #define RSS_IPV6_TCP_CAP_MASK						\
 	TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY
 
-/* func init flags */
-#define FUNC_FLG_RSS		0x0001
-#define FUNC_FLG_STATS		0x0002
-/* removed  FUNC_FLG_UNMATCHED	0x0004 */
-#define FUNC_FLG_TPA		0x0008
-#define FUNC_FLG_SPQ		0x0010
-#define FUNC_FLG_LEADING	0x0020	/* PF only */
-
-
 struct bnx2x_func_init_params {
 	/* dma */
-	dma_addr_t	fw_stat_map;	/* valid iff FUNC_FLG_STATS */
-	dma_addr_t	spq_map;	/* valid iff FUNC_FLG_SPQ */
+	dma_addr_t	spq_map;
 
-	u16		func_flgs;
 	u16		func_id;	/* abs fid */
 	u16		pf_id;
-	u16		spq_prod;	/* valid iff FUNC_FLG_SPQ */
+	u16		spq_prod;
 };
 
 #define for_each_eth_queue(bp, var) \
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 85dd294..e7b584b 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -2661,11 +2661,9 @@ void bnx2x_func_init(struct bnx2x *bp, struct bnx2x_func_init_params *p)
 	storm_memset_func_en(bp, p->func_id, 1);
 
 	/* spq */
-	if (p->func_flgs & FUNC_FLG_SPQ) {
-		storm_memset_spq_addr(bp, p->spq_map, p->func_id);
-		REG_WR(bp, XSEM_REG_FAST_MEMORY +
-		       XSTORM_SPQ_PROD_OFFSET(p->func_id), p->spq_prod);
-	}
+	storm_memset_spq_addr(bp, p->spq_map, p->func_id);
+	REG_WR(bp, XSEM_REG_FAST_MEMORY +
+	       XSTORM_SPQ_PROD_OFFSET(p->func_id), p->spq_prod);
 }
 
 /**
@@ -2838,7 +2836,6 @@ static void bnx2x_pf_init(struct bnx2x *bp)
 {
 	struct bnx2x_func_init_params func_init = {0};
 	struct event_ring_data eq_data = { {0} };
-	u16 flags;
 
 	if (!CHIP_IS_E1x(bp)) {
 		/* reset IGU PF statistics: MSIX + ATTN */
@@ -2855,15 +2852,6 @@ static void bnx2x_pf_init(struct bnx2x *bp)
 				BP_FUNC(bp) : BP_VN(bp))*4, 0);
 	}
 
-	/* function setup flags */
-	flags = (FUNC_FLG_STATS | FUNC_FLG_LEADING | FUNC_FLG_SPQ);
-
-	/* This flag is relevant for E1x only.
-	 * E2 doesn't have a TPA configuration in a function level.
-	 */
-	flags |= (bp->flags & TPA_ENABLE_FLAG) ? FUNC_FLG_TPA : 0;
-
-	func_init.func_flgs = flags;
 	func_init.pf_id = BP_FUNC(bp);
 	func_init.func_id = BP_FUNC(bp);
 	func_init.spq_map = bp->spq_mapping;
-- 
1.7.6

^ permalink raw reply related

* [PATCH 0/7 net-next] bnx2x: cleanups and VLAN stripping toggle
From: Michal Schmidt @ 2011-08-30 14:30 UTC (permalink / raw)
  To: netdev; +Cc: vladz, dmitry, eilong, Michal Schmidt

Hello,
patches 1-6 are cleanups.
Patch 7 adds HW VLAN stripping control via ethtool.

Michal Schmidt (7):
  bnx2x: remove unused fields in struct bnx2x_func_init_params
  bnx2x: remove the 'leading' arguments
  bnx2x: decrease indentation in bnx2x_rx_int()
  bnx2x: simplify TPA sanity check
  bnx2x: do not set TPA flags and features in bnx2x_init_bp
  bnx2x: move fp->disable_tpa to ->flags
  bnx2x: expose HW RX VLAN stripping toggle

 drivers/net/ethernet/broadcom/bnx2x/bnx2x.h      |   21 +--
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c  |  242 +++++++++++-----------
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h  |    6 +-
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c |   62 ++----
 4 files changed, 148 insertions(+), 183 deletions(-)

-- 
1.7.6

^ permalink raw reply

* Re: 802.1Q VLAN random tag injected when vlan configured on forcedeth interface
From: Ruslan N. Marchenko @ 2011-08-30 14:23 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: netdev
In-Reply-To: <20110830134624.GB28341@ruff.mobi>

On Tue, Aug 30, 2011 at 03:46:24PM +0200, Ruslan N. Marchenko wrote:
> On Tue, Aug 30, 2011 at 03:23:48PM +0200, Eric Dumazet wrote:
> > 
> > What kernel version are you using ?
> > 
> Oh, sorry for missing it, it runs on 
> Linux ruff.mobi 2.6.38-11-generic #48-Ubuntu SMP Fri Jul 29 19:05:14 UTC 2011 i686 i686 i386 GNU/Linux
> 
> Just fyi - the openwrt box to which it is connected is 
> Linux OpenWrt 2.6.39.2 #2 Fri Aug 12 09:36:23 EEST 2011 mips GNU/Linux
> although packet drop happens even if there're no vlans configured on remote side.
> 
Here is double-tag sample:
16:20:31.151268 e0:46:9a:4e:88:1d > 00:26:18:40:21:62, ethertype 802.1Q (0x8100), length 106: vlan 2112, p 7, ethertype 802.1Q, vlan 6, p 0, ethertype IPv4, [|ip]
        0x0000:  0026 1840 2162 e046 9a4e 881d 8100 e840
        0x0010:  8100 0006 0800 4500 0054 abec 0000


Regards,
Ruslan

^ permalink raw reply

* [PATCH 9/9] stmmac: update the driver version (Aug_2011) (v2)
From: Giuseppe CAVALLARO @ 2011-08-30 14:21 UTC (permalink / raw)
  To: netdev; +Cc: Giuseppe Cavallaro
In-Reply-To: <1314714064-29101-1-git-send-email-peppe.cavallaro@st.com>

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
 drivers/net/stmmac/stmmac.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/stmmac/stmmac.h b/drivers/net/stmmac/stmmac.h
index c3a2da7..1434bdb 100644
--- a/drivers/net/stmmac/stmmac.h
+++ b/drivers/net/stmmac/stmmac.h
@@ -20,7 +20,7 @@
   Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
 *******************************************************************************/
 
-#define DRV_MODULE_VERSION	"July_2011"
+#define DRV_MODULE_VERSION	"Aug_2011"
 #include <linux/stmmac.h>
 
 #include "common.h"
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 8/9] stmmac: update the doc with new info about the driver's debug (v2)
From: Giuseppe CAVALLARO @ 2011-08-30 14:21 UTC (permalink / raw)
  To: netdev; +Cc: Giuseppe Cavallaro
In-Reply-To: <1314714064-29101-1-git-send-email-peppe.cavallaro@st.com>

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
 Documentation/networking/stmmac.txt |   33 ++++++++++++++++++++++++++++++++-
 1 files changed, 32 insertions(+), 1 deletions(-)

diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt
index 57a2410..40ec92c 100644
--- a/Documentation/networking/stmmac.txt
+++ b/Documentation/networking/stmmac.txt
@@ -235,7 +235,38 @@ reset procedure etc).
  o enh_desc.c: functions for handling enhanced descriptors
  o norm_desc.c: functions for handling normal descriptors
 
-5) TODO:
+5) Debug Information
+
+The driver exports many information i.e. internal statistics,
+debug information, MAC and DMA registers etc.
+
+These can be read in several ways depending on the
+type of the information actually needed.
+
+For example a user can be use the ethtool support
+to get statistics: e.g. using: ethtool -S ethX
+(that shows the Management counters (MMC) if supported)
+or sees the MAC/DMA registers: e.g. using: ethtool -d ethX
+
+Compiling the Kernel with CONFIG_DEBUG_FS and enabling the
+STMMAC_DEBUG_FS option the driver will export the following
+debugfs entries:
+
+/sys/kernel/debug/stmmaceth/descriptors_status
+  To show the DMA TX/RX descriptor rings
+
+Developer can also use the "debug" module parameter to get
+further debug information.
+
+In the end, there are other macros (that cannot be enabled
+via menuconfig) to turn-on the RX/TX DMA debugging,
+specific MAC core debug printk etc. Others to enable the
+debug in the TX and RX processes.
+All these are only useful during the developing stage
+and should never enabled inside the code for general usage.
+In fact, these can generate an huge amount of debug messages.
+
+6) TODO:
  o XGMAC is not supported.
  o Review the timer optimisation code to use an embedded device that will be
   available in new chip generations.
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 7/9] stmmac: add HW DMA feature register (v2)
From: Giuseppe CAVALLARO @ 2011-08-30 14:21 UTC (permalink / raw)
  To: netdev; +Cc: Giuseppe Cavallaro
In-Reply-To: <1314714064-29101-1-git-send-email-peppe.cavallaro@st.com>

New GMAC chips have an extra register to indicate
the presence of the optional features/functions of
the DMA core.

This patch adds this support and all the HW cap
are exported via debugfs.

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
 drivers/net/stmmac/Kconfig         |    3 +-
 drivers/net/stmmac/common.h        |   33 +++++++++
 drivers/net/stmmac/dwmac1000_dma.c |    6 ++
 drivers/net/stmmac/dwmac_dma.h     |    1 +
 drivers/net/stmmac/stmmac.h        |    1 +
 drivers/net/stmmac/stmmac_main.c   |  131 ++++++++++++++++++++++++++++++++++++
 6 files changed, 174 insertions(+), 1 deletions(-)

diff --git a/drivers/net/stmmac/Kconfig b/drivers/net/stmmac/Kconfig
index c253012..c4be14e 100644
--- a/drivers/net/stmmac/Kconfig
+++ b/drivers/net/stmmac/Kconfig
@@ -16,7 +16,8 @@ config STMMAC_DEBUG_FS
 	default n
 	depends on STMMAC_ETH && DEBUG_FS
 	-- help
-	  The stmmac entry in /sys reports DMA TX/RX rings.
+	  The stmmac entry in /sys reports DMA TX/RX rings
+	  or (if supported) the HW cap register.
 
 config STMMAC_DA
 	bool "STMMAC DMA arbitration scheme"
diff --git a/drivers/net/stmmac/common.h b/drivers/net/stmmac/common.h
index 65b1e56..22c61b2 100644
--- a/drivers/net/stmmac/common.h
+++ b/drivers/net/stmmac/common.h
@@ -116,6 +116,37 @@ enum tx_dma_irq_status {
 	handle_tx_rx = 3,
 };
 
+/* DMA HW capabilities */
+struct dma_features {
+	unsigned int mbps_10_100;
+	unsigned int mbps_1000;
+	unsigned int half_duplex;
+	unsigned int hash_filter;
+	unsigned int multi_addr;
+	unsigned int pcs;
+	unsigned int sma_mdio;
+	unsigned int pmt_remote_wake_up;
+	unsigned int pmt_magic_frame;
+	unsigned int rmon;
+	/* IEEE 1588-2002*/
+	unsigned int time_stamp;
+	/* IEEE 1588-2008*/
+	unsigned int atime_stamp;
+	/* 802.3az - Energy-Efficient Ethernet (EEE) */
+	unsigned int eee;
+	unsigned int av;
+	/* TX and RX csum */
+	unsigned int tx_coe;
+	unsigned int rx_coe_type1;
+	unsigned int rx_coe_type2;
+	unsigned int rxfifo_over_2048;
+	/* TX and RX number of channels */
+	unsigned int number_rx_channel;
+	unsigned int number_tx_channel;
+	/* Alternate (enhanced) DESC mode*/
+	unsigned int enh_desc;
+};
+
 /* GMAC TX FIFO is 8K, Rx FIFO is 16K */
 #define BUF_SIZE_16KiB 16384
 #define BUF_SIZE_8KiB 8192
@@ -188,6 +219,8 @@ struct stmmac_dma_ops {
 	void (*stop_rx) (void __iomem *ioaddr);
 	int (*dma_interrupt) (void __iomem *ioaddr,
 			      struct stmmac_extra_stats *x);
+	/* If supported then get the optional core features */
+	unsigned int (*get_hw_feature) (void __iomem *ioaddr);
 };
 
 struct stmmac_ops {
diff --git a/drivers/net/stmmac/dwmac1000_dma.c b/drivers/net/stmmac/dwmac1000_dma.c
index a89384c..da66ac5 100644
--- a/drivers/net/stmmac/dwmac1000_dma.c
+++ b/drivers/net/stmmac/dwmac1000_dma.c
@@ -132,6 +132,11 @@ static void dwmac1000_dump_dma_regs(void __iomem *ioaddr)
 	}
 }
 
+static unsigned int dwmac1000_get_hw_feature(void __iomem *ioaddr)
+{
+	return readl(ioaddr + DMA_HW_FEATURE);
+}
+
 const struct stmmac_dma_ops dwmac1000_dma_ops = {
 	.init = dwmac1000_dma_init,
 	.dump_regs = dwmac1000_dump_dma_regs,
@@ -144,4 +149,5 @@ const struct stmmac_dma_ops dwmac1000_dma_ops = {
 	.start_rx = dwmac_dma_start_rx,
 	.stop_rx = dwmac_dma_stop_rx,
 	.dma_interrupt = dwmac_dma_interrupt,
+	.get_hw_feature = dwmac1000_get_hw_feature,
 };
diff --git a/drivers/net/stmmac/dwmac_dma.h b/drivers/net/stmmac/dwmac_dma.h
index da3f5cc..437edac 100644
--- a/drivers/net/stmmac/dwmac_dma.h
+++ b/drivers/net/stmmac/dwmac_dma.h
@@ -34,6 +34,7 @@
 #define DMA_MISSED_FRAME_CTR	0x00001020	/* Missed Frame Counter */
 #define DMA_CUR_TX_BUF_ADDR	0x00001050	/* Current Host Tx Buffer */
 #define DMA_CUR_RX_BUF_ADDR	0x00001054	/* Current Host Rx Buffer */
+#define DMA_HW_FEATURE		0x00001058	/* HW Feature Register */
 
 /* DMA Control register defines */
 #define DMA_CONTROL_ST		0x00002000	/* Start/Stop Transmission */
diff --git a/drivers/net/stmmac/stmmac.h b/drivers/net/stmmac/stmmac.h
index ef03796..c3a2da7 100644
--- a/drivers/net/stmmac/stmmac.h
+++ b/drivers/net/stmmac/stmmac.h
@@ -78,6 +78,7 @@ struct stmmac_priv {
 #endif
 	struct plat_stmmacenet_data *plat;
 	struct stmmac_counters mmc;
+	struct dma_features dma_cap;
 };
 
 extern int stmmac_mdio_unregister(struct net_device *ndev);
diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c
index f9ba0f7..a87d583 100644
--- a/drivers/net/stmmac/stmmac_main.c
+++ b/drivers/net/stmmac/stmmac_main.c
@@ -779,6 +779,49 @@ static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv)
 	}
 	return 0;
 }
+
+/* New GMAC chips support a new register to indicate the
+ * presence of the optional feature/functions.
+ */
+static int stmmac_get_hw_features(struct stmmac_priv *priv)
+{
+	u32 hw_cap = priv->hw->dma->get_hw_feature(priv->ioaddr);
+
+	if (likely(hw_cap)) {
+		priv->dma_cap.mbps_10_100 = (hw_cap & 0x1);
+		priv->dma_cap.mbps_1000 = (hw_cap & 0x2) >> 1;
+		priv->dma_cap.half_duplex = (hw_cap & 0x4) >> 2;
+		priv->dma_cap.hash_filter = (hw_cap & 0x10) >> 4;
+		priv->dma_cap.multi_addr = (hw_cap & 0x20) >> 5;
+		priv->dma_cap.pcs = (hw_cap & 0x40) >> 6;
+		priv->dma_cap.sma_mdio = (hw_cap & 0x100) >> 8;
+		priv->dma_cap.pmt_remote_wake_up = (hw_cap & 0x200) >> 9;
+		priv->dma_cap.pmt_magic_frame = (hw_cap & 0x400) >> 10;
+		priv->dma_cap.rmon = (hw_cap & 0x800) >> 11; /* MMC */
+		/* IEEE 1588-2002*/
+		priv->dma_cap.time_stamp = (hw_cap & 0x1000) >> 12;
+		/* IEEE 1588-2008*/
+		priv->dma_cap.atime_stamp = (hw_cap & 0x2000) >> 13;
+		/* 802.3az - Energy-Efficient Ethernet (EEE) */
+		priv->dma_cap.eee = (hw_cap & 0x4000) >> 14;
+		priv->dma_cap.av = (hw_cap & 0x8000) >> 15;
+		/* TX and RX csum */
+		priv->dma_cap.tx_coe = (hw_cap & 0x10000) >> 16;
+		priv->dma_cap.rx_coe_type1 = (hw_cap & 0x20000) >> 17;
+		priv->dma_cap.rx_coe_type2 = (hw_cap & 0x40000) >> 18;
+		priv->dma_cap.rxfifo_over_2048 = (hw_cap & 0x80000) >> 19;
+		/* TX and RX number of channels */
+		priv->dma_cap.number_rx_channel = (hw_cap & 0x300000) >> 20;
+		priv->dma_cap.number_tx_channel = (hw_cap & 0xc00000) >> 22;
+		/* Alternate (enhanced) DESC mode*/
+		priv->dma_cap.enh_desc = (hw_cap & 0x1000000) >> 24;
+
+	} else
+		pr_debug("\tNo HW DMA feature register supported");
+
+	return hw_cap;
+}
+
 /**
  *  stmmac_open - open entry point of the driver
  *  @dev : pointer to the device structure.
@@ -853,6 +896,8 @@ static int stmmac_open(struct net_device *dev)
 
 	stmmac_get_synopsys_id(priv);
 
+	stmmac_get_hw_features(priv);
+
 	if (priv->rx_coe)
 		pr_info("stmmac: Rx Checksum Offload Engine supported\n");
 	if (priv->plat->tx_coe)
@@ -1449,6 +1494,7 @@ static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 #ifdef CONFIG_STMMAC_DEBUG_FS
 static struct dentry *stmmac_fs_dir;
 static struct dentry *stmmac_rings_status;
+static struct dentry *stmmac_dma_cap;
 
 static int stmmac_sysfs_ring_read(struct seq_file *seq, void *v)
 {
@@ -1502,6 +1548,78 @@ static const struct file_operations stmmac_rings_status_fops = {
 	.release = seq_release,
 };
 
+static int stmmac_sysfs_dma_cap_read(struct seq_file *seq, void *v)
+{
+	struct net_device *dev = seq->private;
+	struct stmmac_priv *priv = netdev_priv(dev);
+
+	if (!stmmac_get_hw_features(priv)) {
+		seq_printf(seq, "DMA HW features not supported\n");
+		return 0;
+	}
+
+	seq_printf(seq, "==============================\n");
+	seq_printf(seq, "\tDMA HW features\n");
+	seq_printf(seq, "==============================\n");
+
+	seq_printf(seq, "\t10/100 Mbps %s\n",
+		   (priv->dma_cap.mbps_10_100) ? "Y" : "N");
+	seq_printf(seq, "\t1000 Mbps %s\n",
+		   (priv->dma_cap.mbps_1000) ? "Y" : "N");
+	seq_printf(seq, "\tHalf duple %s\n",
+		   (priv->dma_cap.half_duplex) ? "Y" : "N");
+	seq_printf(seq, "\tHash Filter: %s\n",
+		   (priv->dma_cap.hash_filter) ? "Y" : "N");
+	seq_printf(seq, "\tMultiple MAC address registers: %s\n",
+		   (priv->dma_cap.multi_addr) ? "Y" : "N");
+	seq_printf(seq, "\tPCS (TBI/SGMII/RTBI PHY interfatces): %s\n",
+		   (priv->dma_cap.pcs) ? "Y" : "N");
+	seq_printf(seq, "\tSMA (MDIO) Interface: %s\n",
+		   (priv->dma_cap.sma_mdio) ? "Y" : "N");
+	seq_printf(seq, "\tPMT Remote wake up: %s\n",
+		   (priv->dma_cap.pmt_remote_wake_up) ? "Y" : "N");
+	seq_printf(seq, "\tPMT Magic Frame: %s\n",
+		   (priv->dma_cap.pmt_magic_frame) ? "Y" : "N");
+	seq_printf(seq, "\tRMON module: %s\n",
+		   (priv->dma_cap.rmon) ? "Y" : "N");
+	seq_printf(seq, "\tIEEE 1588-2002 Time Stamp: %s\n",
+		   (priv->dma_cap.time_stamp) ? "Y" : "N");
+	seq_printf(seq, "\tIEEE 1588-2008 Advanced Time Stamp:%s\n",
+		   (priv->dma_cap.atime_stamp) ? "Y" : "N");
+	seq_printf(seq, "\t802.3az - Energy-Efficient Ethernet (EEE) %s\n",
+		   (priv->dma_cap.eee) ? "Y" : "N");
+	seq_printf(seq, "\tAV features: %s\n", (priv->dma_cap.av) ? "Y" : "N");
+	seq_printf(seq, "\tChecksum Offload in TX: %s\n",
+		   (priv->dma_cap.tx_coe) ? "Y" : "N");
+	seq_printf(seq, "\tIP Checksum Offload (type1) in RX: %s\n",
+		   (priv->dma_cap.rx_coe_type1) ? "Y" : "N");
+	seq_printf(seq, "\tIP Checksum Offload (type2) in RX: %s\n",
+		   (priv->dma_cap.rx_coe_type2) ? "Y" : "N");
+	seq_printf(seq, "\tRXFIFO > 2048bytes: %s\n",
+		   (priv->dma_cap.rxfifo_over_2048) ? "Y" : "N");
+	seq_printf(seq, "\tNumber of Additional RX channel: %d\n",
+		   priv->dma_cap.number_rx_channel);
+	seq_printf(seq, "\tNumber of Additional TX channel: %d\n",
+		   priv->dma_cap.number_tx_channel);
+	seq_printf(seq, "\tEnhanced descriptors: %s\n",
+		   (priv->dma_cap.enh_desc) ? "Y" : "N");
+
+	return 0;
+}
+
+static int stmmac_sysfs_dma_cap_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, stmmac_sysfs_dma_cap_read, inode->i_private);
+}
+
+static const struct file_operations stmmac_dma_cap_fops = {
+	.owner = THIS_MODULE,
+	.open = stmmac_sysfs_dma_cap_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release,
+};
+
 static int stmmac_init_fs(struct net_device *dev)
 {
 	/* Create debugfs entries */
@@ -1526,12 +1644,25 @@ static int stmmac_init_fs(struct net_device *dev)
 		return -ENOMEM;
 	}
 
+	/* Entry to report the DMA HW features */
+	stmmac_dma_cap = debugfs_create_file("dma_cap", S_IRUGO, stmmac_fs_dir,
+					     dev, &stmmac_dma_cap_fops);
+
+	if (!stmmac_dma_cap || IS_ERR(stmmac_dma_cap)) {
+		pr_info("ERROR creating stmmac MMC debugfs file\n");
+		debugfs_remove(stmmac_rings_status);
+		debugfs_remove(stmmac_fs_dir);
+
+		return -ENOMEM;
+	}
+
 	return 0;
 }
 
 static void stmmac_exit_fs(void)
 {
 	debugfs_remove(stmmac_rings_status);
+	debugfs_remove(stmmac_dma_cap);
 	debugfs_remove(stmmac_fs_dir);
 }
 #endif /* CONFIG_STMMAC_DEBUG_FS */
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 6/9] stmmac: rework the code to get the Synopsys ID (v2)
From: Giuseppe CAVALLARO @ 2011-08-30 14:21 UTC (permalink / raw)
  To: netdev; +Cc: Giuseppe Cavallaro
In-Reply-To: <1314714064-29101-1-git-send-email-peppe.cavallaro@st.com>

The Synopsys ID is now passed from the MAC core
to the main. This info will be used for managing
the HW cap register (supported in the new GMAC
generations).

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
 drivers/net/stmmac/common.h         |    1 +
 drivers/net/stmmac/dwmac1000_core.c |    6 ++----
 drivers/net/stmmac/dwmac100_core.c  |    1 +
 drivers/net/stmmac/stmmac_main.c    |   20 +++++++++++++++++++-
 4 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/drivers/net/stmmac/common.h b/drivers/net/stmmac/common.h
index e08fee8..65b1e56 100644
--- a/drivers/net/stmmac/common.h
+++ b/drivers/net/stmmac/common.h
@@ -230,6 +230,7 @@ struct mac_device_info {
 	const struct stmmac_dma_ops	*dma;
 	struct mii_regs mii;	/* MII register Addresses */
 	struct mac_link link;
+	unsigned int synopsys_uid;
 };
 
 struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr);
diff --git a/drivers/net/stmmac/dwmac1000_core.c b/drivers/net/stmmac/dwmac1000_core.c
index 9ba9cae..b1c48b9 100644
--- a/drivers/net/stmmac/dwmac1000_core.c
+++ b/drivers/net/stmmac/dwmac1000_core.c
@@ -224,10 +224,7 @@ static const struct stmmac_ops dwmac1000_ops = {
 struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr)
 {
 	struct mac_device_info *mac;
-	u32 uid = readl(ioaddr + GMAC_VERSION);
-
-	pr_info("\tDWMAC1000 - user ID: 0x%x, Synopsys ID: 0x%x\n",
-		((uid & 0x0000ff00) >> 8), (uid & 0x000000ff));
+	u32 hwid = readl(ioaddr + GMAC_VERSION);
 
 	mac = kzalloc(sizeof(const struct mac_device_info), GFP_KERNEL);
 	if (!mac)
@@ -241,6 +238,7 @@ struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr)
 	mac->link.speed = GMAC_CONTROL_FES;
 	mac->mii.addr = GMAC_MII_ADDR;
 	mac->mii.data = GMAC_MII_DATA;
+	mac->synopsys_uid = hwid;
 
 	return mac;
 }
diff --git a/drivers/net/stmmac/dwmac100_core.c b/drivers/net/stmmac/dwmac100_core.c
index aacfc6e..138fb8d 100644
--- a/drivers/net/stmmac/dwmac100_core.c
+++ b/drivers/net/stmmac/dwmac100_core.c
@@ -188,6 +188,7 @@ struct mac_device_info *dwmac100_setup(void __iomem *ioaddr)
 	mac->link.speed = 0;
 	mac->mii.addr = MAC_MII_ADDR;
 	mac->mii.data = MAC_MII_DATA;
+	mac->synopsys_uid = 0;
 
 	return mac;
 }
diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c
index 1319b4c..f9ba0f7 100644
--- a/drivers/net/stmmac/stmmac_main.c
+++ b/drivers/net/stmmac/stmmac_main.c
@@ -762,6 +762,23 @@ static void stmmac_mmc_setup(struct stmmac_priv *priv)
 	memset(&priv->mmc, 0, sizeof(struct stmmac_counters));
 }
 
+static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv)
+{
+	u32 hwid = priv->hw->synopsys_uid;
+
+	/* Only check valid Synopsys Id because old MAC chips
+	 * have no HW registers where get the ID */
+	if (likely(hwid)) {
+		u32 uid = ((hwid & 0x0000ff00) >> 8);
+		u32 synid = (hwid & 0x000000ff);
+
+		pr_info("STMMAC - user ID: 0x%x, Synopsys ID: 0x%x\n",
+			uid, synid);
+
+		return synid;
+	}
+	return 0;
+}
 /**
  *  stmmac_open - open entry point of the driver
  *  @dev : pointer to the device structure.
@@ -834,7 +851,8 @@ static int stmmac_open(struct net_device *dev)
 	/* Initialize the MAC Core */
 	priv->hw->mac->core_init(priv->ioaddr);
 
-	priv->rx_coe = priv->hw->mac->rx_coe(priv->ioaddr);
+	stmmac_get_synopsys_id(priv);
+
 	if (priv->rx_coe)
 		pr_info("stmmac: Rx Checksum Offload Engine supported\n");
 	if (priv->plat->tx_coe)
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 5/9] stmmac: export DMA TX/RX rings via debugfs (v2)
From: Giuseppe CAVALLARO @ 2011-08-30 14:21 UTC (permalink / raw)
  To: netdev; +Cc: Giuseppe Cavallaro
In-Reply-To: <1314714064-29101-1-git-send-email-peppe.cavallaro@st.com>

This patch adds the following debugFs entry to dump the
RX/TX DMA rings:

/sys/kernel/debug/stmmaceth/descriptors_status

This is an example:
=======================
  RX descriptor ring
=======================
[0] DES0=0x85ee0320 DES1=0x1fff1fff BUF1=0x5fae2022 BUF2=0x0
[1] DES0=0x85ee0320 DES1=0x1fff1fff BUF1=0x5fae0022 BUF2=0x0
[2] DES0=0x81460320 DES1=0x1fff1fff BUF1=0x5f9dd022 BUF2=0x0

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
 drivers/net/stmmac/Kconfig       |    7 +++
 drivers/net/stmmac/stmmac_main.c |  105 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 112 insertions(+), 0 deletions(-)

diff --git a/drivers/net/stmmac/Kconfig b/drivers/net/stmmac/Kconfig
index 7df7df4..c253012 100644
--- a/drivers/net/stmmac/Kconfig
+++ b/drivers/net/stmmac/Kconfig
@@ -11,6 +11,13 @@ config STMMAC_ETH
 
 if STMMAC_ETH
 
+config STMMAC_DEBUG_FS
+	bool "Enable monitoring via sysFS "
+	default n
+	depends on STMMAC_ETH && DEBUG_FS
+	-- help
+	  The stmmac entry in /sys reports DMA TX/RX rings.
+
 config STMMAC_DA
 	bool "STMMAC DMA arbitration scheme"
 	default n
diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c
index 88b2973..1319b4c 100644
--- a/drivers/net/stmmac/stmmac_main.c
+++ b/drivers/net/stmmac/stmmac_main.c
@@ -47,6 +47,10 @@
 #include <linux/slab.h>
 #include <linux/prefetch.h>
 #include "stmmac.h"
+#ifdef CONFIG_STMMAC_DEBUG_FS
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#endif
 
 #define STMMAC_RESOURCE_NAME	"stmmaceth"
 
@@ -1424,6 +1428,96 @@ static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 	return ret;
 }
 
+#ifdef CONFIG_STMMAC_DEBUG_FS
+static struct dentry *stmmac_fs_dir;
+static struct dentry *stmmac_rings_status;
+
+static int stmmac_sysfs_ring_read(struct seq_file *seq, void *v)
+{
+	struct tmp_s {
+		u64 a;
+		unsigned int b;
+		unsigned int c;
+	};
+	int i;
+	struct net_device *dev = seq->private;
+	struct stmmac_priv *priv = netdev_priv(dev);
+
+	seq_printf(seq, "=======================\n");
+	seq_printf(seq, " RX descriptor ring\n");
+	seq_printf(seq, "=======================\n");
+
+	for (i = 0; i < priv->dma_rx_size; i++) {
+		struct tmp_s *x = (struct tmp_s *)(priv->dma_rx + i);
+		seq_printf(seq, "[%d] DES0=0x%x DES1=0x%x BUF1=0x%x BUF2=0x%x",
+			   i, (unsigned int)(x->a),
+			   (unsigned int)((x->a) >> 32), x->b, x->c);
+		seq_printf(seq, "\n");
+	}
+
+	seq_printf(seq, "\n");
+	seq_printf(seq, "=======================\n");
+	seq_printf(seq, "  TX descriptor ring\n");
+	seq_printf(seq, "=======================\n");
+
+	for (i = 0; i < priv->dma_tx_size; i++) {
+		struct tmp_s *x = (struct tmp_s *)(priv->dma_tx + i);
+		seq_printf(seq, "[%d] DES0=0x%x DES1=0x%x BUF1=0x%x BUF2=0x%x",
+			   i, (unsigned int)(x->a),
+			   (unsigned int)((x->a) >> 32), x->b, x->c);
+		seq_printf(seq, "\n");
+	}
+
+	return 0;
+}
+
+static int stmmac_sysfs_ring_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, stmmac_sysfs_ring_read, inode->i_private);
+}
+
+static const struct file_operations stmmac_rings_status_fops = {
+	.owner = THIS_MODULE,
+	.open = stmmac_sysfs_ring_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release,
+};
+
+static int stmmac_init_fs(struct net_device *dev)
+{
+	/* Create debugfs entries */
+	stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL);
+
+	if (!stmmac_fs_dir || IS_ERR(stmmac_fs_dir)) {
+		pr_err("ERROR %s, debugfs create directory failed\n",
+		       STMMAC_RESOURCE_NAME);
+
+		return -ENOMEM;
+	}
+
+	/* Entry to report DMA RX/TX rings */
+	stmmac_rings_status = debugfs_create_file("descriptors_status",
+					   S_IRUGO, stmmac_fs_dir, dev,
+					   &stmmac_rings_status_fops);
+
+	if (!stmmac_rings_status || IS_ERR(stmmac_rings_status)) {
+		pr_info("ERROR creating stmmac ring debugfs file\n");
+		debugfs_remove(stmmac_fs_dir);
+
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void stmmac_exit_fs(void)
+{
+	debugfs_remove(stmmac_rings_status);
+	debugfs_remove(stmmac_fs_dir);
+}
+#endif /* CONFIG_STMMAC_DEBUG_FS */
+
 static const struct net_device_ops stmmac_netdev_ops = {
 	.ndo_open = stmmac_open,
 	.ndo_start_xmit = stmmac_xmit,
@@ -1648,6 +1742,13 @@ static int stmmac_dvr_probe(struct platform_device *pdev)
 	if (ret < 0)
 		goto out_unregister;
 	pr_debug("registered!\n");
+
+#ifdef CONFIG_STMMAC_DEBUG_FS
+	ret = stmmac_init_fs(ndev);
+	if (ret < 0)
+		pr_warning("\tFailed debugFS registration");
+#endif
+
 	return 0;
 
 out_unregister:
@@ -1700,6 +1801,10 @@ static int stmmac_dvr_remove(struct platform_device *pdev)
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	release_mem_region(res->start, resource_size(res));
 
+#ifdef CONFIG_STMMAC_DEBUG_FS
+	stmmac_exit_fs();
+#endif
+
 	free_netdev(ndev);
 
 	return 0;
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 4/9] stmmac: add MMC support exported via ethtool (v2)
From: Giuseppe CAVALLARO @ 2011-08-30 14:20 UTC (permalink / raw)
  To: netdev; +Cc: Giuseppe Cavallaro
In-Reply-To: <1314714064-29101-1-git-send-email-peppe.cavallaro@st.com>

This patch adds the MMC management counters support.
MMC module is an extension of the register address
space and all the hardware counters can be accessed
via ethtoo -S ethX.

Note that, the MMC interrupts remain masked and the logic
to handle this kind of interrupt will be added later (if
actually useful).

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
 drivers/net/stmmac/Makefile         |    3 +-
 drivers/net/stmmac/common.h         |    1 +
 drivers/net/stmmac/dwmac1000_dma.c  |    8 -
 drivers/net/stmmac/mmc.h            |  131 +++++++++++++++++
 drivers/net/stmmac/mmc_core.c       |  265 +++++++++++++++++++++++++++++++++++
 drivers/net/stmmac/stmmac.h         |    1 +
 drivers/net/stmmac/stmmac_ethtool.c |  145 +++++++++++++++++--
 drivers/net/stmmac/stmmac_main.c    |   13 ++
 8 files changed, 544 insertions(+), 23 deletions(-)
 create mode 100644 drivers/net/stmmac/mmc.h
 create mode 100644 drivers/net/stmmac/mmc_core.c

diff --git a/drivers/net/stmmac/Makefile b/drivers/net/stmmac/Makefile
index 9691733..0f23d95 100644
--- a/drivers/net/stmmac/Makefile
+++ b/drivers/net/stmmac/Makefile
@@ -2,4 +2,5 @@ obj-$(CONFIG_STMMAC_ETH) += stmmac.o
 stmmac-$(CONFIG_STMMAC_TIMER) += stmmac_timer.o
 stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o	\
 	      dwmac_lib.o dwmac1000_core.o  dwmac1000_dma.o	\
-	      dwmac100_core.o dwmac100_dma.o enh_desc.o  norm_desc.o $(stmmac-y)
+	      dwmac100_core.o dwmac100_dma.o enh_desc.o  norm_desc.o \
+	      mmc_core.o $(stmmac-y)
diff --git a/drivers/net/stmmac/common.h b/drivers/net/stmmac/common.h
index 290b97a..e08fee8 100644
--- a/drivers/net/stmmac/common.h
+++ b/drivers/net/stmmac/common.h
@@ -29,6 +29,7 @@
 #endif
 
 #include "descs.h"
+#include "mmc.h"
 
 #undef CHIP_DEBUG_PRINT
 /* Turn-on extra printk debug for MAC core, dma and descriptors */
diff --git a/drivers/net/stmmac/dwmac1000_dma.c b/drivers/net/stmmac/dwmac1000_dma.c
index 3dbeea6..a89384c 100644
--- a/drivers/net/stmmac/dwmac1000_dma.c
+++ b/drivers/net/stmmac/dwmac1000_dma.c
@@ -118,13 +118,6 @@ static void dwmac1000_dma_operation_mode(void __iomem *ioaddr, int txmode,
 	writel(csr6, ioaddr + DMA_CONTROL);
 }
 
-/* Not yet implemented --- no RMON module */
-static void dwmac1000_dma_diagnostic_fr(void *data,
-		  struct stmmac_extra_stats *x, void __iomem *ioaddr)
-{
-	return;
-}
-
 static void dwmac1000_dump_dma_regs(void __iomem *ioaddr)
 {
 	int i;
@@ -143,7 +136,6 @@ const struct stmmac_dma_ops dwmac1000_dma_ops = {
 	.init = dwmac1000_dma_init,
 	.dump_regs = dwmac1000_dump_dma_regs,
 	.dma_mode = dwmac1000_dma_operation_mode,
-	.dma_diagnostic_fr = dwmac1000_dma_diagnostic_fr,
 	.enable_dma_transmission = dwmac_enable_dma_transmission,
 	.enable_dma_irq = dwmac_enable_dma_irq,
 	.disable_dma_irq = dwmac_disable_dma_irq,
diff --git a/drivers/net/stmmac/mmc.h b/drivers/net/stmmac/mmc.h
new file mode 100644
index 0000000..a383520
--- /dev/null
+++ b/drivers/net/stmmac/mmc.h
@@ -0,0 +1,131 @@
+/*******************************************************************************
+  MMC Header file
+
+  Copyright (C) 2011  STMicroelectronics Ltd
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms and conditions of the GNU General Public License,
+  version 2, as published by the Free Software Foundation.
+
+  This program is distributed in the hope it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+  more details.
+
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+  The full GNU General Public License is included in this distribution in
+  the file called "COPYING".
+
+  Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+*******************************************************************************/
+
+/* MMC control register */
+/* When set, all counter are reset */
+#define MMC_CNTRL_COUNTER_RESET		0x1
+/* When set, do not roll over zero
+ * after reaching the max value*/
+#define MMC_CNTRL_COUNTER_STOP_ROLLOVER	0x2
+#define MMC_CNTRL_RESET_ON_READ		0x4	/* Reset after reading */
+#define MMC_CNTRL_COUNTER_FREEZER	0x8	/* Freeze counter values to the
+						 * current value.*/
+#define MMC_CNTRL_PRESET		0x10
+#define MMC_CNTRL_FULL_HALF_PRESET	0x20
+struct stmmac_counters {
+	unsigned int mmc_tx_octetcount_gb;
+	unsigned int mmc_tx_framecount_gb;
+	unsigned int mmc_tx_broadcastframe_g;
+	unsigned int mmc_tx_multicastframe_g;
+	unsigned int mmc_tx_64_octets_gb;
+	unsigned int mmc_tx_65_to_127_octets_gb;
+	unsigned int mmc_tx_128_to_255_octets_gb;
+	unsigned int mmc_tx_256_to_511_octets_gb;
+	unsigned int mmc_tx_512_to_1023_octets_gb;
+	unsigned int mmc_tx_1024_to_max_octets_gb;
+	unsigned int mmc_tx_unicast_gb;
+	unsigned int mmc_tx_multicast_gb;
+	unsigned int mmc_tx_broadcast_gb;
+	unsigned int mmc_tx_underflow_error;
+	unsigned int mmc_tx_singlecol_g;
+	unsigned int mmc_tx_multicol_g;
+	unsigned int mmc_tx_deferred;
+	unsigned int mmc_tx_latecol;
+	unsigned int mmc_tx_exesscol;
+	unsigned int mmc_tx_carrier_error;
+	unsigned int mmc_tx_octetcount_g;
+	unsigned int mmc_tx_framecount_g;
+	unsigned int mmc_tx_excessdef;
+	unsigned int mmc_tx_pause_frame;
+	unsigned int mmc_tx_vlan_frame_g;
+
+	/* MMC RX counter registers */
+	unsigned int mmc_rx_framecount_gb;
+	unsigned int mmc_rx_octetcount_gb;
+	unsigned int mmc_rx_octetcount_g;
+	unsigned int mmc_rx_broadcastframe_g;
+	unsigned int mmc_rx_multicastframe_g;
+	unsigned int mmc_rx_crc_errror;
+	unsigned int mmc_rx_align_error;
+	unsigned int mmc_rx_run_error;
+	unsigned int mmc_rx_jabber_error;
+	unsigned int mmc_rx_undersize_g;
+	unsigned int mmc_rx_oversize_g;
+	unsigned int mmc_rx_64_octets_gb;
+	unsigned int mmc_rx_65_to_127_octets_gb;
+	unsigned int mmc_rx_128_to_255_octets_gb;
+	unsigned int mmc_rx_256_to_511_octets_gb;
+	unsigned int mmc_rx_512_to_1023_octets_gb;
+	unsigned int mmc_rx_1024_to_max_octets_gb;
+	unsigned int mmc_rx_unicast_g;
+	unsigned int mmc_rx_length_error;
+	unsigned int mmc_rx_autofrangetype;
+	unsigned int mmc_rx_pause_frames;
+	unsigned int mmc_rx_fifo_overflow;
+	unsigned int mmc_rx_vlan_frames_gb;
+	unsigned int mmc_rx_watchdog_error;
+	/* IPC */
+	unsigned int mmc_rx_ipc_intr_mask;
+	unsigned int mmc_rx_ipc_intr;
+	/* IPv4 */
+	unsigned int mmc_rx_ipv4_gd;
+	unsigned int mmc_rx_ipv4_hderr;
+	unsigned int mmc_rx_ipv4_nopay;
+	unsigned int mmc_rx_ipv4_frag;
+	unsigned int mmc_rx_ipv4_udsbl;
+
+	unsigned int mmc_rx_ipv4_gd_octets;
+	unsigned int mmc_rx_ipv4_hderr_octets;
+	unsigned int mmc_rx_ipv4_nopay_octets;
+	unsigned int mmc_rx_ipv4_frag_octets;
+	unsigned int mmc_rx_ipv4_udsbl_octets;
+
+	/* IPV6 */
+	unsigned int mmc_rx_ipv6_gd_octets;
+	unsigned int mmc_rx_ipv6_hderr_octets;
+	unsigned int mmc_rx_ipv6_nopay_octets;
+
+	unsigned int mmc_rx_ipv6_gd;
+	unsigned int mmc_rx_ipv6_hderr;
+	unsigned int mmc_rx_ipv6_nopay;
+
+	/* Protocols */
+	unsigned int mmc_rx_udp_gd;
+	unsigned int mmc_rx_udp_err;
+	unsigned int mmc_rx_tcp_gd;
+	unsigned int mmc_rx_tcp_err;
+	unsigned int mmc_rx_icmp_gd;
+	unsigned int mmc_rx_icmp_err;
+
+	unsigned int mmc_rx_udp_gd_octets;
+	unsigned int mmc_rx_udp_err_octets;
+	unsigned int mmc_rx_tcp_gd_octets;
+	unsigned int mmc_rx_tcp_err_octets;
+	unsigned int mmc_rx_icmp_gd_octets;
+	unsigned int mmc_rx_icmp_err_octets;
+};
+
+extern void dwmac_mmc_ctrl(void __iomem *ioaddr, unsigned int mode);
+extern void dwmac_mmc_intr_all_mask(void __iomem *ioaddr);
+extern void dwmac_mmc_read(void __iomem *ioaddr, struct stmmac_counters *mmc);
diff --git a/drivers/net/stmmac/mmc_core.c b/drivers/net/stmmac/mmc_core.c
new file mode 100644
index 0000000..41e6b33
--- /dev/null
+++ b/drivers/net/stmmac/mmc_core.c
@@ -0,0 +1,265 @@
+/*******************************************************************************
+  DWMAC Management Counters
+
+  Copyright (C) 2011  STMicroelectronics Ltd
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms and conditions of the GNU General Public License,
+  version 2, as published by the Free Software Foundation.
+
+  This program is distributed in the hope it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+  more details.
+
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+  The full GNU General Public License is included in this distribution in
+  the file called "COPYING".
+
+  Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+*******************************************************************************/
+
+#include <linux/io.h>
+#include "mmc.h"
+
+/* MAC Management Counters register offset */
+
+#define MMC_CNTRL		0x00000100	/* MMC Control */
+#define MMC_RX_INTR		0x00000104	/* MMC RX Interrupt */
+#define MMC_TX_INTR		0x00000108	/* MMC TX Interrupt */
+#define MMC_RX_INTR_MASK	0x0000010c	/* MMC Interrupt Mask */
+#define MMC_TX_INTR_MASK	0x00000110	/* MMC Interrupt Mask */
+#define MMC_DEFAUL_MASK		0xffffffff
+
+/* MMC TX counter registers */
+
+/* Note:
+ * _GB register stands for good and bad frames
+ * _G is for good only.
+ */
+#define MMC_TX_OCTETCOUNT_GB		0x00000114
+#define MMC_TX_FRAMECOUNT_GB		0x00000118
+#define MMC_TX_BROADCASTFRAME_G		0x0000011c
+#define MMC_TX_MULTICASTFRAME_G		0x00000120
+#define MMC_TX_64_OCTETS_GB		0x00000124
+#define MMC_TX_65_TO_127_OCTETS_GB	0x00000128
+#define MMC_TX_128_TO_255_OCTETS_GB	0x0000012c
+#define MMC_TX_256_TO_511_OCTETS_GB	0x00000130
+#define MMC_TX_512_TO_1023_OCTETS_GB	0x00000134
+#define MMC_TX_1024_TO_MAX_OCTETS_GB	0x00000138
+#define MMC_TX_UNICAST_GB		0x0000013c
+#define MMC_TX_MULTICAST_GB		0x00000140
+#define MMC_TX_BROADCAST_GB		0x00000144
+#define MMC_TX_UNDERFLOW_ERROR		0x00000148
+#define MMC_TX_SINGLECOL_G		0x0000014c
+#define MMC_TX_MULTICOL_G		0x00000150
+#define MMC_TX_DEFERRED			0x00000154
+#define MMC_TX_LATECOL			0x00000158
+#define MMC_TX_EXESSCOL			0x0000015c
+#define MMC_TX_CARRIER_ERROR		0x00000160
+#define MMC_TX_OCTETCOUNT_G		0x00000164
+#define MMC_TX_FRAMECOUNT_G		0x00000168
+#define MMC_TX_EXCESSDEF		0x0000016c
+#define MMC_TX_PAUSE_FRAME		0x00000170
+#define MMC_TX_VLAN_FRAME_G		0x00000174
+
+/* MMC RX counter registers */
+#define MMC_RX_FRAMECOUNT_GB		0x00000180
+#define MMC_RX_OCTETCOUNT_GB		0x00000184
+#define MMC_RX_OCTETCOUNT_G		0x00000188
+#define MMC_RX_BROADCASTFRAME_G		0x0000018c
+#define MMC_RX_MULTICASTFRAME_G		0x00000190
+#define MMC_RX_CRC_ERRROR		0x00000194
+#define MMC_RX_ALIGN_ERROR		0x00000198
+#define MMC_RX_RUN_ERROR		0x0000019C
+#define MMC_RX_JABBER_ERROR		0x000001A0
+#define MMC_RX_UNDERSIZE_G		0x000001A4
+#define MMC_RX_OVERSIZE_G		0x000001A8
+#define MMC_RX_64_OCTETS_GB		0x000001AC
+#define MMC_RX_65_TO_127_OCTETS_GB	0x000001b0
+#define MMC_RX_128_TO_255_OCTETS_GB	0x000001b4
+#define MMC_RX_256_TO_511_OCTETS_GB	0x000001b8
+#define MMC_RX_512_TO_1023_OCTETS_GB	0x000001bc
+#define MMC_RX_1024_TO_MAX_OCTETS_GB	0x000001c0
+#define MMC_RX_UNICAST_G		0x000001c4
+#define MMC_RX_LENGTH_ERROR		0x000001c8
+#define MMC_RX_AUTOFRANGETYPE		0x000001cc
+#define MMC_RX_PAUSE_FRAMES		0x000001d0
+#define MMC_RX_FIFO_OVERFLOW		0x000001d4
+#define MMC_RX_VLAN_FRAMES_GB		0x000001d8
+#define MMC_RX_WATCHDOG_ERROR		0x000001dc
+/* IPC*/
+#define MMC_RX_IPC_INTR_MASK		0x00000200
+#define MMC_RX_IPC_INTR			0x00000208
+/* IPv4*/
+#define MMC_RX_IPV4_GD			0x00000210
+#define MMC_RX_IPV4_HDERR		0x00000214
+#define MMC_RX_IPV4_NOPAY		0x00000218
+#define MMC_RX_IPV4_FRAG		0x0000021C
+#define MMC_RX_IPV4_UDSBL		0x00000220
+
+#define MMC_RX_IPV4_GD_OCTETS		0x00000250
+#define MMC_RX_IPV4_HDERR_OCTETS	0x00000254
+#define MMC_RX_IPV4_NOPAY_OCTETS	0x00000258
+#define MMC_RX_IPV4_FRAG_OCTETS		0x0000025c
+#define MMC_RX_IPV4_UDSBL_OCTETS	0x00000260
+
+/* IPV6*/
+#define MMC_RX_IPV6_GD_OCTETS		0x00000264
+#define MMC_RX_IPV6_HDERR_OCTETS	0x00000268
+#define MMC_RX_IPV6_NOPAY_OCTETS	0x0000026c
+
+#define MMC_RX_IPV6_GD			0x00000224
+#define MMC_RX_IPV6_HDERR		0x00000228
+#define MMC_RX_IPV6_NOPAY		0x0000022c
+
+/* Protocols*/
+#define MMC_RX_UDP_GD			0x00000230
+#define MMC_RX_UDP_ERR			0x00000234
+#define MMC_RX_TCP_GD			0x00000238
+#define MMC_RX_TCP_ERR			0x0000023c
+#define MMC_RX_ICMP_GD			0x00000240
+#define MMC_RX_ICMP_ERR			0x00000244
+
+#define MMC_RX_UDP_GD_OCTETS		0x00000270
+#define MMC_RX_UDP_ERR_OCTETS		0x00000274
+#define MMC_RX_TCP_GD_OCTETS		0x00000278
+#define MMC_RX_TCP_ERR_OCTETS		0x0000027c
+#define MMC_RX_ICMP_GD_OCTETS		0x00000280
+#define MMC_RX_ICMP_ERR_OCTETS		0x00000284
+
+void dwmac_mmc_ctrl(void __iomem *ioaddr, unsigned int mode)
+{
+	u32 value = readl(ioaddr + MMC_CNTRL);
+
+	value |= (mode & 0x3F);
+
+	writel(value, ioaddr + MMC_CNTRL);
+
+	pr_debug("stmmac: MMC ctrl register (offset 0x%x): 0x%08x\n",
+		 MMC_CNTRL, value);
+}
+
+/* To mask all all interrupts.*/
+void dwmac_mmc_intr_all_mask(void __iomem *ioaddr)
+{
+	writel(MMC_DEFAUL_MASK, ioaddr + MMC_RX_INTR_MASK);
+	writel(MMC_DEFAUL_MASK, ioaddr + MMC_TX_INTR_MASK);
+}
+
+/* This reads the MAC core counters (if actaully supported).
+ * by default the MMC core is programmed to reset each
+ * counter after a read. So all the field of the mmc struct
+ * have to be incremented.
+ */
+void dwmac_mmc_read(void __iomem *ioaddr, struct stmmac_counters *mmc)
+{
+	mmc->mmc_tx_octetcount_gb += readl(ioaddr + MMC_TX_OCTETCOUNT_GB);
+	mmc->mmc_tx_framecount_gb += readl(ioaddr + MMC_TX_FRAMECOUNT_GB);
+	mmc->mmc_tx_broadcastframe_g += readl(ioaddr + MMC_TX_BROADCASTFRAME_G);
+	mmc->mmc_tx_multicastframe_g += readl(ioaddr + MMC_TX_MULTICASTFRAME_G);
+	mmc->mmc_tx_64_octets_gb += readl(ioaddr + MMC_TX_64_OCTETS_GB);
+	mmc->mmc_tx_65_to_127_octets_gb +=
+	    readl(ioaddr + MMC_TX_65_TO_127_OCTETS_GB);
+	mmc->mmc_tx_128_to_255_octets_gb +=
+	    readl(ioaddr + MMC_TX_128_TO_255_OCTETS_GB);
+	mmc->mmc_tx_256_to_511_octets_gb +=
+	    readl(ioaddr + MMC_TX_256_TO_511_OCTETS_GB);
+	mmc->mmc_tx_512_to_1023_octets_gb +=
+	    readl(ioaddr + MMC_TX_512_TO_1023_OCTETS_GB);
+	mmc->mmc_tx_1024_to_max_octets_gb +=
+	    readl(ioaddr + MMC_TX_1024_TO_MAX_OCTETS_GB);
+	mmc->mmc_tx_unicast_gb += readl(ioaddr + MMC_TX_UNICAST_GB);
+	mmc->mmc_tx_multicast_gb += readl(ioaddr + MMC_TX_MULTICAST_GB);
+	mmc->mmc_tx_broadcast_gb += readl(ioaddr + MMC_TX_BROADCAST_GB);
+	mmc->mmc_tx_underflow_error += readl(ioaddr + MMC_TX_UNDERFLOW_ERROR);
+	mmc->mmc_tx_singlecol_g += readl(ioaddr + MMC_TX_SINGLECOL_G);
+	mmc->mmc_tx_multicol_g += readl(ioaddr + MMC_TX_MULTICOL_G);
+	mmc->mmc_tx_deferred += readl(ioaddr + MMC_TX_DEFERRED);
+	mmc->mmc_tx_latecol += readl(ioaddr + MMC_TX_LATECOL);
+	mmc->mmc_tx_exesscol += readl(ioaddr + MMC_TX_EXESSCOL);
+	mmc->mmc_tx_carrier_error += readl(ioaddr + MMC_TX_CARRIER_ERROR);
+	mmc->mmc_tx_octetcount_g += readl(ioaddr + MMC_TX_OCTETCOUNT_G);
+	mmc->mmc_tx_framecount_g += readl(ioaddr + MMC_TX_FRAMECOUNT_G);
+	mmc->mmc_tx_excessdef += readl(ioaddr + MMC_TX_EXCESSDEF);
+	mmc->mmc_tx_pause_frame += readl(ioaddr + MMC_TX_PAUSE_FRAME);
+	mmc->mmc_tx_vlan_frame_g += readl(ioaddr + MMC_TX_VLAN_FRAME_G);
+
+	/* MMC RX counter registers */
+	mmc->mmc_rx_framecount_gb += readl(ioaddr + MMC_RX_FRAMECOUNT_GB);
+	mmc->mmc_rx_octetcount_gb += readl(ioaddr + MMC_RX_OCTETCOUNT_GB);
+	mmc->mmc_rx_octetcount_g += readl(ioaddr + MMC_RX_OCTETCOUNT_G);
+	mmc->mmc_rx_broadcastframe_g += readl(ioaddr + MMC_RX_BROADCASTFRAME_G);
+	mmc->mmc_rx_multicastframe_g += readl(ioaddr + MMC_RX_MULTICASTFRAME_G);
+	mmc->mmc_rx_crc_errror += readl(ioaddr + MMC_RX_CRC_ERRROR);
+	mmc->mmc_rx_align_error += readl(ioaddr + MMC_RX_ALIGN_ERROR);
+	mmc->mmc_rx_run_error += readl(ioaddr + MMC_RX_RUN_ERROR);
+	mmc->mmc_rx_jabber_error += readl(ioaddr + MMC_RX_JABBER_ERROR);
+	mmc->mmc_rx_undersize_g += readl(ioaddr + MMC_RX_UNDERSIZE_G);
+	mmc->mmc_rx_oversize_g += readl(ioaddr + MMC_RX_OVERSIZE_G);
+	mmc->mmc_rx_64_octets_gb += readl(ioaddr + MMC_RX_64_OCTETS_GB);
+	mmc->mmc_rx_65_to_127_octets_gb +=
+	    readl(ioaddr + MMC_RX_65_TO_127_OCTETS_GB);
+	mmc->mmc_rx_128_to_255_octets_gb +=
+	    readl(ioaddr + MMC_RX_128_TO_255_OCTETS_GB);
+	mmc->mmc_rx_256_to_511_octets_gb +=
+	    readl(ioaddr + MMC_RX_256_TO_511_OCTETS_GB);
+	mmc->mmc_rx_512_to_1023_octets_gb +=
+	    readl(ioaddr + MMC_RX_512_TO_1023_OCTETS_GB);
+	mmc->mmc_rx_1024_to_max_octets_gb +=
+	    readl(ioaddr + MMC_RX_1024_TO_MAX_OCTETS_GB);
+	mmc->mmc_rx_unicast_g += readl(ioaddr + MMC_RX_UNICAST_G);
+	mmc->mmc_rx_length_error += readl(ioaddr + MMC_RX_LENGTH_ERROR);
+	mmc->mmc_rx_autofrangetype += readl(ioaddr + MMC_RX_AUTOFRANGETYPE);
+	mmc->mmc_rx_pause_frames += readl(ioaddr + MMC_RX_PAUSE_FRAMES);
+	mmc->mmc_rx_fifo_overflow += readl(ioaddr + MMC_RX_FIFO_OVERFLOW);
+	mmc->mmc_rx_vlan_frames_gb += readl(ioaddr + MMC_RX_VLAN_FRAMES_GB);
+	mmc->mmc_rx_watchdog_error += readl(ioaddr + MMC_RX_WATCHDOG_ERROR);
+	/* IPC */
+	mmc->mmc_rx_ipc_intr_mask += readl(ioaddr + MMC_RX_IPC_INTR_MASK);
+	mmc->mmc_rx_ipc_intr += readl(ioaddr + MMC_RX_IPC_INTR);
+	/* IPv4 */
+	mmc->mmc_rx_ipv4_gd += readl(ioaddr + MMC_RX_IPV4_GD);
+	mmc->mmc_rx_ipv4_hderr += readl(ioaddr + MMC_RX_IPV4_HDERR);
+	mmc->mmc_rx_ipv4_nopay += readl(ioaddr + MMC_RX_IPV4_NOPAY);
+	mmc->mmc_rx_ipv4_frag += readl(ioaddr + MMC_RX_IPV4_FRAG);
+	mmc->mmc_rx_ipv4_udsbl += readl(ioaddr + MMC_RX_IPV4_UDSBL);
+
+	mmc->mmc_rx_ipv4_gd_octets += readl(ioaddr + MMC_RX_IPV4_GD_OCTETS);
+	mmc->mmc_rx_ipv4_hderr_octets +=
+	    readl(ioaddr + MMC_RX_IPV4_HDERR_OCTETS);
+	mmc->mmc_rx_ipv4_nopay_octets +=
+	    readl(ioaddr + MMC_RX_IPV4_NOPAY_OCTETS);
+	mmc->mmc_rx_ipv4_frag_octets += readl(ioaddr + MMC_RX_IPV4_FRAG_OCTETS);
+	mmc->mmc_rx_ipv4_udsbl_octets +=
+	    readl(ioaddr + MMC_RX_IPV4_UDSBL_OCTETS);
+
+	/* IPV6 */
+	mmc->mmc_rx_ipv6_gd_octets += readl(ioaddr + MMC_RX_IPV6_GD_OCTETS);
+	mmc->mmc_rx_ipv6_hderr_octets +=
+	    readl(ioaddr + MMC_RX_IPV6_HDERR_OCTETS);
+	mmc->mmc_rx_ipv6_nopay_octets +=
+	    readl(ioaddr + MMC_RX_IPV6_NOPAY_OCTETS);
+
+	mmc->mmc_rx_ipv6_gd += readl(ioaddr + MMC_RX_IPV6_GD);
+	mmc->mmc_rx_ipv6_hderr += readl(ioaddr + MMC_RX_IPV6_HDERR);
+	mmc->mmc_rx_ipv6_nopay += readl(ioaddr + MMC_RX_IPV6_NOPAY);
+
+	/* Protocols */
+	mmc->mmc_rx_udp_gd += readl(ioaddr + MMC_RX_UDP_GD);
+	mmc->mmc_rx_udp_err += readl(ioaddr + MMC_RX_UDP_ERR);
+	mmc->mmc_rx_tcp_gd += readl(ioaddr + MMC_RX_TCP_GD);
+	mmc->mmc_rx_tcp_err += readl(ioaddr + MMC_RX_TCP_ERR);
+	mmc->mmc_rx_icmp_gd += readl(ioaddr + MMC_RX_ICMP_GD);
+	mmc->mmc_rx_icmp_err += readl(ioaddr + MMC_RX_ICMP_ERR);
+
+	mmc->mmc_rx_udp_gd_octets += readl(ioaddr + MMC_RX_UDP_GD_OCTETS);
+	mmc->mmc_rx_udp_err_octets += readl(ioaddr + MMC_RX_UDP_ERR_OCTETS);
+	mmc->mmc_rx_tcp_gd_octets += readl(ioaddr + MMC_RX_TCP_GD_OCTETS);
+	mmc->mmc_rx_tcp_err_octets += readl(ioaddr + MMC_RX_TCP_ERR_OCTETS);
+	mmc->mmc_rx_icmp_gd_octets += readl(ioaddr + MMC_RX_ICMP_GD_OCTETS);
+	mmc->mmc_rx_icmp_err_octets += readl(ioaddr + MMC_RX_ICMP_ERR_OCTETS);
+}
diff --git a/drivers/net/stmmac/stmmac.h b/drivers/net/stmmac/stmmac.h
index 619e3af..ef03796 100644
--- a/drivers/net/stmmac/stmmac.h
+++ b/drivers/net/stmmac/stmmac.h
@@ -77,6 +77,7 @@ struct stmmac_priv {
 	struct stmmac_timer *tm;
 #endif
 	struct plat_stmmacenet_data *plat;
+	struct stmmac_counters mmc;
 };
 
 extern int stmmac_mdio_unregister(struct net_device *ndev);
diff --git a/drivers/net/stmmac/stmmac_ethtool.c b/drivers/net/stmmac/stmmac_ethtool.c
index 79df79d..7d23f99 100644
--- a/drivers/net/stmmac/stmmac_ethtool.c
+++ b/drivers/net/stmmac/stmmac_ethtool.c
@@ -46,7 +46,7 @@ struct stmmac_stats {
 	{ #m, FIELD_SIZEOF(struct stmmac_extra_stats, m),	\
 	offsetof(struct stmmac_priv, xstats.m)}
 
-static const struct  stmmac_stats stmmac_gstrings_stats[] = {
+static const struct stmmac_stats stmmac_gstrings_stats[] = {
 	STMMAC_STAT(tx_underflow),
 	STMMAC_STAT(tx_carrier),
 	STMMAC_STAT(tx_losscarrier),
@@ -91,19 +91,109 @@ static const struct  stmmac_stats stmmac_gstrings_stats[] = {
 };
 #define STMMAC_STATS_LEN ARRAY_SIZE(stmmac_gstrings_stats)
 
+/* HW MAC Management counters (if supported) */
+#define STMMAC_MMC_STAT(m)	\
+	{ #m, FIELD_SIZEOF(struct stmmac_counters, m),	\
+	offsetof(struct stmmac_priv, mmc.m)}
+
+static const struct stmmac_stats stmmac_gstr_mmc[] = {
+	STMMAC_MMC_STAT(mmc_tx_octetcount_gb),
+	STMMAC_MMC_STAT(mmc_tx_framecount_gb),
+	STMMAC_MMC_STAT(mmc_tx_broadcastframe_g),
+	STMMAC_MMC_STAT(mmc_tx_multicastframe_g),
+	STMMAC_MMC_STAT(mmc_tx_64_octets_gb),
+	STMMAC_MMC_STAT(mmc_tx_65_to_127_octets_gb),
+	STMMAC_MMC_STAT(mmc_tx_128_to_255_octets_gb),
+	STMMAC_MMC_STAT(mmc_tx_256_to_511_octets_gb),
+	STMMAC_MMC_STAT(mmc_tx_512_to_1023_octets_gb),
+	STMMAC_MMC_STAT(mmc_tx_1024_to_max_octets_gb),
+	STMMAC_MMC_STAT(mmc_tx_unicast_gb),
+	STMMAC_MMC_STAT(mmc_tx_multicast_gb),
+	STMMAC_MMC_STAT(mmc_tx_broadcast_gb),
+	STMMAC_MMC_STAT(mmc_tx_underflow_error),
+	STMMAC_MMC_STAT(mmc_tx_singlecol_g),
+	STMMAC_MMC_STAT(mmc_tx_multicol_g),
+	STMMAC_MMC_STAT(mmc_tx_deferred),
+	STMMAC_MMC_STAT(mmc_tx_latecol),
+	STMMAC_MMC_STAT(mmc_tx_exesscol),
+	STMMAC_MMC_STAT(mmc_tx_carrier_error),
+	STMMAC_MMC_STAT(mmc_tx_octetcount_g),
+	STMMAC_MMC_STAT(mmc_tx_framecount_g),
+	STMMAC_MMC_STAT(mmc_tx_excessdef),
+	STMMAC_MMC_STAT(mmc_tx_pause_frame),
+	STMMAC_MMC_STAT(mmc_tx_vlan_frame_g),
+	STMMAC_MMC_STAT(mmc_rx_framecount_gb),
+	STMMAC_MMC_STAT(mmc_rx_octetcount_gb),
+	STMMAC_MMC_STAT(mmc_rx_octetcount_g),
+	STMMAC_MMC_STAT(mmc_rx_broadcastframe_g),
+	STMMAC_MMC_STAT(mmc_rx_multicastframe_g),
+	STMMAC_MMC_STAT(mmc_rx_crc_errror),
+	STMMAC_MMC_STAT(mmc_rx_align_error),
+	STMMAC_MMC_STAT(mmc_rx_run_error),
+	STMMAC_MMC_STAT(mmc_rx_jabber_error),
+	STMMAC_MMC_STAT(mmc_rx_undersize_g),
+	STMMAC_MMC_STAT(mmc_rx_oversize_g),
+	STMMAC_MMC_STAT(mmc_rx_64_octets_gb),
+	STMMAC_MMC_STAT(mmc_rx_65_to_127_octets_gb),
+	STMMAC_MMC_STAT(mmc_rx_128_to_255_octets_gb),
+	STMMAC_MMC_STAT(mmc_rx_256_to_511_octets_gb),
+	STMMAC_MMC_STAT(mmc_rx_512_to_1023_octets_gb),
+	STMMAC_MMC_STAT(mmc_rx_1024_to_max_octets_gb),
+	STMMAC_MMC_STAT(mmc_rx_unicast_g),
+	STMMAC_MMC_STAT(mmc_rx_length_error),
+	STMMAC_MMC_STAT(mmc_rx_autofrangetype),
+	STMMAC_MMC_STAT(mmc_rx_pause_frames),
+	STMMAC_MMC_STAT(mmc_rx_fifo_overflow),
+	STMMAC_MMC_STAT(mmc_rx_vlan_frames_gb),
+	STMMAC_MMC_STAT(mmc_rx_watchdog_error),
+	STMMAC_MMC_STAT(mmc_rx_ipc_intr_mask),
+	STMMAC_MMC_STAT(mmc_rx_ipc_intr),
+	STMMAC_MMC_STAT(mmc_rx_ipv4_gd),
+	STMMAC_MMC_STAT(mmc_rx_ipv4_hderr),
+	STMMAC_MMC_STAT(mmc_rx_ipv4_nopay),
+	STMMAC_MMC_STAT(mmc_rx_ipv4_frag),
+	STMMAC_MMC_STAT(mmc_rx_ipv4_udsbl),
+	STMMAC_MMC_STAT(mmc_rx_ipv4_gd_octets),
+	STMMAC_MMC_STAT(mmc_rx_ipv4_hderr_octets),
+	STMMAC_MMC_STAT(mmc_rx_ipv4_nopay_octets),
+	STMMAC_MMC_STAT(mmc_rx_ipv4_frag_octets),
+	STMMAC_MMC_STAT(mmc_rx_ipv4_udsbl_octets),
+	STMMAC_MMC_STAT(mmc_rx_ipv6_gd_octets),
+	STMMAC_MMC_STAT(mmc_rx_ipv6_hderr_octets),
+	STMMAC_MMC_STAT(mmc_rx_ipv6_nopay_octets),
+	STMMAC_MMC_STAT(mmc_rx_ipv6_gd),
+	STMMAC_MMC_STAT(mmc_rx_ipv6_hderr),
+	STMMAC_MMC_STAT(mmc_rx_ipv6_nopay),
+	STMMAC_MMC_STAT(mmc_rx_udp_gd),
+	STMMAC_MMC_STAT(mmc_rx_udp_err),
+	STMMAC_MMC_STAT(mmc_rx_tcp_gd),
+	STMMAC_MMC_STAT(mmc_rx_tcp_err),
+	STMMAC_MMC_STAT(mmc_rx_icmp_gd),
+	STMMAC_MMC_STAT(mmc_rx_icmp_err),
+	STMMAC_MMC_STAT(mmc_rx_udp_gd_octets),
+	STMMAC_MMC_STAT(mmc_rx_udp_err_octets),
+	STMMAC_MMC_STAT(mmc_rx_tcp_gd_octets),
+	STMMAC_MMC_STAT(mmc_rx_tcp_err_octets),
+	STMMAC_MMC_STAT(mmc_rx_icmp_gd_octets),
+	STMMAC_MMC_STAT(mmc_rx_icmp_err_octets),
+};
+#define STMMAC_MMC_STATS_LEN ARRAY_SIZE(stmmac_gstr_mmc)
+
 static void stmmac_ethtool_getdrvinfo(struct net_device *dev,
 				      struct ethtool_drvinfo *info)
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
 
-	if (!priv->plat->has_gmac)
-		strcpy(info->driver, MAC100_ETHTOOL_NAME);
-	else
+	info->n_stats = STMMAC_STATS_LEN;
+
+	if (likely(priv->plat->has_gmac)) {
 		strcpy(info->driver, GMAC_ETHTOOL_NAME);
+		info->n_stats += STMMAC_MMC_STATS_LEN;
+	} else
+		strcpy(info->driver, MAC100_ETHTOOL_NAME);
 
 	strcpy(info->version, DRV_MODULE_VERSION);
 	info->fw_version[0] = '\0';
-	info->n_stats = STMMAC_STATS_LEN;
 }
 
 static int stmmac_ethtool_getsettings(struct net_device *dev,
@@ -252,24 +342,44 @@ static void stmmac_get_ethtool_stats(struct net_device *dev,
 				 struct ethtool_stats *dummy, u64 *data)
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
-	int i;
-
-	/* Update HW stats if supported */
-	priv->hw->dma->dma_diagnostic_fr(&dev->stats, (void *) &priv->xstats,
-					 priv->ioaddr);
-
+	int i, j = 0;
+
+	/* Update the DMA HW counters for dwmac10/100 */
+	if (unlikely(!priv->plat->has_gmac))
+		priv->hw->dma->dma_diagnostic_fr(&dev->stats,
+						 (void *) &priv->xstats,
+						 priv->ioaddr);
+	else {
+		/* If supported, for new GMAC chips expose the MMC counters */
+		dwmac_mmc_read(priv->ioaddr, &priv->mmc);
+
+		for (i = 0; i < STMMAC_MMC_STATS_LEN; i++) {
+			char *p = (char *)priv + stmmac_gstr_mmc[i].stat_offset;
+
+			data[j++] = (stmmac_gstr_mmc[i].sizeof_stat ==
+				     sizeof(u64)) ? (*(u64 *)p) : (*(u32 *)p);
+		}
+	}
 	for (i = 0; i < STMMAC_STATS_LEN; i++) {
 		char *p = (char *)priv + stmmac_gstrings_stats[i].stat_offset;
-		data[i] = (stmmac_gstrings_stats[i].sizeof_stat ==
-		sizeof(u64)) ? (*(u64 *)p) : (*(u32 *)p);
+		data[j++] = (stmmac_gstrings_stats[i].sizeof_stat ==
+			     sizeof(u64)) ? (*(u64 *)p) : (*(u32 *)p);
 	}
 }
 
 static int stmmac_get_sset_count(struct net_device *netdev, int sset)
 {
+	struct stmmac_priv *priv = netdev_priv(netdev);
+	int len;
+
 	switch (sset) {
 	case ETH_SS_STATS:
-		return STMMAC_STATS_LEN;
+		len = STMMAC_STATS_LEN;
+
+		if (likely(priv->plat->has_gmac))
+			len += STMMAC_MMC_STATS_LEN;
+
+		return len;
 	default:
 		return -EOPNOTSUPP;
 	}
@@ -279,9 +389,16 @@ static void stmmac_get_strings(struct net_device *dev, u32 stringset, u8 *data)
 {
 	int i;
 	u8 *p = data;
+	struct stmmac_priv *priv = netdev_priv(dev);
 
 	switch (stringset) {
 	case ETH_SS_STATS:
+		if (likely(priv->plat->has_gmac))
+			for (i = 0; i < STMMAC_MMC_STATS_LEN; i++) {
+				memcpy(p, stmmac_gstr_mmc[i].stat_string,
+				       ETH_GSTRING_LEN);
+				p += ETH_GSTRING_LEN;
+			}
 		for (i = 0; i < STMMAC_STATS_LEN; i++) {
 			memcpy(p, stmmac_gstrings_stats[i].stat_string,
 				ETH_GSTRING_LEN);
diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c
index 931cbf6..88b2973 100644
--- a/drivers/net/stmmac/stmmac_main.c
+++ b/drivers/net/stmmac/stmmac_main.c
@@ -747,6 +747,17 @@ static void stmmac_dma_interrupt(struct stmmac_priv *priv)
 		stmmac_tx_err(priv);
 }
 
+static void stmmac_mmc_setup(struct stmmac_priv *priv)
+{
+	unsigned int mode = MMC_CNTRL_RESET_ON_READ | MMC_CNTRL_COUNTER_RESET |
+			    MMC_CNTRL_PRESET | MMC_CNTRL_FULL_HALF_PRESET;
+
+	/* Do not manage MMC IRQ (FIXME) */
+	dwmac_mmc_intr_all_mask(priv->ioaddr);
+	dwmac_mmc_ctrl(priv->ioaddr, mode);
+	memset(&priv->mmc, 0, sizeof(struct stmmac_counters));
+}
+
 /**
  *  stmmac_open - open entry point of the driver
  *  @dev : pointer to the device structure.
@@ -845,6 +856,8 @@ static int stmmac_open(struct net_device *dev)
 	memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats));
 	priv->xstats.threshold = tc;
 
+	stmmac_mmc_setup(priv);
+
 	/* Start the ball rolling... */
 	DBG(probe, DEBUG, "%s: DMA RX/TX processes started...\n", dev->name);
 	priv->hw->dma->start_tx(priv->ioaddr);
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 3/9] stmmac: support wake up irq from external sources (v2)
From: Giuseppe CAVALLARO @ 2011-08-30 14:20 UTC (permalink / raw)
  To: netdev; +Cc: Deepak Sikri, Giuseppe Cavallaro
In-Reply-To: <1314714064-29101-1-git-send-email-peppe.cavallaro@st.com>

From: Deepak Sikri <deepak.sikri@st.com>

On some platforms e.g. SPEAr the wake up irq differs from the
GMAC interrupt source.
With this patch an external wake up irq can be passed through the
platform code and named as "eth_wake_irq".

In case the wake up interrupt is not passed from the platform
so the driver will continue to use the mac irq (ndev->irq)

Signed-off-by: Deepak Sikri <deepak.sikri@st.com>
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
 drivers/net/stmmac/stmmac.h         |    1 +
 drivers/net/stmmac/stmmac_ethtool.c |    4 ++--
 drivers/net/stmmac/stmmac_main.c    |   14 +++++++++++++-
 3 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/net/stmmac/stmmac.h b/drivers/net/stmmac/stmmac.h
index de1929b..619e3af 100644
--- a/drivers/net/stmmac/stmmac.h
+++ b/drivers/net/stmmac/stmmac.h
@@ -72,6 +72,7 @@ struct stmmac_priv {
 	spinlock_t lock;
 	int wolopts;
 	int wolenabled;
+	int wol_irq;
 #ifdef CONFIG_STMMAC_TIMER
 	struct stmmac_timer *tm;
 #endif
diff --git a/drivers/net/stmmac/stmmac_ethtool.c b/drivers/net/stmmac/stmmac_ethtool.c
index 7ed8fb6..79df79d 100644
--- a/drivers/net/stmmac/stmmac_ethtool.c
+++ b/drivers/net/stmmac/stmmac_ethtool.c
@@ -321,10 +321,10 @@ static int stmmac_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 	if (wol->wolopts) {
 		pr_info("stmmac: wakeup enable\n");
 		device_set_wakeup_enable(priv->device, 1);
-		enable_irq_wake(dev->irq);
+		enable_irq_wake(priv->wol_irq);
 	} else {
 		device_set_wakeup_enable(priv->device, 0);
-		disable_irq_wake(dev->irq);
+		disable_irq_wake(priv->wol_irq);
 	}
 
 	spin_lock_irq(&priv->lock);
diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c
index da11405..931cbf6 100644
--- a/drivers/net/stmmac/stmmac_main.c
+++ b/drivers/net/stmmac/stmmac_main.c
@@ -1512,7 +1512,7 @@ static int stmmac_mac_device_setup(struct net_device *dev)
 
 	if (device_can_wakeup(priv->device)) {
 		priv->wolopts = WAKE_MAGIC; /* Magic Frame as default */
-		enable_irq_wake(dev->irq);
+		enable_irq_wake(priv->wol_irq);
 	}
 
 	return 0;
@@ -1585,6 +1585,18 @@ static int stmmac_dvr_probe(struct platform_device *pdev)
 		pr_info("\tPMT module supported\n");
 		device_set_wakeup_capable(&pdev->dev, 1);
 	}
+	/*
+	 * On some platforms e.g. SPEAr the wake up irq differs from the mac irq
+	 * The external wake up irq can be passed through the platform code
+	 * named as "eth_wake_irq"
+	 *
+	 * In case the wake up interrupt is not passed from the platform
+	 * so the driver will continue to use the mac irq (ndev->irq)
+	 */
+	priv->wol_irq = platform_get_irq_byname(pdev, "eth_wake_irq");
+	if (priv->wol_irq == -ENXIO)
+		priv->wol_irq = ndev->irq;
+
 
 	platform_set_drvdata(pdev, ndev);
 
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 2/9] stmmac: remove the mmc code (v2)
From: Giuseppe CAVALLARO @ 2011-08-30 14:20 UTC (permalink / raw)
  To: netdev; +Cc: Giuseppe Cavallaro
In-Reply-To: <1314714064-29101-1-git-send-email-peppe.cavallaro@st.com>

DWMAC Management Counters (MMC) are not fully support.
The minimal support added in the past allowed to
only disable counters (if present) and mask their
interrupts.
This patch prepares the driver to support the MMC
removing obsolete code.

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
 drivers/net/stmmac/common.h         |   11 -----------
 drivers/net/stmmac/dwmac1000_core.c |    2 --
 drivers/net/stmmac/dwmac100_core.c  |   11 -----------
 drivers/net/stmmac/stmmac_main.c    |    4 ----
 4 files changed, 0 insertions(+), 28 deletions(-)

diff --git a/drivers/net/stmmac/common.h b/drivers/net/stmmac/common.h
index 375ea19..290b97a 100644
--- a/drivers/net/stmmac/common.h
+++ b/drivers/net/stmmac/common.h
@@ -130,17 +130,6 @@ enum tx_dma_irq_status {
 #define MAC_ENABLE_TX		0x00000008	/* Transmitter Enable */
 #define MAC_RNABLE_RX		0x00000004	/* Receiver Enable */
 
-/* MAC Management Counters register */
-#define MMC_CONTROL		0x00000100	/* MMC Control */
-#define MMC_HIGH_INTR		0x00000104	/* MMC High Interrupt */
-#define MMC_LOW_INTR		0x00000108	/* MMC Low Interrupt */
-#define MMC_HIGH_INTR_MASK	0x0000010c	/* MMC High Interrupt Mask */
-#define MMC_LOW_INTR_MASK	0x00000110	/* MMC Low Interrupt Mask */
-
-#define MMC_CONTROL_MAX_FRM_MASK	0x0003ff8	/* Maximum Frame Size */
-#define MMC_CONTROL_MAX_FRM_SHIFT	3
-#define MMC_CONTROL_MAX_FRAME		0x7FF
-
 struct stmmac_desc_ops {
 	/* DMA RX descriptor ring initialization */
 	void (*init_rx_desc) (struct dma_desc *p, unsigned int ring_size,
diff --git a/drivers/net/stmmac/dwmac1000_core.c b/drivers/net/stmmac/dwmac1000_core.c
index eea184a..9ba9cae 100644
--- a/drivers/net/stmmac/dwmac1000_core.c
+++ b/drivers/net/stmmac/dwmac1000_core.c
@@ -37,8 +37,6 @@ static void dwmac1000_core_init(void __iomem *ioaddr)
 	value |= GMAC_CORE_INIT;
 	writel(value, ioaddr + GMAC_CONTROL);
 
-	/* Freeze MMC counters */
-	writel(0x8, ioaddr + GMAC_MMC_CTRL);
 	/* Mask GMAC interrupts */
 	writel(0x207, ioaddr + GMAC_INT_MASK);
 
diff --git a/drivers/net/stmmac/dwmac100_core.c b/drivers/net/stmmac/dwmac100_core.c
index 743a580..aacfc6e 100644
--- a/drivers/net/stmmac/dwmac100_core.c
+++ b/drivers/net/stmmac/dwmac100_core.c
@@ -70,17 +70,6 @@ static void dwmac100_dump_mac_regs(void __iomem *ioaddr)
 		readl(ioaddr + MAC_VLAN1));
 	pr_info("\tVLAN2 tag (offset 0x%x): 0x%08x\n", MAC_VLAN2,
 		readl(ioaddr + MAC_VLAN2));
-	pr_info("\n\tMAC management counter registers\n");
-	pr_info("\t MMC crtl (offset 0x%x): 0x%08x\n",
-		MMC_CONTROL, readl(ioaddr + MMC_CONTROL));
-	pr_info("\t MMC High Interrupt (offset 0x%x): 0x%08x\n",
-		MMC_HIGH_INTR, readl(ioaddr + MMC_HIGH_INTR));
-	pr_info("\t MMC Low Interrupt (offset 0x%x): 0x%08x\n",
-		MMC_LOW_INTR, readl(ioaddr + MMC_LOW_INTR));
-	pr_info("\t MMC High Interrupt Mask (offset 0x%x): 0x%08x\n",
-		MMC_HIGH_INTR_MASK, readl(ioaddr + MMC_HIGH_INTR_MASK));
-	pr_info("\t MMC Low Interrupt Mask (offset 0x%x): 0x%08x\n",
-		MMC_LOW_INTR_MASK, readl(ioaddr + MMC_LOW_INTR_MASK));
 }
 
 static void dwmac100_irq_status(void __iomem *ioaddr)
diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c
index c6e567e..da11405 100644
--- a/drivers/net/stmmac/stmmac_main.c
+++ b/drivers/net/stmmac/stmmac_main.c
@@ -826,10 +826,6 @@ static int stmmac_open(struct net_device *dev)
 		pr_info("\tTX Checksum insertion supported\n");
 	netdev_update_features(dev);
 
-	/* Initialise the MMC (if present) to disable all interrupts. */
-	writel(0xffffffff, priv->ioaddr + MMC_HIGH_INTR_MASK);
-	writel(0xffffffff, priv->ioaddr + MMC_LOW_INTR_MASK);
-
 	/* Request the IRQ lines */
 	ret = request_irq(dev->irq, stmmac_interrupt,
 			 IRQF_SHARED, dev->name, dev);
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 1/9] stmmac: remove the STBus bridge setting from the GMAC code (v2)
From: Giuseppe CAVALLARO @ 2011-08-30 14:20 UTC (permalink / raw)
  To: netdev; +Cc: Giuseppe Cavallaro
In-Reply-To: <1314714064-29101-1-git-send-email-peppe.cavallaro@st.com>

This patch removes a piece of code (actually commented)
only useful for some ST platforms in the past.

This kind of setting now can be done by using the platform
callbacks provided in linux/stmmac.h (see the stmmac.txt for
further details).

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
 drivers/net/stmmac/dwmac1000_core.c |    3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/drivers/net/stmmac/dwmac1000_core.c b/drivers/net/stmmac/dwmac1000_core.c
index 0f63b3c..eea184a 100644
--- a/drivers/net/stmmac/dwmac1000_core.c
+++ b/drivers/net/stmmac/dwmac1000_core.c
@@ -37,9 +37,6 @@ static void dwmac1000_core_init(void __iomem *ioaddr)
 	value |= GMAC_CORE_INIT;
 	writel(value, ioaddr + GMAC_CONTROL);
 
-	/* STBus Bridge Configuration */
-	/*writel(0xc5608, ioaddr + 0x00007000);*/
-
 	/* Freeze MMC counters */
 	writel(0x8, ioaddr + GMAC_MMC_CTRL);
 	/* Mask GMAC interrupts */
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 0/9] update the stmmac to the version Aug_2011 (v2)
From: Giuseppe CAVALLARO @ 2011-08-30 14:20 UTC (permalink / raw)
  To: netdev; +Cc: Giuseppe Cavallaro

These patches update the driver adding new supports:
MMC (HW management counters), HW feature register and
debugfs support.

MMC counters are exposed via ethtool.

These also update the documentation adding a new section
for the debugging.

Deepak Sikri (1):
  stmmac: support wake up irq from external sources

Giuseppe Cavallaro (8):
  stmmac: remove the STBus bridge setting from the GMAC code
  stmmac: remove the mmc code
  stmmac: add MMC support exported via ethtool
  stmmac: export DMA TX/RX rings via debugfs.
  stmmac: rework the code to get the Synopsys ID
  stmmac: add HW DMA feature register
  stmmac: update the doc with new info about the driver's debug.
  stmmac: update the driver version (Aug_2011)

 Documentation/networking/stmmac.txt |   33 ++++-
 drivers/net/stmmac/Kconfig          |    8 +
 drivers/net/stmmac/Makefile         |    3 +-
 drivers/net/stmmac/common.h         |   46 +++++--
 drivers/net/stmmac/dwmac1000_core.c |   11 +-
 drivers/net/stmmac/dwmac1000_dma.c  |   14 +-
 drivers/net/stmmac/dwmac100_core.c  |   12 +--
 drivers/net/stmmac/dwmac_dma.h      |    1 +
 drivers/net/stmmac/mmc.h            |  131 ++++++++++++++++
 drivers/net/stmmac/mmc_core.c       |  265 ++++++++++++++++++++++++++++++++
 drivers/net/stmmac/stmmac.h         |    5 +-
 drivers/net/stmmac/stmmac_ethtool.c |  149 ++++++++++++++++--
 drivers/net/stmmac/stmmac_main.c    |  287 ++++++++++++++++++++++++++++++++++-
 13 files changed, 901 insertions(+), 64 deletions(-)
 create mode 100644 drivers/net/stmmac/mmc.h
 create mode 100644 drivers/net/stmmac/mmc_core.c

-- 
1.7.4.4

^ permalink raw reply

* Re: BQL crap and wireless
From: Jim Gettys @ 2011-08-30 13:58 UTC (permalink / raw)
  To: Adrian Chadd
  Cc: Tom Herbert, Luis R. Rodriguez, Dave Taht, linux-wireless,
	Andrew McGregor, Matt Smith, Kevin Hayes, Derek Smithies,
	netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <CAJ-Vmonwur-SXddNwjPEidCMqes+PwbRWFBddfdwTp2jOMu64g-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

On 08/29/2011 11:42 PM, Adrian Chadd wrote:
> On 30 August 2011 11:34, Tom Herbert <therbert-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org> wrote:
>
>> The generalization of BQL would be to set the queue limit in terms of
>> a cost function implemented by the driver.  The cost function would
>> most likely be an estimate of time to transmit a packet.  So C(P)
>> could represent cost of a packet, sum(C(P) for P queued) is aggregate
>> cost of queue packets, and queue limit is the maximum cost sum.  For
>> wired Ethernet, number of bytes in packet might be a reasonable
>> function (although framing cost could be included, but I'm not sure
>> that would make a material difference).  For wireless, maybe the
>> function could be more complex possibly taking multicast, previous
>> history of transmission times, or other arbitrary characteristics of
>> the packet into account...
>>
>> I can post a new patch with this generalization if this is interesting.
> As I said before, I think this is the kind of thing the rate control
> code needs to get its dirty hands into.
>
> With 802.11 you have to care about the PHY side of things too, so your
> cost suddenly would include the PER for combinations of {remote node,
> antenna setup, TX rate, sub-frame length, aggregate length}, etc. Do
> you choose that up front and then match a cost to it, or do you
> involve the rate control code in deciding a "good enough" way of
> handling what's on the queue by making rate decisions, then implement
> random/weighted/etc drop of what's left? Do you do some weighted/etc
> drop beforehand in the face of congestion, then pass what's left to
> the rate control code, then discard the rest?
>
> C(P) is going to be quite variable - a full frame retransmit of a 4ms
> long aggregate frame is SUM(exponential backoff, grab the air,
> preamble, header, 4ms, etc. for each pass.)
>
It's not clear to me that doing heroic measures to compute the cost is
going to be worthwhile due to the rate at which the costs can change on
wireless; just getting into the rough ballpark may be enough. But
buffering algorithms and AQM algorithms are going to need an estimate of
the *time* it will take to transmit data, more than # of bytes or packets.

Ultimately, if the queue starts builds, we'll need an AQM algorithm to
control the buffer growth.

Hopefully we can start testing SFB and other possibilities in CeroWrt
soon; Kathleen Nichols and Van Jacobson have been making some progress
on an algorithm called "RED light" which is based on the observed
transfer rate as well.  The eBDP algorithm in debloat testing also
helps, which Van pointed us at late last year when this came up (though
John Linville says eBDP needs rework before it can go upstream). We
didn't want to start testing SFB and other options while we were aware
of other problems in the wireless driver itself; Andrew and Felix's work
with Dave have apparently brought that problem to a decent point. 
                - Jim

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* PROTECTED PROJECT!!
From: KimJr @ 2011-08-30  6:25 UTC (permalink / raw)


I want to discuss an important issue with you .
I write to know if this is your valid email.
Please, let me know if your email is still valid.
My valid Email:  ikimyu@9.cn

KimJr

^ permalink raw reply

* [patch 3/3 -next] 6LoWPAN: call dev_put() on error in lowpan_newlink()
From: Dan Carpenter @ 2011-08-30 13:51 UTC (permalink / raw)
  To: Alexander Smirnov
  Cc: Dmitry Eremin-Solenikov, Sergey Lapin, David S. Miller,
	open list:IEEE 802.15.4 SUB..., open list:NETWORKING [GENERAL],
	kernel-janitors

We should release the dev_hold() on error before returning here.

Signed-off-by: Dan Carpenter <error27@gmail.com>
---
All three of these patches were compile tested only, but this is the
one I'm not very certain of.  I've obviously tried to get it right,
but please review it carefully.

diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index 5dc0489..f0d1536 100644
--- a/net/ieee802154/6lowpan.c
+++ b/net/ieee802154/6lowpan.c
@@ -793,8 +793,11 @@ static int lowpan_newlink(struct net *src_net, struct net_device *dev,
 	mutex_init(&lowpan_dev_info(dev)->dev_list_mtx);
 
 	entry = kzalloc(sizeof(struct lowpan_dev_record), GFP_KERNEL);
-	if (!entry)
+	if (!entry) {
+		dev_put(real_dev);
+		lowpan_dev_info(dev)->real_dev = NULL;
 		return -ENOMEM;
+	}
 
 	entry->ldev = dev;
 

^ permalink raw reply related

* [patch 2/3 -next] 6LoWPAN: use the _safe version of list_for_each
From: Dan Carpenter @ 2011-08-30 13:46 UTC (permalink / raw)
  To: Alexander Smirnov
  Cc: Dmitry Eremin-Solenikov, Sergey Lapin, David S. Miller,
	open list:IEEE 802.15.4 SUB..., open list:NETWORKING [GENERAL],
	kernel-janitors

When we kfree(entry) that causes a use-after-free bug so we have to
use list_for_each_entry_safe() safe here.

Signed-off-by: Dan Carpenter <error27@gmail.com>
---
Curly parens are not needed here, but kernel style is to use them for
multi-line indent blocks.

diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index cf304cc..5dc0489 100644
--- a/net/ieee802154/6lowpan.c
+++ b/net/ieee802154/6lowpan.c
@@ -813,15 +813,17 @@ static void lowpan_dellink(struct net_device *dev, struct list_head *head)
 	struct lowpan_dev_info *lowpan_dev = lowpan_dev_info(dev);
 	struct net_device *real_dev = lowpan_dev->real_dev;
 	struct lowpan_dev_record *entry;
+	struct lowpan_dev_record *tmp;
 
 	ASSERT_RTNL();
 
 	mutex_lock(&lowpan_dev_info(dev)->dev_list_mtx);
-	list_for_each_entry(entry, &lowpan_devices, list)
+	list_for_each_entry_safe(entry, tmp, &lowpan_devices, list) {
 		if (entry->ldev == dev) {
 			list_del(&entry->list);
 			kfree(entry);
 		}
+	}
 	mutex_unlock(&lowpan_dev_info(dev)->dev_list_mtx);
 
 	mutex_destroy(&lowpan_dev_info(dev)->dev_list_mtx);

^ permalink raw reply related

* [patch 1/3 -next] 6LoWPAN: use kfree_skb() instead of kfree()
From: Dan Carpenter @ 2011-08-30 13:45 UTC (permalink / raw)
  To: Alexander Smirnov
  Cc: Dmitry Eremin-Solenikov, Sergey Lapin, David S. Miller,
	open list:IEEE 802.15.4 SUB..., open list:NETWORKING [GENERAL],
	kernel-janitors

Use kfree_skb() to free sbk_buffs.

Signed-off-by: Dan Carpenter <error27@gmail.com>

diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index cf304cc..8a9dbaa 100644
--- a/net/ieee802154/6lowpan.c
+++ b/net/ieee802154/6lowpan.c
@@ -674,7 +674,7 @@ lowpan_process_data(struct sk_buff *skb)
 							sizeof(hdr));
 	return lowpan_skb_deliver(skb, &hdr);
 drop:
-	kfree(skb);
+	kfree_skb(skb);
 	return -EINVAL;
 }
 

^ permalink raw reply related

* Re: 802.1Q VLAN random tag injected when vlan configured on forcedeth interface
From: Ruslan N. Marchenko @ 2011-08-30 13:46 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: netdev
In-Reply-To: <1314710628.2935.22.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC>

On Tue, Aug 30, 2011 at 03:23:48PM +0200, Eric Dumazet wrote:
> 
> What kernel version are you using ?
> 
Oh, sorry for missing it, it runs on 
Linux ruff.mobi 2.6.38-11-generic #48-Ubuntu SMP Fri Jul 29 19:05:14 UTC 2011 i686 i686 i386 GNU/Linux

Just fyi - the openwrt box to which it is connected is 
Linux OpenWrt 2.6.39.2 #2 Fri Aug 12 09:36:23 EEST 2011 mips GNU/Linux
although packet drop happens even if there're no vlans configured on remote side.

Regards,
Ruslan

^ permalink raw reply

* Re: 802.1Q VLAN random tag injected when vlan configured on forcedeth interface
From: Eric Dumazet @ 2011-08-30 13:23 UTC (permalink / raw)
  To: Ruslan N. Marchenko; +Cc: netdev
In-Reply-To: <20110830125111.GA28341@ruff.mobi>

Le mardi 30 août 2011 à 14:51 +0200, Ruslan N. Marchenko a écrit :
> Hi guys,
> I've faced with strange behaviour of 8021q driver: when enabling vlan subinterface on eth interface I'm getting ~50% packetloss due to packets are marked with incorrect tags (and eventually dropped by kernel since no vlans configured for such IDs).
> Scenario:
> [    0.476950] cpufreq-nforce2: No nForce2 chipset.
> [    1.519133] forcedeth: Reverse Engineered nForce ethernet driver. Version 0.64.
> [    1.519991] forcedeth 0000:00:0a.0: PCI INT A -> Link[LMAC] -> GSI 22 (level, low) -> IRQ 22
> [    1.520037] forcedeth 0000:00:0a.0: setting latency timer to 64
> [    1.586526] forcedeth 0000:00:0a.0: ifname eth0, PHY OUI 0x732 @ 3, addr 00:26:18:40:21:61
> [    1.586542] forcedeth 0000:00:0a.0: highdma csum pwrctl gbit lnktim msi desc-v3
> 
> modprobe 8021q
> 
> - network still works properly, packets are comming not marked at all.
> 
> ip li add link eth0 name vl6 type vlan id 6
> 
> - from this moment massive packetdrop starting to happen, almost half of the *incoming* packets are shown in tcpdump as 
> 14:15:52.859296 00:13:f7:1e:fe:e4 > 00:26:18:40:21:61, ethertype 802.1Q (0x8100), length 102: vlan 64, p 3, ethertype IPv4, [|ip]
> 14:15:56.869572 00:13:f7:1e:fe:e4 > 00:26:18:40:21:61, ethertype 802.1Q (0x8100), length 102: vlan 2112, p 7, ethertype IPv4, [|ip]
> 
> mostly only these two tags appears (64 & 2112). Moreover this happens as on native vlan level (pure ethernet) so on tagged subinterface (as if qinq double tagging) for properly tagged with ID 6 incomming packets.
> 
> I've tried disabling all offloads:
> 
> Offload parameters for eth0:
> rx-checksumming: off
> tx-checksumming: off
> scatter-gather: off
> tcp-segmentation-offload: off
> udp-fragmentation-offload: off
> generic-segmentation-offload: off
> generic-receive-offload: off
> large-receive-offload: off
> rx-vlan-offload: off
> tx-vlan-offload: off
> ntuple-filters: off
> receive-hashing: off
> 
> - doesn't have any effect.
> Once executing 
> ip li del vl6 type vlan
> misterious tags disappear and everything works smoothly. Don't know who injects that garbage into frames - 8021q or forcedeth driver :(
> Any ideas or suggestions to narrow the problem down?
> 
> Additional data.
> Link level data dump example for broken frame:
> 12:35:32.175523 00:13:f7:1e:fe:e4 > 00:26:18:40:21:61, ethertype 802.1Q (0x8100), length 102: vlan 2112, p 2, ethertype IPv4, [|ip]
>         0x0000:  0026 1840 2161 0013 f71e fee4 8100 4840
>         0x0010:  0800 4500 0054 7a12 0000 4001 eb0f
> 0x0C-0D - TPID: ethertype 802.1Q (0x8100) 
> 0x0E-0F - TCI (0100100001000000) PCP 010, CFI 0, VID 100001000000/0x840/2112
> 0x10-11 - ethertype IPv4
> normal ping reply follows, which appears untagged in 50% cases with vlan configured and 100% cases without.
> 
> Interface is plugged into openwrt box into non-switched (wan) gigabit port with vid 6 subinterface configured.
> 

What kernel version are you using ?

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox