sfc: Rename register I/O header and functions used by both Falcon and Siena
[deliverable/linux.git] / drivers / net / sfc / falcon_xmac.c
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 "regs.h"
16 #include "io.h"
17 #include "mac.h"
18 #include "mdio_10g.h"
19 #include "phy.h"
20 #include "workarounds.h"
21
22 /**************************************************************************
23 *
24 * MAC operations
25 *
26 *************************************************************************/
27
28 /* Configure the XAUI driver that is an output from Falcon */
29 static void falcon_setup_xaui(struct efx_nic *efx)
30 {
31 efx_oword_t sdctl, txdrv;
32
33 /* Move the XAUI into low power, unless there is no PHY, in
34 * which case the XAUI will have to drive a cable. */
35 if (efx->phy_type == PHY_TYPE_NONE)
36 return;
37
38 efx_reado(efx, &sdctl, FR_AB_XX_SD_CTL);
39 EFX_SET_OWORD_FIELD(sdctl, FRF_AB_XX_HIDRVD, FFE_AB_XX_SD_CTL_DRV_DEF);
40 EFX_SET_OWORD_FIELD(sdctl, FRF_AB_XX_LODRVD, FFE_AB_XX_SD_CTL_DRV_DEF);
41 EFX_SET_OWORD_FIELD(sdctl, FRF_AB_XX_HIDRVC, FFE_AB_XX_SD_CTL_DRV_DEF);
42 EFX_SET_OWORD_FIELD(sdctl, FRF_AB_XX_LODRVC, FFE_AB_XX_SD_CTL_DRV_DEF);
43 EFX_SET_OWORD_FIELD(sdctl, FRF_AB_XX_HIDRVB, FFE_AB_XX_SD_CTL_DRV_DEF);
44 EFX_SET_OWORD_FIELD(sdctl, FRF_AB_XX_LODRVB, FFE_AB_XX_SD_CTL_DRV_DEF);
45 EFX_SET_OWORD_FIELD(sdctl, FRF_AB_XX_HIDRVA, FFE_AB_XX_SD_CTL_DRV_DEF);
46 EFX_SET_OWORD_FIELD(sdctl, FRF_AB_XX_LODRVA, FFE_AB_XX_SD_CTL_DRV_DEF);
47 efx_writeo(efx, &sdctl, FR_AB_XX_SD_CTL);
48
49 EFX_POPULATE_OWORD_8(txdrv,
50 FRF_AB_XX_DEQD, FFE_AB_XX_TXDRV_DEQ_DEF,
51 FRF_AB_XX_DEQC, FFE_AB_XX_TXDRV_DEQ_DEF,
52 FRF_AB_XX_DEQB, FFE_AB_XX_TXDRV_DEQ_DEF,
53 FRF_AB_XX_DEQA, FFE_AB_XX_TXDRV_DEQ_DEF,
54 FRF_AB_XX_DTXD, FFE_AB_XX_TXDRV_DTX_DEF,
55 FRF_AB_XX_DTXC, FFE_AB_XX_TXDRV_DTX_DEF,
56 FRF_AB_XX_DTXB, FFE_AB_XX_TXDRV_DTX_DEF,
57 FRF_AB_XX_DTXA, FFE_AB_XX_TXDRV_DTX_DEF);
58 efx_writeo(efx, &txdrv, FR_AB_XX_TXDRV_CTL);
59 }
60
61 int falcon_reset_xaui(struct efx_nic *efx)
62 {
63 efx_oword_t reg;
64 int count;
65
66 /* Start reset sequence */
67 EFX_POPULATE_DWORD_1(reg, FRF_AB_XX_RST_XX_EN, 1);
68 efx_writeo(efx, &reg, FR_AB_XX_PWR_RST);
69
70 /* Wait up to 10 ms for completion, then reinitialise */
71 for (count = 0; count < 1000; count++) {
72 efx_reado(efx, &reg, FR_AB_XX_PWR_RST);
73 if (EFX_OWORD_FIELD(reg, FRF_AB_XX_RST_XX_EN) == 0 &&
74 EFX_OWORD_FIELD(reg, FRF_AB_XX_SD_RST_ACT) == 0) {
75 falcon_setup_xaui(efx);
76 return 0;
77 }
78 udelay(10);
79 }
80 EFX_ERR(efx, "timed out waiting for XAUI/XGXS reset\n");
81 return -ETIMEDOUT;
82 }
83
84 static void falcon_mask_status_intr(struct efx_nic *efx, bool enable)
85 {
86 efx_oword_t reg;
87
88 if ((falcon_rev(efx) != FALCON_REV_B0) || LOOPBACK_INTERNAL(efx))
89 return;
90
91 /* We expect xgmii faults if the wireside link is up */
92 if (!EFX_WORKAROUND_5147(efx) || !efx->link_up)
93 return;
94
95 /* We can only use this interrupt to signal the negative edge of
96 * xaui_align [we have to poll the positive edge]. */
97 if (!efx->mac_up)
98 return;
99
100 /* Flush the ISR */
101 if (enable)
102 efx_reado(efx, &reg, FR_AB_XM_MGT_INT_MSK);
103
104 EFX_POPULATE_OWORD_2(reg,
105 FRF_AB_XM_MSK_RMTFLT, !enable,
106 FRF_AB_XM_MSK_LCLFLT, !enable);
107 efx_writeo(efx, &reg, FR_AB_XM_MGT_INT_MASK);
108 }
109
110 /* Get status of XAUI link */
111 bool falcon_xaui_link_ok(struct efx_nic *efx)
112 {
113 efx_oword_t reg;
114 bool align_done, link_ok = false;
115 int sync_status;
116
117 if (LOOPBACK_INTERNAL(efx))
118 return true;
119
120 /* Read link status */
121 efx_reado(efx, &reg, FR_AB_XX_CORE_STAT);
122
123 align_done = EFX_OWORD_FIELD(reg, FRF_AB_XX_ALIGN_DONE);
124 sync_status = EFX_OWORD_FIELD(reg, FRF_AB_XX_SYNC_STAT);
125 if (align_done && (sync_status == FFE_AB_XX_STAT_ALL_LANES))
126 link_ok = true;
127
128 /* Clear link status ready for next read */
129 EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_COMMA_DET, FFE_AB_XX_STAT_ALL_LANES);
130 EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_CHAR_ERR, FFE_AB_XX_STAT_ALL_LANES);
131 EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_DISPERR, FFE_AB_XX_STAT_ALL_LANES);
132 efx_writeo(efx, &reg, FR_AB_XX_CORE_STAT);
133
134 /* If the link is up, then check the phy side of the xaui link */
135 if (efx->link_up && link_ok)
136 if (efx->phy_op->mmds & (1 << MDIO_MMD_PHYXS))
137 link_ok = efx_mdio_phyxgxs_lane_sync(efx);
138
139 return link_ok;
140 }
141
142 static void falcon_reconfigure_xmac_core(struct efx_nic *efx)
143 {
144 unsigned int max_frame_len;
145 efx_oword_t reg;
146 bool rx_fc = !!(efx->link_fc & EFX_FC_RX);
147
148 /* Configure MAC - cut-thru mode is hard wired on */
149 EFX_POPULATE_DWORD_3(reg,
150 FRF_AB_XM_RX_JUMBO_MODE, 1,
151 FRF_AB_XM_TX_STAT_EN, 1,
152 FRF_AB_XM_RX_STAT_EN, 1);
153 efx_writeo(efx, &reg, FR_AB_XM_GLB_CFG);
154
155 /* Configure TX */
156 EFX_POPULATE_DWORD_6(reg,
157 FRF_AB_XM_TXEN, 1,
158 FRF_AB_XM_TX_PRMBL, 1,
159 FRF_AB_XM_AUTO_PAD, 1,
160 FRF_AB_XM_TXCRC, 1,
161 FRF_AB_XM_FCNTL, 1,
162 FRF_AB_XM_IPG, 0x3);
163 efx_writeo(efx, &reg, FR_AB_XM_TX_CFG);
164
165 /* Configure RX */
166 EFX_POPULATE_DWORD_5(reg,
167 FRF_AB_XM_RXEN, 1,
168 FRF_AB_XM_AUTO_DEPAD, 0,
169 FRF_AB_XM_ACPT_ALL_MCAST, 1,
170 FRF_AB_XM_ACPT_ALL_UCAST, efx->promiscuous,
171 FRF_AB_XM_PASS_CRC_ERR, 1);
172 efx_writeo(efx, &reg, FR_AB_XM_RX_CFG);
173
174 /* Set frame length */
175 max_frame_len = EFX_MAX_FRAME_LEN(efx->net_dev->mtu);
176 EFX_POPULATE_DWORD_1(reg, FRF_AB_XM_MAX_RX_FRM_SIZE, max_frame_len);
177 efx_writeo(efx, &reg, FR_AB_XM_RX_PARAM);
178 EFX_POPULATE_DWORD_2(reg,
179 FRF_AB_XM_MAX_TX_FRM_SIZE, max_frame_len,
180 FRF_AB_XM_TX_JUMBO_MODE, 1);
181 efx_writeo(efx, &reg, FR_AB_XM_TX_PARAM);
182
183 EFX_POPULATE_DWORD_2(reg,
184 FRF_AB_XM_PAUSE_TIME, 0xfffe, /* MAX PAUSE TIME */
185 FRF_AB_XM_DIS_FCNTL, !rx_fc);
186 efx_writeo(efx, &reg, FR_AB_XM_FC);
187
188 /* Set MAC address */
189 memcpy(&reg, &efx->net_dev->dev_addr[0], 4);
190 efx_writeo(efx, &reg, FR_AB_XM_ADR_LO);
191 memcpy(&reg, &efx->net_dev->dev_addr[4], 2);
192 efx_writeo(efx, &reg, FR_AB_XM_ADR_HI);
193 }
194
195 static void falcon_reconfigure_xgxs_core(struct efx_nic *efx)
196 {
197 efx_oword_t reg;
198 bool xgxs_loopback = (efx->loopback_mode == LOOPBACK_XGXS);
199 bool xaui_loopback = (efx->loopback_mode == LOOPBACK_XAUI);
200 bool xgmii_loopback = (efx->loopback_mode == LOOPBACK_XGMII);
201
202 /* XGXS block is flaky and will need to be reset if moving
203 * into our out of XGMII, XGXS or XAUI loopbacks. */
204 if (EFX_WORKAROUND_5147(efx)) {
205 bool old_xgmii_loopback, old_xgxs_loopback, old_xaui_loopback;
206 bool reset_xgxs;
207
208 efx_reado(efx, &reg, FR_AB_XX_CORE_STAT);
209 old_xgxs_loopback = EFX_OWORD_FIELD(reg, FRF_AB_XX_XGXS_LB_EN);
210 old_xgmii_loopback =
211 EFX_OWORD_FIELD(reg, FRF_AB_XX_XGMII_LB_EN);
212
213 efx_reado(efx, &reg, FR_AB_XX_SD_CTL);
214 old_xaui_loopback = EFX_OWORD_FIELD(reg, FRF_AB_XX_LPBKA);
215
216 /* The PHY driver may have turned XAUI off */
217 reset_xgxs = ((xgxs_loopback != old_xgxs_loopback) ||
218 (xaui_loopback != old_xaui_loopback) ||
219 (xgmii_loopback != old_xgmii_loopback));
220
221 if (reset_xgxs)
222 falcon_reset_xaui(efx);
223 }
224
225 efx_reado(efx, &reg, FR_AB_XX_CORE_STAT);
226 EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_FORCE_SIG,
227 (xgxs_loopback || xaui_loopback) ?
228 FFE_AB_XX_FORCE_SIG_ALL_LANES : 0);
229 EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_XGXS_LB_EN, xgxs_loopback);
230 EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_XGMII_LB_EN, xgmii_loopback);
231 efx_writeo(efx, &reg, FR_AB_XX_CORE_STAT);
232
233 efx_reado(efx, &reg, FR_AB_XX_SD_CTL);
234 EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_LPBKD, xaui_loopback);
235 EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_LPBKC, xaui_loopback);
236 EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_LPBKB, xaui_loopback);
237 EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_LPBKA, xaui_loopback);
238 efx_writeo(efx, &reg, FR_AB_XX_SD_CTL);
239 }
240
241
242 /* Try and bring the Falcon side of the Falcon-Phy XAUI link fails
243 * to come back up. Bash it until it comes back up */
244 static void falcon_check_xaui_link_up(struct efx_nic *efx, int tries)
245 {
246 efx->mac_up = falcon_xaui_link_ok(efx);
247
248 if ((efx->loopback_mode == LOOPBACK_NETWORK) ||
249 efx_phy_mode_disabled(efx->phy_mode))
250 /* XAUI link is expected to be down */
251 return;
252
253 while (!efx->mac_up && tries) {
254 EFX_LOG(efx, "bashing xaui\n");
255 falcon_reset_xaui(efx);
256 udelay(200);
257
258 efx->mac_up = falcon_xaui_link_ok(efx);
259 --tries;
260 }
261 }
262
263 static void falcon_reconfigure_xmac(struct efx_nic *efx)
264 {
265 falcon_mask_status_intr(efx, false);
266
267 falcon_reconfigure_xgxs_core(efx);
268 falcon_reconfigure_xmac_core(efx);
269
270 falcon_reconfigure_mac_wrapper(efx);
271
272 falcon_check_xaui_link_up(efx, 5);
273 falcon_mask_status_intr(efx, true);
274 }
275
276 static void falcon_update_stats_xmac(struct efx_nic *efx)
277 {
278 struct efx_mac_stats *mac_stats = &efx->mac_stats;
279 int rc;
280
281 rc = falcon_dma_stats(efx, XgDmaDone_offset);
282 if (rc)
283 return;
284
285 /* Update MAC stats from DMAed values */
286 FALCON_STAT(efx, XgRxOctets, rx_bytes);
287 FALCON_STAT(efx, XgRxOctetsOK, rx_good_bytes);
288 FALCON_STAT(efx, XgRxPkts, rx_packets);
289 FALCON_STAT(efx, XgRxPktsOK, rx_good);
290 FALCON_STAT(efx, XgRxBroadcastPkts, rx_broadcast);
291 FALCON_STAT(efx, XgRxMulticastPkts, rx_multicast);
292 FALCON_STAT(efx, XgRxUnicastPkts, rx_unicast);
293 FALCON_STAT(efx, XgRxUndersizePkts, rx_lt64);
294 FALCON_STAT(efx, XgRxOversizePkts, rx_gtjumbo);
295 FALCON_STAT(efx, XgRxJabberPkts, rx_bad_gtjumbo);
296 FALCON_STAT(efx, XgRxUndersizeFCSerrorPkts, rx_bad_lt64);
297 FALCON_STAT(efx, XgRxDropEvents, rx_overflow);
298 FALCON_STAT(efx, XgRxFCSerrorPkts, rx_bad);
299 FALCON_STAT(efx, XgRxAlignError, rx_align_error);
300 FALCON_STAT(efx, XgRxSymbolError, rx_symbol_error);
301 FALCON_STAT(efx, XgRxInternalMACError, rx_internal_error);
302 FALCON_STAT(efx, XgRxControlPkts, rx_control);
303 FALCON_STAT(efx, XgRxPausePkts, rx_pause);
304 FALCON_STAT(efx, XgRxPkts64Octets, rx_64);
305 FALCON_STAT(efx, XgRxPkts65to127Octets, rx_65_to_127);
306 FALCON_STAT(efx, XgRxPkts128to255Octets, rx_128_to_255);
307 FALCON_STAT(efx, XgRxPkts256to511Octets, rx_256_to_511);
308 FALCON_STAT(efx, XgRxPkts512to1023Octets, rx_512_to_1023);
309 FALCON_STAT(efx, XgRxPkts1024to15xxOctets, rx_1024_to_15xx);
310 FALCON_STAT(efx, XgRxPkts15xxtoMaxOctets, rx_15xx_to_jumbo);
311 FALCON_STAT(efx, XgRxLengthError, rx_length_error);
312 FALCON_STAT(efx, XgTxPkts, tx_packets);
313 FALCON_STAT(efx, XgTxOctets, tx_bytes);
314 FALCON_STAT(efx, XgTxMulticastPkts, tx_multicast);
315 FALCON_STAT(efx, XgTxBroadcastPkts, tx_broadcast);
316 FALCON_STAT(efx, XgTxUnicastPkts, tx_unicast);
317 FALCON_STAT(efx, XgTxControlPkts, tx_control);
318 FALCON_STAT(efx, XgTxPausePkts, tx_pause);
319 FALCON_STAT(efx, XgTxPkts64Octets, tx_64);
320 FALCON_STAT(efx, XgTxPkts65to127Octets, tx_65_to_127);
321 FALCON_STAT(efx, XgTxPkts128to255Octets, tx_128_to_255);
322 FALCON_STAT(efx, XgTxPkts256to511Octets, tx_256_to_511);
323 FALCON_STAT(efx, XgTxPkts512to1023Octets, tx_512_to_1023);
324 FALCON_STAT(efx, XgTxPkts1024to15xxOctets, tx_1024_to_15xx);
325 FALCON_STAT(efx, XgTxPkts1519toMaxOctets, tx_15xx_to_jumbo);
326 FALCON_STAT(efx, XgTxUndersizePkts, tx_lt64);
327 FALCON_STAT(efx, XgTxOversizePkts, tx_gtjumbo);
328 FALCON_STAT(efx, XgTxNonTcpUdpPkt, tx_non_tcpudp);
329 FALCON_STAT(efx, XgTxMacSrcErrPkt, tx_mac_src_error);
330 FALCON_STAT(efx, XgTxIpSrcErrPkt, tx_ip_src_error);
331
332 /* Update derived statistics */
333 mac_stats->tx_good_bytes =
334 (mac_stats->tx_bytes - mac_stats->tx_bad_bytes -
335 mac_stats->tx_control * 64);
336 mac_stats->rx_bad_bytes =
337 (mac_stats->rx_bytes - mac_stats->rx_good_bytes -
338 mac_stats->rx_control * 64);
339 }
340
341 static void falcon_xmac_irq(struct efx_nic *efx)
342 {
343 /* The XGMII link has a transient fault, which indicates either:
344 * - there's a transient xgmii fault
345 * - falcon's end of the xaui link may need a kick
346 * - the wire-side link may have gone down, but the lasi/poll()
347 * hasn't noticed yet.
348 *
349 * We only want to even bother polling XAUI if we're confident it's
350 * not (1) or (3). In both cases, the only reliable way to spot this
351 * is to wait a bit. We do this here by forcing the mac link state
352 * to down, and waiting for the mac poll to come round and check
353 */
354 efx->mac_up = false;
355 }
356
357 static void falcon_poll_xmac(struct efx_nic *efx)
358 {
359 if (!EFX_WORKAROUND_5147(efx) || !efx->link_up || efx->mac_up)
360 return;
361
362 falcon_mask_status_intr(efx, false);
363 falcon_check_xaui_link_up(efx, 1);
364 falcon_mask_status_intr(efx, true);
365 }
366
367 struct efx_mac_operations falcon_xmac_operations = {
368 .reconfigure = falcon_reconfigure_xmac,
369 .update_stats = falcon_update_stats_xmac,
370 .irq = falcon_xmac_irq,
371 .poll = falcon_poll_xmac,
372 };
This page took 0.040791 seconds and 5 git commands to generate.