Commit | Line | Data |
---|---|---|
8ceee660 BH |
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" | |
3e6c4538 | 15 | #include "regs.h" |
8ceee660 BH |
16 | #include "falcon_io.h" |
17 | #include "mac.h" | |
8ceee660 BH |
18 | #include "mdio_10g.h" |
19 | #include "phy.h" | |
8ceee660 BH |
20 | #include "workarounds.h" |
21 | ||
8ceee660 BH |
22 | /************************************************************************** |
23 | * | |
24 | * MAC operations | |
25 | * | |
26 | *************************************************************************/ | |
8ceee660 BH |
27 | |
28 | /* Configure the XAUI driver that is an output from Falcon */ | |
29 | static void falcon_setup_xaui(struct efx_nic *efx) | |
30 | { | |
c1e5fcc9 | 31 | efx_oword_t sdctl, txdrv; |
8ceee660 BH |
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 | ||
3e6c4538 BH |
38 | falcon_read(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 | falcon_write(efx, &sdctl, FR_AB_XX_SD_CTL); | |
c1e5fcc9 BH |
48 | |
49 | EFX_POPULATE_OWORD_8(txdrv, | |
3e6c4538 BH |
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 | falcon_write(efx, &txdrv, FR_AB_XX_TXDRV_CTL); | |
8ceee660 BH |
59 | } |
60 | ||
ef08af03 | 61 | int falcon_reset_xaui(struct efx_nic *efx) |
8ceee660 | 62 | { |
c1e5fcc9 | 63 | efx_oword_t reg; |
8ceee660 BH |
64 | int count; |
65 | ||
d4ec09ac | 66 | /* Start reset sequence */ |
3e6c4538 BH |
67 | EFX_POPULATE_DWORD_1(reg, FRF_AB_XX_RST_XX_EN, 1); |
68 | falcon_write(efx, ®, FR_AB_XX_PWR_RST); | |
8ceee660 | 69 | |
d4ec09ac BH |
70 | /* Wait up to 10 ms for completion, then reinitialise */ |
71 | for (count = 0; count < 1000; count++) { | |
3e6c4538 BH |
72 | falcon_read(efx, ®, 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) { | |
8ceee660 BH |
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 | ||
177dfcd8 | 84 | static void falcon_mask_status_intr(struct efx_nic *efx, bool enable) |
8ceee660 | 85 | { |
c1e5fcc9 | 86 | efx_oword_t reg; |
8ceee660 | 87 | |
177dfcd8 BH |
88 | if ((falcon_rev(efx) != FALCON_REV_B0) || LOOPBACK_INTERNAL(efx)) |
89 | return; | |
8ceee660 | 90 | |
177dfcd8 BH |
91 | /* We expect xgmii faults if the wireside link is up */ |
92 | if (!EFX_WORKAROUND_5147(efx) || !efx->link_up) | |
93 | return; | |
8ceee660 | 94 | |
177dfcd8 BH |
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) | |
8ceee660 BH |
98 | return; |
99 | ||
100 | /* Flush the ISR */ | |
101 | if (enable) | |
3e6c4538 | 102 | falcon_read(efx, ®, FR_AB_XM_MGT_INT_MSK); |
8ceee660 | 103 | |
c1e5fcc9 | 104 | EFX_POPULATE_OWORD_2(reg, |
3e6c4538 BH |
105 | FRF_AB_XM_MSK_RMTFLT, !enable, |
106 | FRF_AB_XM_MSK_LCLFLT, !enable); | |
107 | falcon_write(efx, ®, FR_AB_XM_MGT_INT_MASK); | |
8ceee660 BH |
108 | } |
109 | ||
177dfcd8 | 110 | /* Get status of XAUI link */ |
dc8cfa55 | 111 | bool falcon_xaui_link_ok(struct efx_nic *efx) |
8ceee660 | 112 | { |
c1e5fcc9 | 113 | efx_oword_t reg; |
dc8cfa55 BH |
114 | bool align_done, link_ok = false; |
115 | int sync_status; | |
8ceee660 | 116 | |
3273c2e8 | 117 | if (LOOPBACK_INTERNAL(efx)) |
dc8cfa55 | 118 | return true; |
3273c2e8 | 119 | |
8ceee660 | 120 | /* Read link status */ |
3e6c4538 | 121 | falcon_read(efx, ®, FR_AB_XX_CORE_STAT); |
8ceee660 | 122 | |
3e6c4538 BH |
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)) | |
dc8cfa55 | 126 | link_ok = true; |
8ceee660 BH |
127 | |
128 | /* Clear link status ready for next read */ | |
3e6c4538 BH |
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 | falcon_write(efx, ®, FR_AB_XX_CORE_STAT); | |
8ceee660 | 133 | |
177dfcd8 BH |
134 | /* If the link is up, then check the phy side of the xaui link */ |
135 | if (efx->link_up && link_ok) | |
dc8cfa55 | 136 | if (efx->phy_op->mmds & (1 << MDIO_MMD_PHYXS)) |
68e7f45e | 137 | link_ok = efx_mdio_phyxgxs_lane_sync(efx); |
8ceee660 BH |
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; | |
c1e5fcc9 | 145 | efx_oword_t reg; |
04cc8cac | 146 | bool rx_fc = !!(efx->link_fc & EFX_FC_RX); |
8ceee660 BH |
147 | |
148 | /* Configure MAC - cut-thru mode is hard wired on */ | |
149 | EFX_POPULATE_DWORD_3(reg, | |
3e6c4538 BH |
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 | falcon_write(efx, ®, FR_AB_XM_GLB_CFG); | |
8ceee660 BH |
154 | |
155 | /* Configure TX */ | |
156 | EFX_POPULATE_DWORD_6(reg, | |
3e6c4538 BH |
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 | falcon_write(efx, ®, FR_AB_XM_TX_CFG); | |
8ceee660 BH |
164 | |
165 | /* Configure RX */ | |
166 | EFX_POPULATE_DWORD_5(reg, | |
3e6c4538 BH |
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 | falcon_write(efx, ®, FR_AB_XM_RX_CFG); | |
8ceee660 BH |
173 | |
174 | /* Set frame length */ | |
175 | max_frame_len = EFX_MAX_FRAME_LEN(efx->net_dev->mtu); | |
3e6c4538 BH |
176 | EFX_POPULATE_DWORD_1(reg, FRF_AB_XM_MAX_RX_FRM_SIZE, max_frame_len); |
177 | falcon_write(efx, ®, FR_AB_XM_RX_PARAM); | |
8ceee660 | 178 | EFX_POPULATE_DWORD_2(reg, |
3e6c4538 BH |
179 | FRF_AB_XM_MAX_TX_FRM_SIZE, max_frame_len, |
180 | FRF_AB_XM_TX_JUMBO_MODE, 1); | |
181 | falcon_write(efx, ®, FR_AB_XM_TX_PARAM); | |
8ceee660 BH |
182 | |
183 | EFX_POPULATE_DWORD_2(reg, | |
3e6c4538 BH |
184 | FRF_AB_XM_PAUSE_TIME, 0xfffe, /* MAX PAUSE TIME */ |
185 | FRF_AB_XM_DIS_FCNTL, !rx_fc); | |
186 | falcon_write(efx, ®, FR_AB_XM_FC); | |
8ceee660 BH |
187 | |
188 | /* Set MAC address */ | |
3e6c4538 BH |
189 | memcpy(®, &efx->net_dev->dev_addr[0], 4); |
190 | falcon_write(efx, ®, FR_AB_XM_ADR_LO); | |
191 | memcpy(®, &efx->net_dev->dev_addr[4], 2); | |
192 | falcon_write(efx, ®, FR_AB_XM_ADR_HI); | |
8ceee660 BH |
193 | } |
194 | ||
3273c2e8 BH |
195 | static void falcon_reconfigure_xgxs_core(struct efx_nic *efx) |
196 | { | |
c1e5fcc9 | 197 | efx_oword_t reg; |
dc8cfa55 BH |
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); | |
3273c2e8 BH |
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)) { | |
dc8cfa55 BH |
205 | bool old_xgmii_loopback, old_xgxs_loopback, old_xaui_loopback; |
206 | bool reset_xgxs; | |
3273c2e8 | 207 | |
3e6c4538 BH |
208 | falcon_read(efx, ®, 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); | |
3273c2e8 | 212 | |
3e6c4538 BH |
213 | falcon_read(efx, ®, FR_AB_XX_SD_CTL); |
214 | old_xaui_loopback = EFX_OWORD_FIELD(reg, FRF_AB_XX_LPBKA); | |
3273c2e8 BH |
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)); | |
8c8661e4 BH |
220 | |
221 | if (reset_xgxs) | |
222 | falcon_reset_xaui(efx); | |
3273c2e8 BH |
223 | } |
224 | ||
3e6c4538 BH |
225 | falcon_read(efx, ®, FR_AB_XX_CORE_STAT); |
226 | EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_FORCE_SIG, | |
3273c2e8 | 227 | (xgxs_loopback || xaui_loopback) ? |
3e6c4538 BH |
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 | falcon_write(efx, ®, FR_AB_XX_CORE_STAT); | |
232 | ||
233 | falcon_read(efx, ®, 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 | falcon_write(efx, ®, FR_AB_XX_SD_CTL); | |
3273c2e8 BH |
239 | } |
240 | ||
241 | ||
8ceee660 BH |
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 */ | |
177dfcd8 | 244 | static void falcon_check_xaui_link_up(struct efx_nic *efx, int tries) |
8ceee660 | 245 | { |
177dfcd8 | 246 | efx->mac_up = falcon_xaui_link_ok(efx); |
8ceee660 | 247 | |
3273c2e8 | 248 | if ((efx->loopback_mode == LOOPBACK_NETWORK) || |
f8b87c17 | 249 | efx_phy_mode_disabled(efx->phy_mode)) |
177dfcd8 BH |
250 | /* XAUI link is expected to be down */ |
251 | return; | |
8ceee660 | 252 | |
177dfcd8 BH |
253 | while (!efx->mac_up && tries) { |
254 | EFX_LOG(efx, "bashing xaui\n"); | |
91ad757c | 255 | falcon_reset_xaui(efx); |
8ceee660 | 256 | udelay(200); |
8ceee660 | 257 | |
177dfcd8 BH |
258 | efx->mac_up = falcon_xaui_link_ok(efx); |
259 | --tries; | |
260 | } | |
8ceee660 BH |
261 | } |
262 | ||
177dfcd8 | 263 | static void falcon_reconfigure_xmac(struct efx_nic *efx) |
8ceee660 | 264 | { |
dc8cfa55 | 265 | falcon_mask_status_intr(efx, false); |
8ceee660 | 266 | |
3273c2e8 | 267 | falcon_reconfigure_xgxs_core(efx); |
8ceee660 | 268 | falcon_reconfigure_xmac_core(efx); |
3273c2e8 | 269 | |
8ceee660 BH |
270 | falcon_reconfigure_mac_wrapper(efx); |
271 | ||
177dfcd8 BH |
272 | falcon_check_xaui_link_up(efx, 5); |
273 | falcon_mask_status_intr(efx, true); | |
8ceee660 BH |
274 | } |
275 | ||
177dfcd8 | 276 | static void falcon_update_stats_xmac(struct efx_nic *efx) |
8ceee660 BH |
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 = | |
c264361d BH |
334 | (mac_stats->tx_bytes - mac_stats->tx_bad_bytes - |
335 | mac_stats->tx_control * 64); | |
8ceee660 | 336 | mac_stats->rx_bad_bytes = |
c264361d BH |
337 | (mac_stats->rx_bytes - mac_stats->rx_good_bytes - |
338 | mac_stats->rx_control * 64); | |
8ceee660 BH |
339 | } |
340 | ||
766ca0fa | 341 | static void falcon_xmac_irq(struct efx_nic *efx) |
8ceee660 | 342 | { |
766ca0fa BH |
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 | } | |
8ceee660 | 356 | |
766ca0fa BH |
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; | |
3273c2e8 | 361 | |
dc8cfa55 | 362 | falcon_mask_status_intr(efx, false); |
766ca0fa BH |
363 | falcon_check_xaui_link_up(efx, 1); |
364 | falcon_mask_status_intr(efx, true); | |
8ceee660 BH |
365 | } |
366 | ||
177dfcd8 BH |
367 | struct efx_mac_operations falcon_xmac_operations = { |
368 | .reconfigure = falcon_reconfigure_xmac, | |
369 | .update_stats = falcon_update_stats_xmac, | |
766ca0fa BH |
370 | .irq = falcon_xmac_irq, |
371 | .poll = falcon_poll_xmac, | |
177dfcd8 | 372 | }; |