aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGiuseppe CAVALLARO <peppe.cavallaro@st.com>2011-10-26 15:43:09 -0400
committerDavid S. Miller <davem@davemloft.net>2011-10-27 23:17:12 -0400
commit3c20f72f9108b2fcf30ec63d8a4203736c01ccd0 (patch)
tree8310be8eba2e616fc3b93e5c7e379343c0480710
parente2c57f839c63f452b4704e048c8db9cf669ed410 (diff)
stmmac: update normal descriptor structure (v2)
This patch updates the normal descriptor structure to work fine on new GMAC Synopsys chips. Normal descriptors were designed on the old MAC10/100 databook 1.91 where some bits were reserved: for example the tx checksum insertion and rx checksum offload. The patch maintains the back-compatibility with old MAC devices (tested on STx7109 MAC10/100) and adds new fields that actually new GMAC devices can use. For example, STx7109 (MAC10/100) will pass from the platform tx_coe = 0, enh_desc = 0, has_gmac = 0. A platform like Loongson1B (GMAC) will pass: tx_coe = 1, enh_desc = 0, has_gmac = 1. Thanks to Kelvin, he enhanced the normal descriptors for GMAC (on MIPS Loongson1B platform). Signed-off-by: Kelvin Cheung <keguang.zhang@gmail.com> Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/common.h8
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/descs.h31
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/norm_desc.c38
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c8
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c6
5 files changed, 51 insertions, 40 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 9100c100d29..2cc11929582 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -49,7 +49,7 @@ struct stmmac_extra_stats {
49 unsigned long tx_underflow ____cacheline_aligned; 49 unsigned long tx_underflow ____cacheline_aligned;
50 unsigned long tx_carrier; 50 unsigned long tx_carrier;
51 unsigned long tx_losscarrier; 51 unsigned long tx_losscarrier;
52 unsigned long tx_heartbeat; 52 unsigned long vlan_tag;
53 unsigned long tx_deferred; 53 unsigned long tx_deferred;
54 unsigned long tx_vlan; 54 unsigned long tx_vlan;
55 unsigned long tx_jabber; 55 unsigned long tx_jabber;
@@ -58,9 +58,9 @@ struct stmmac_extra_stats {
58 unsigned long tx_ip_header_error; 58 unsigned long tx_ip_header_error;
59 /* Receive errors */ 59 /* Receive errors */
60 unsigned long rx_desc; 60 unsigned long rx_desc;
61 unsigned long rx_partial; 61 unsigned long sa_filter_fail;
62 unsigned long rx_runt; 62 unsigned long overflow_error;
63 unsigned long rx_toolong; 63 unsigned long ipc_csum_error;
64 unsigned long rx_collision; 64 unsigned long rx_collision;
65 unsigned long rx_crc; 65 unsigned long rx_crc;
66 unsigned long rx_length; 66 unsigned long rx_length;
diff --git a/drivers/net/ethernet/stmicro/stmmac/descs.h b/drivers/net/ethernet/stmicro/stmmac/descs.h
index 63a03e26469..9820ec842cc 100644
--- a/drivers/net/ethernet/stmicro/stmmac/descs.h
+++ b/drivers/net/ethernet/stmicro/stmmac/descs.h
@@ -25,33 +25,34 @@ struct dma_desc {
25 union { 25 union {
26 struct { 26 struct {
27 /* RDES0 */ 27 /* RDES0 */
28 u32 reserved1:1; 28 u32 payload_csum_error:1;
29 u32 crc_error:1; 29 u32 crc_error:1;
30 u32 dribbling:1; 30 u32 dribbling:1;
31 u32 mii_error:1; 31 u32 mii_error:1;
32 u32 receive_watchdog:1; 32 u32 receive_watchdog:1;
33 u32 frame_type:1; 33 u32 frame_type:1;
34 u32 collision:1; 34 u32 collision:1;
35 u32 frame_too_long:1; 35 u32 ipc_csum_error:1;
36 u32 last_descriptor:1; 36 u32 last_descriptor:1;
37 u32 first_descriptor:1; 37 u32 first_descriptor:1;
38 u32 multicast_frame:1; 38 u32 vlan_tag:1;
39 u32 run_frame:1; 39 u32 overflow_error:1;
40 u32 length_error:1; 40 u32 length_error:1;
41 u32 partial_frame_error:1; 41 u32 sa_filter_fail:1;
42 u32 descriptor_error:1; 42 u32 descriptor_error:1;
43 u32 error_summary:1; 43 u32 error_summary:1;
44 u32 frame_length:14; 44 u32 frame_length:14;
45 u32 filtering_fail:1; 45 u32 da_filter_fail:1;
46 u32 own:1; 46 u32 own:1;
47 /* RDES1 */ 47 /* RDES1 */
48 u32 buffer1_size:11; 48 u32 buffer1_size:11;
49 u32 buffer2_size:11; 49 u32 buffer2_size:11;
50 u32 reserved2:2; 50 u32 reserved1:2;
51 u32 second_address_chained:1; 51 u32 second_address_chained:1;
52 u32 end_ring:1; 52 u32 end_ring:1;
53 u32 reserved3:5; 53 u32 reserved2:5;
54 u32 disable_ic:1; 54 u32 disable_ic:1;
55
55 } rx; 56 } rx;
56 struct { 57 struct {
57 /* RDES0 */ 58 /* RDES0 */
@@ -91,24 +92,28 @@ struct dma_desc {
91 u32 underflow_error:1; 92 u32 underflow_error:1;
92 u32 excessive_deferral:1; 93 u32 excessive_deferral:1;
93 u32 collision_count:4; 94 u32 collision_count:4;
94 u32 heartbeat_fail:1; 95 u32 vlan_frame:1;
95 u32 excessive_collisions:1; 96 u32 excessive_collisions:1;
96 u32 late_collision:1; 97 u32 late_collision:1;
97 u32 no_carrier:1; 98 u32 no_carrier:1;
98 u32 loss_carrier:1; 99 u32 loss_carrier:1;
99 u32 reserved1:3; 100 u32 payload_error:1;
101 u32 frame_flushed:1;
102 u32 jabber_timeout:1;
100 u32 error_summary:1; 103 u32 error_summary:1;
101 u32 reserved2:15; 104 u32 ip_header_error:1;
105 u32 time_stamp_status:1;
106 u32 reserved1:13;
102 u32 own:1; 107 u32 own:1;
103 /* TDES1 */ 108 /* TDES1 */
104 u32 buffer1_size:11; 109 u32 buffer1_size:11;
105 u32 buffer2_size:11; 110 u32 buffer2_size:11;
106 u32 reserved3:1; 111 u32 time_stamp_enable:1;
107 u32 disable_padding:1; 112 u32 disable_padding:1;
108 u32 second_address_chained:1; 113 u32 second_address_chained:1;
109 u32 end_ring:1; 114 u32 end_ring:1;
110 u32 crc_disable:1; 115 u32 crc_disable:1;
111 u32 reserved4:2; 116 u32 checksum_insertion:2;
112 u32 first_segment:1; 117 u32 first_segment:1;
113 u32 last_segment:1; 118 u32 last_segment:1;
114 u32 interrupt:1; 119 u32 interrupt:1;
diff --git a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
index f7e8ba7f501..fda5d2b31d3 100644
--- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
@@ -50,11 +50,12 @@ static int ndesc_get_tx_status(void *data, struct stmmac_extra_stats *x,
50 stats->collisions += p->des01.tx.collision_count; 50 stats->collisions += p->des01.tx.collision_count;
51 ret = -1; 51 ret = -1;
52 } 52 }
53 if (unlikely(p->des01.tx.heartbeat_fail)) { 53
54 x->tx_heartbeat++; 54 if (p->des01.etx.vlan_frame) {
55 stats->tx_heartbeat_errors++; 55 CHIP_DBG(KERN_INFO "GMAC TX status: VLAN frame\n");
56 ret = -1; 56 x->tx_vlan++;
57 } 57 }
58
58 if (unlikely(p->des01.tx.deferred)) 59 if (unlikely(p->des01.tx.deferred))
59 x->tx_deferred++; 60 x->tx_deferred++;
60 61
@@ -68,12 +69,12 @@ static int ndesc_get_tx_len(struct dma_desc *p)
68 69
69/* This function verifies if each incoming frame has some errors 70/* This function verifies if each incoming frame has some errors
70 * and, if required, updates the multicast statistics. 71 * and, if required, updates the multicast statistics.
71 * In case of success, it returns csum_none because the device 72 * In case of success, it returns good_frame because the GMAC device
72 * is not able to compute the csum in HW. */ 73 * is supposed to be able to compute the csum in HW. */
73static int ndesc_get_rx_status(void *data, struct stmmac_extra_stats *x, 74static int ndesc_get_rx_status(void *data, struct stmmac_extra_stats *x,
74 struct dma_desc *p) 75 struct dma_desc *p)
75{ 76{
76 int ret = csum_none; 77 int ret = good_frame;
77 struct net_device_stats *stats = (struct net_device_stats *)data; 78 struct net_device_stats *stats = (struct net_device_stats *)data;
78 79
79 if (unlikely(p->des01.rx.last_descriptor == 0)) { 80 if (unlikely(p->des01.rx.last_descriptor == 0)) {
@@ -86,12 +87,12 @@ static int ndesc_get_rx_status(void *data, struct stmmac_extra_stats *x,
86 if (unlikely(p->des01.rx.error_summary)) { 87 if (unlikely(p->des01.rx.error_summary)) {
87 if (unlikely(p->des01.rx.descriptor_error)) 88 if (unlikely(p->des01.rx.descriptor_error))
88 x->rx_desc++; 89 x->rx_desc++;
89 if (unlikely(p->des01.rx.partial_frame_error)) 90 if (unlikely(p->des01.rx.sa_filter_fail))
90 x->rx_partial++; 91 x->sa_filter_fail++;
91 if (unlikely(p->des01.rx.run_frame)) 92 if (unlikely(p->des01.rx.overflow_error))
92 x->rx_runt++; 93 x->overflow_error++;
93 if (unlikely(p->des01.rx.frame_too_long)) 94 if (unlikely(p->des01.rx.ipc_csum_error))
94 x->rx_toolong++; 95 x->ipc_csum_error++;
95 if (unlikely(p->des01.rx.collision)) { 96 if (unlikely(p->des01.rx.collision)) {
96 x->rx_collision++; 97 x->rx_collision++;
97 stats->collisions++; 98 stats->collisions++;
@@ -113,10 +114,10 @@ static int ndesc_get_rx_status(void *data, struct stmmac_extra_stats *x,
113 x->rx_mii++; 114 x->rx_mii++;
114 ret = discard_frame; 115 ret = discard_frame;
115 } 116 }
116 if (p->des01.rx.multicast_frame) { 117#ifdef STMMAC_VLAN_TAG_USED
117 x->rx_multicast++; 118 if (p->des01.rx.vlan_tag)
118 stats->multicast++; 119 x->vlan_tag++;
119 } 120#endif
120 return ret; 121 return ret;
121} 122}
122 123
@@ -184,6 +185,9 @@ static void ndesc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
184{ 185{
185 p->des01.tx.first_segment = is_fs; 186 p->des01.tx.first_segment = is_fs;
186 norm_set_tx_desc_len(p, len); 187 norm_set_tx_desc_len(p, len);
188
189 if (likely(csum_flag))
190 p->des01.tx.checksum_insertion = cic_full;
187} 191}
188 192
189static void ndesc_clear_tx_ic(struct dma_desc *p) 193static void ndesc_clear_tx_ic(struct dma_desc *p)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index 406404f6e32..e8eff09bbbd 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -50,7 +50,7 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
50 STMMAC_STAT(tx_underflow), 50 STMMAC_STAT(tx_underflow),
51 STMMAC_STAT(tx_carrier), 51 STMMAC_STAT(tx_carrier),
52 STMMAC_STAT(tx_losscarrier), 52 STMMAC_STAT(tx_losscarrier),
53 STMMAC_STAT(tx_heartbeat), 53 STMMAC_STAT(vlan_tag),
54 STMMAC_STAT(tx_deferred), 54 STMMAC_STAT(tx_deferred),
55 STMMAC_STAT(tx_vlan), 55 STMMAC_STAT(tx_vlan),
56 STMMAC_STAT(rx_vlan), 56 STMMAC_STAT(rx_vlan),
@@ -59,9 +59,9 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
59 STMMAC_STAT(tx_payload_error), 59 STMMAC_STAT(tx_payload_error),
60 STMMAC_STAT(tx_ip_header_error), 60 STMMAC_STAT(tx_ip_header_error),
61 STMMAC_STAT(rx_desc), 61 STMMAC_STAT(rx_desc),
62 STMMAC_STAT(rx_partial), 62 STMMAC_STAT(sa_filter_fail),
63 STMMAC_STAT(rx_runt), 63 STMMAC_STAT(overflow_error),
64 STMMAC_STAT(rx_toolong), 64 STMMAC_STAT(ipc_csum_error),
65 STMMAC_STAT(rx_collision), 65 STMMAC_STAT(rx_collision),
66 STMMAC_STAT(rx_crc), 66 STMMAC_STAT(rx_crc),
67 STMMAC_STAT(rx_length), 67 STMMAC_STAT(rx_length),
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 003ab56f49b..20546bbbb8d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -813,6 +813,7 @@ static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv)
813static int stmmac_get_hw_features(struct stmmac_priv *priv) 813static int stmmac_get_hw_features(struct stmmac_priv *priv)
814{ 814{
815 u32 hw_cap = 0; 815 u32 hw_cap = 0;
816
816 if (priv->hw->dma->get_hw_feature) { 817 if (priv->hw->dma->get_hw_feature) {
817 hw_cap = priv->hw->dma->get_hw_feature(priv->ioaddr); 818 hw_cap = priv->hw->dma->get_hw_feature(priv->ioaddr);
818 819
@@ -938,6 +939,7 @@ static int stmmac_open(struct net_device *dev)
938 939
939 stmmac_get_hw_features(priv); 940 stmmac_get_hw_features(priv);
940 941
942 priv->rx_coe = priv->hw->mac->rx_coe(priv->ioaddr);
941 if (priv->rx_coe) 943 if (priv->rx_coe)
942 pr_info("stmmac: Rx Checksum Offload Engine supported\n"); 944 pr_info("stmmac: Rx Checksum Offload Engine supported\n");
943 if (priv->plat->tx_coe) 945 if (priv->plat->tx_coe)
@@ -1275,8 +1277,8 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
1275#endif 1277#endif
1276 skb->protocol = eth_type_trans(skb, priv->dev); 1278 skb->protocol = eth_type_trans(skb, priv->dev);
1277 1279
1278 if (unlikely(status == csum_none)) { 1280 if (unlikely(!priv->rx_coe)) {
1279 /* always for the old mac 10/100 */ 1281 /* No RX COE for old mac10/100 devices */
1280 skb_checksum_none_assert(skb); 1282 skb_checksum_none_assert(skb);
1281 netif_receive_skb(skb); 1283 netif_receive_skb(skb);
1282 } else { 1284 } else {