diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2008-12-13 00:50:08 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-12-13 00:58:17 -0500 |
commit | 177dfcd80f28f8fbc3e22c2d8b24d21cb86f1d97 (patch) | |
tree | a6e5e9949f388d48ac20c4efbb2811762ac5f9d4 /drivers/net/sfc/falcon_gmac.c | |
parent | 356eebb2b3af24cc701823f1e025f04eef333239 (diff) |
sfc: Add support for sub-10G speeds
The SFC4000 has a separate MAC for use at sub-10G speeds. Introduce
an efx_mac_operations structure with implementations for the two MACs.
Switch between the MACs as necessary.
PHY settings are independent of the MAC, so add get_settings() and
set_settings() to efx_phy_operations. Also add macs field to indicate
which MACs the PHY is connected to.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sfc/falcon_gmac.c')
-rw-r--r-- | drivers/net/sfc/falcon_gmac.c | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/drivers/net/sfc/falcon_gmac.c b/drivers/net/sfc/falcon_gmac.c new file mode 100644 index 000000000000..247f8025ef00 --- /dev/null +++ b/drivers/net/sfc/falcon_gmac.c | |||
@@ -0,0 +1,233 @@ | |||
1 | /**************************************************************************** | ||
2 | * Driver for Solarflare Solarstorm network controllers and boards | ||
3 | * Copyright 2005-2006 Fen Systems Ltd. | ||
4 | * Copyright 2006-2008 Solarflare Communications Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License version 2 as published | ||
8 | * by the Free Software Foundation, incorporated herein by reference. | ||
9 | */ | ||
10 | |||
11 | #include <linux/delay.h> | ||
12 | #include "net_driver.h" | ||
13 | #include "efx.h" | ||
14 | #include "falcon.h" | ||
15 | #include "mac.h" | ||
16 | #include "falcon_hwdefs.h" | ||
17 | #include "falcon_io.h" | ||
18 | #include "gmii.h" | ||
19 | |||
20 | /************************************************************************** | ||
21 | * | ||
22 | * MAC operations | ||
23 | * | ||
24 | *************************************************************************/ | ||
25 | |||
26 | static void falcon_reconfigure_gmac(struct efx_nic *efx) | ||
27 | { | ||
28 | bool loopback, tx_fc, rx_fc, bytemode; | ||
29 | int if_mode; | ||
30 | unsigned int max_frame_len; | ||
31 | efx_oword_t reg; | ||
32 | |||
33 | /* Configuration register 1 */ | ||
34 | tx_fc = (efx->flow_control & EFX_FC_TX) || !efx->link_fd; | ||
35 | rx_fc = !!(efx->flow_control & EFX_FC_RX); | ||
36 | loopback = (efx->loopback_mode == LOOPBACK_GMAC); | ||
37 | bytemode = (efx->link_speed == 1000); | ||
38 | |||
39 | EFX_POPULATE_OWORD_5(reg, | ||
40 | GM_LOOP, loopback, | ||
41 | GM_TX_EN, 1, | ||
42 | GM_TX_FC_EN, tx_fc, | ||
43 | GM_RX_EN, 1, | ||
44 | GM_RX_FC_EN, rx_fc); | ||
45 | falcon_write(efx, ®, GM_CFG1_REG); | ||
46 | udelay(10); | ||
47 | |||
48 | /* Configuration register 2 */ | ||
49 | if_mode = (bytemode) ? 2 : 1; | ||
50 | EFX_POPULATE_OWORD_5(reg, | ||
51 | GM_IF_MODE, if_mode, | ||
52 | GM_PAD_CRC_EN, 1, | ||
53 | GM_LEN_CHK, 1, | ||
54 | GM_FD, efx->link_fd, | ||
55 | GM_PAMBL_LEN, 0x7/*datasheet recommended */); | ||
56 | |||
57 | falcon_write(efx, ®, GM_CFG2_REG); | ||
58 | udelay(10); | ||
59 | |||
60 | /* Max frame len register */ | ||
61 | max_frame_len = EFX_MAX_FRAME_LEN(efx->net_dev->mtu); | ||
62 | EFX_POPULATE_OWORD_1(reg, GM_MAX_FLEN, max_frame_len); | ||
63 | falcon_write(efx, ®, GM_MAX_FLEN_REG); | ||
64 | udelay(10); | ||
65 | |||
66 | /* FIFO configuration register 0 */ | ||
67 | EFX_POPULATE_OWORD_5(reg, | ||
68 | GMF_FTFENREQ, 1, | ||
69 | GMF_STFENREQ, 1, | ||
70 | GMF_FRFENREQ, 1, | ||
71 | GMF_SRFENREQ, 1, | ||
72 | GMF_WTMENREQ, 1); | ||
73 | falcon_write(efx, ®, GMF_CFG0_REG); | ||
74 | udelay(10); | ||
75 | |||
76 | /* FIFO configuration register 1 */ | ||
77 | EFX_POPULATE_OWORD_2(reg, | ||
78 | GMF_CFGFRTH, 0x12, | ||
79 | GMF_CFGXOFFRTX, 0xffff); | ||
80 | falcon_write(efx, ®, GMF_CFG1_REG); | ||
81 | udelay(10); | ||
82 | |||
83 | /* FIFO configuration register 2 */ | ||
84 | EFX_POPULATE_OWORD_2(reg, | ||
85 | GMF_CFGHWM, 0x3f, | ||
86 | GMF_CFGLWM, 0xa); | ||
87 | falcon_write(efx, ®, GMF_CFG2_REG); | ||
88 | udelay(10); | ||
89 | |||
90 | /* FIFO configuration register 3 */ | ||
91 | EFX_POPULATE_OWORD_2(reg, | ||
92 | GMF_CFGHWMFT, 0x1c, | ||
93 | GMF_CFGFTTH, 0x08); | ||
94 | falcon_write(efx, ®, GMF_CFG3_REG); | ||
95 | udelay(10); | ||
96 | |||
97 | /* FIFO configuration register 4 */ | ||
98 | EFX_POPULATE_OWORD_1(reg, GMF_HSTFLTRFRM_PAUSE, 1); | ||
99 | falcon_write(efx, ®, GMF_CFG4_REG); | ||
100 | udelay(10); | ||
101 | |||
102 | /* FIFO configuration register 5 */ | ||
103 | falcon_read(efx, ®, GMF_CFG5_REG); | ||
104 | EFX_SET_OWORD_FIELD(reg, GMF_CFGBYTMODE, bytemode); | ||
105 | EFX_SET_OWORD_FIELD(reg, GMF_CFGHDPLX, !efx->link_fd); | ||
106 | EFX_SET_OWORD_FIELD(reg, GMF_HSTDRPLT64, !efx->link_fd); | ||
107 | EFX_SET_OWORD_FIELD(reg, GMF_HSTFLTRFRMDC_PAUSE, 0); | ||
108 | falcon_write(efx, ®, GMF_CFG5_REG); | ||
109 | udelay(10); | ||
110 | |||
111 | /* MAC address */ | ||
112 | EFX_POPULATE_OWORD_4(reg, | ||
113 | GM_HWADDR_5, efx->net_dev->dev_addr[5], | ||
114 | GM_HWADDR_4, efx->net_dev->dev_addr[4], | ||
115 | GM_HWADDR_3, efx->net_dev->dev_addr[3], | ||
116 | GM_HWADDR_2, efx->net_dev->dev_addr[2]); | ||
117 | falcon_write(efx, ®, GM_ADR1_REG); | ||
118 | udelay(10); | ||
119 | EFX_POPULATE_OWORD_2(reg, | ||
120 | GM_HWADDR_1, efx->net_dev->dev_addr[1], | ||
121 | GM_HWADDR_0, efx->net_dev->dev_addr[0]); | ||
122 | falcon_write(efx, ®, GM_ADR2_REG); | ||
123 | udelay(10); | ||
124 | |||
125 | falcon_reconfigure_mac_wrapper(efx); | ||
126 | } | ||
127 | |||
128 | static void falcon_update_stats_gmac(struct efx_nic *efx) | ||
129 | { | ||
130 | struct efx_mac_stats *mac_stats = &efx->mac_stats; | ||
131 | unsigned long old_rx_pause, old_tx_pause; | ||
132 | unsigned long new_rx_pause, new_tx_pause; | ||
133 | int rc; | ||
134 | |||
135 | rc = falcon_dma_stats(efx, GDmaDone_offset); | ||
136 | if (rc) | ||
137 | return; | ||
138 | |||
139 | /* Pause frames are erroneously counted as errors (SFC bug 3269) */ | ||
140 | old_rx_pause = mac_stats->rx_pause; | ||
141 | old_tx_pause = mac_stats->tx_pause; | ||
142 | |||
143 | /* Update MAC stats from DMAed values */ | ||
144 | FALCON_STAT(efx, GRxGoodOct, rx_good_bytes); | ||
145 | FALCON_STAT(efx, GRxBadOct, rx_bad_bytes); | ||
146 | FALCON_STAT(efx, GRxMissPkt, rx_missed); | ||
147 | FALCON_STAT(efx, GRxFalseCRS, rx_false_carrier); | ||
148 | FALCON_STAT(efx, GRxPausePkt, rx_pause); | ||
149 | FALCON_STAT(efx, GRxBadPkt, rx_bad); | ||
150 | FALCON_STAT(efx, GRxUcastPkt, rx_unicast); | ||
151 | FALCON_STAT(efx, GRxMcastPkt, rx_multicast); | ||
152 | FALCON_STAT(efx, GRxBcastPkt, rx_broadcast); | ||
153 | FALCON_STAT(efx, GRxGoodLt64Pkt, rx_good_lt64); | ||
154 | FALCON_STAT(efx, GRxBadLt64Pkt, rx_bad_lt64); | ||
155 | FALCON_STAT(efx, GRx64Pkt, rx_64); | ||
156 | FALCON_STAT(efx, GRx65to127Pkt, rx_65_to_127); | ||
157 | FALCON_STAT(efx, GRx128to255Pkt, rx_128_to_255); | ||
158 | FALCON_STAT(efx, GRx256to511Pkt, rx_256_to_511); | ||
159 | FALCON_STAT(efx, GRx512to1023Pkt, rx_512_to_1023); | ||
160 | FALCON_STAT(efx, GRx1024to15xxPkt, rx_1024_to_15xx); | ||
161 | FALCON_STAT(efx, GRx15xxtoJumboPkt, rx_15xx_to_jumbo); | ||
162 | FALCON_STAT(efx, GRxGtJumboPkt, rx_gtjumbo); | ||
163 | FALCON_STAT(efx, GRxFcsErr64to15xxPkt, rx_bad_64_to_15xx); | ||
164 | FALCON_STAT(efx, GRxFcsErr15xxtoJumboPkt, rx_bad_15xx_to_jumbo); | ||
165 | FALCON_STAT(efx, GRxFcsErrGtJumboPkt, rx_bad_gtjumbo); | ||
166 | FALCON_STAT(efx, GTxGoodBadOct, tx_bytes); | ||
167 | FALCON_STAT(efx, GTxGoodOct, tx_good_bytes); | ||
168 | FALCON_STAT(efx, GTxSglColPkt, tx_single_collision); | ||
169 | FALCON_STAT(efx, GTxMultColPkt, tx_multiple_collision); | ||
170 | FALCON_STAT(efx, GTxExColPkt, tx_excessive_collision); | ||
171 | FALCON_STAT(efx, GTxDefPkt, tx_deferred); | ||
172 | FALCON_STAT(efx, GTxLateCol, tx_late_collision); | ||
173 | FALCON_STAT(efx, GTxExDefPkt, tx_excessive_deferred); | ||
174 | FALCON_STAT(efx, GTxPausePkt, tx_pause); | ||
175 | FALCON_STAT(efx, GTxBadPkt, tx_bad); | ||
176 | FALCON_STAT(efx, GTxUcastPkt, tx_unicast); | ||
177 | FALCON_STAT(efx, GTxMcastPkt, tx_multicast); | ||
178 | FALCON_STAT(efx, GTxBcastPkt, tx_broadcast); | ||
179 | FALCON_STAT(efx, GTxLt64Pkt, tx_lt64); | ||
180 | FALCON_STAT(efx, GTx64Pkt, tx_64); | ||
181 | FALCON_STAT(efx, GTx65to127Pkt, tx_65_to_127); | ||
182 | FALCON_STAT(efx, GTx128to255Pkt, tx_128_to_255); | ||
183 | FALCON_STAT(efx, GTx256to511Pkt, tx_256_to_511); | ||
184 | FALCON_STAT(efx, GTx512to1023Pkt, tx_512_to_1023); | ||
185 | FALCON_STAT(efx, GTx1024to15xxPkt, tx_1024_to_15xx); | ||
186 | FALCON_STAT(efx, GTx15xxtoJumboPkt, tx_15xx_to_jumbo); | ||
187 | FALCON_STAT(efx, GTxGtJumboPkt, tx_gtjumbo); | ||
188 | FALCON_STAT(efx, GTxNonTcpUdpPkt, tx_non_tcpudp); | ||
189 | FALCON_STAT(efx, GTxMacSrcErrPkt, tx_mac_src_error); | ||
190 | FALCON_STAT(efx, GTxIpSrcErrPkt, tx_ip_src_error); | ||
191 | |||
192 | /* Pause frames are erroneously counted as errors (SFC bug 3269) */ | ||
193 | new_rx_pause = mac_stats->rx_pause; | ||
194 | new_tx_pause = mac_stats->tx_pause; | ||
195 | mac_stats->rx_bad -= (new_rx_pause - old_rx_pause); | ||
196 | mac_stats->tx_bad -= (new_tx_pause - old_tx_pause); | ||
197 | |||
198 | /* Derive stats that the MAC doesn't provide directly */ | ||
199 | mac_stats->tx_bad_bytes = | ||
200 | mac_stats->tx_bytes - mac_stats->tx_good_bytes; | ||
201 | mac_stats->tx_packets = | ||
202 | mac_stats->tx_lt64 + mac_stats->tx_64 + | ||
203 | mac_stats->tx_65_to_127 + mac_stats->tx_128_to_255 + | ||
204 | mac_stats->tx_256_to_511 + mac_stats->tx_512_to_1023 + | ||
205 | mac_stats->tx_1024_to_15xx + mac_stats->tx_15xx_to_jumbo + | ||
206 | mac_stats->tx_gtjumbo; | ||
207 | mac_stats->tx_collision = | ||
208 | mac_stats->tx_single_collision + | ||
209 | mac_stats->tx_multiple_collision + | ||
210 | mac_stats->tx_excessive_collision + | ||
211 | mac_stats->tx_late_collision; | ||
212 | mac_stats->rx_bytes = | ||
213 | mac_stats->rx_good_bytes + mac_stats->rx_bad_bytes; | ||
214 | mac_stats->rx_packets = | ||
215 | mac_stats->rx_good_lt64 + mac_stats->rx_bad_lt64 + | ||
216 | mac_stats->rx_64 + mac_stats->rx_65_to_127 + | ||
217 | mac_stats->rx_128_to_255 + mac_stats->rx_256_to_511 + | ||
218 | mac_stats->rx_512_to_1023 + mac_stats->rx_1024_to_15xx + | ||
219 | mac_stats->rx_15xx_to_jumbo + mac_stats->rx_gtjumbo; | ||
220 | mac_stats->rx_good = mac_stats->rx_packets - mac_stats->rx_bad; | ||
221 | mac_stats->rx_lt64 = mac_stats->rx_good_lt64 + mac_stats->rx_bad_lt64; | ||
222 | } | ||
223 | |||
224 | static int falcon_check_gmac(struct efx_nic *efx) | ||
225 | { | ||
226 | return efx->phy_op->check_hw(efx); | ||
227 | } | ||
228 | |||
229 | struct efx_mac_operations falcon_gmac_operations = { | ||
230 | .reconfigure = falcon_reconfigure_gmac, | ||
231 | .update_stats = falcon_update_stats_gmac, | ||
232 | .check_hw = falcon_check_gmac, | ||
233 | }; | ||