diff options
author | Giuseppe CAVALLARO <peppe.cavallaro@st.com> | 2011-10-26 15:43:09 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-10-27 23:17:12 -0400 |
commit | 3c20f72f9108b2fcf30ec63d8a4203736c01ccd0 (patch) | |
tree | 8310be8eba2e616fc3b93e5c7e379343c0480710 /drivers/net/ethernet/stmicro | |
parent | e2c57f839c63f452b4704e048c8db9cf669ed410 (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>
Diffstat (limited to 'drivers/net/ethernet/stmicro')
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/common.h | 8 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/descs.h | 31 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/norm_desc.c | 38 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 8 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6 |
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 9100c100d295..2cc119295821 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 63a03e264694..9820ec842cc0 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 f7e8ba7f501a..fda5d2b31d3a 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. */ |
73 | static int ndesc_get_rx_status(void *data, struct stmmac_extra_stats *x, | 74 | static 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 | ||
189 | static void ndesc_clear_tx_ic(struct dma_desc *p) | 193 | static 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 406404f6e321..e8eff09bbbd7 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 003ab56f49b6..20546bbbb8db 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) | |||
813 | static int stmmac_get_hw_features(struct stmmac_priv *priv) | 813 | static 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 { |