Commit | Line | Data |
---|---|---|
8ceee660 BH |
1 | /**************************************************************************** |
2 | * Driver for Solarflare Solarstorm network controllers and boards | |
3 | * Copyright 2005-2006 Fen Systems Ltd. | |
906bb26c | 4 | * Copyright 2006-2009 Solarflare Communications Inc. |
8ceee660 BH |
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" | |
744093c9 | 14 | #include "nic.h" |
3e6c4538 | 15 | #include "regs.h" |
12d00cad | 16 | #include "io.h" |
8ceee660 | 17 | #include "mac.h" |
8ceee660 | 18 | #include "mdio_10g.h" |
8ceee660 BH |
19 | #include "workarounds.h" |
20 | ||
8ceee660 BH |
21 | /************************************************************************** |
22 | * | |
23 | * MAC operations | |
24 | * | |
25 | *************************************************************************/ | |
8ceee660 BH |
26 | |
27 | /* Configure the XAUI driver that is an output from Falcon */ | |
b7b40eeb | 28 | void falcon_setup_xaui(struct efx_nic *efx) |
8ceee660 | 29 | { |
c1e5fcc9 | 30 | efx_oword_t sdctl, txdrv; |
8ceee660 BH |
31 | |
32 | /* Move the XAUI into low power, unless there is no PHY, in | |
33 | * which case the XAUI will have to drive a cable. */ | |
34 | if (efx->phy_type == PHY_TYPE_NONE) | |
35 | return; | |
36 | ||
12d00cad | 37 | efx_reado(efx, &sdctl, FR_AB_XX_SD_CTL); |
3e6c4538 BH |
38 | EFX_SET_OWORD_FIELD(sdctl, FRF_AB_XX_HIDRVD, FFE_AB_XX_SD_CTL_DRV_DEF); |
39 | EFX_SET_OWORD_FIELD(sdctl, FRF_AB_XX_LODRVD, FFE_AB_XX_SD_CTL_DRV_DEF); | |
40 | EFX_SET_OWORD_FIELD(sdctl, FRF_AB_XX_HIDRVC, FFE_AB_XX_SD_CTL_DRV_DEF); | |
41 | EFX_SET_OWORD_FIELD(sdctl, FRF_AB_XX_LODRVC, FFE_AB_XX_SD_CTL_DRV_DEF); | |
42 | EFX_SET_OWORD_FIELD(sdctl, FRF_AB_XX_HIDRVB, FFE_AB_XX_SD_CTL_DRV_DEF); | |
43 | EFX_SET_OWORD_FIELD(sdctl, FRF_AB_XX_LODRVB, FFE_AB_XX_SD_CTL_DRV_DEF); | |
44 | EFX_SET_OWORD_FIELD(sdctl, FRF_AB_XX_HIDRVA, FFE_AB_XX_SD_CTL_DRV_DEF); | |
45 | EFX_SET_OWORD_FIELD(sdctl, FRF_AB_XX_LODRVA, FFE_AB_XX_SD_CTL_DRV_DEF); | |
12d00cad | 46 | efx_writeo(efx, &sdctl, FR_AB_XX_SD_CTL); |
c1e5fcc9 BH |
47 | |
48 | EFX_POPULATE_OWORD_8(txdrv, | |
3e6c4538 BH |
49 | FRF_AB_XX_DEQD, FFE_AB_XX_TXDRV_DEQ_DEF, |
50 | FRF_AB_XX_DEQC, FFE_AB_XX_TXDRV_DEQ_DEF, | |
51 | FRF_AB_XX_DEQB, FFE_AB_XX_TXDRV_DEQ_DEF, | |
52 | FRF_AB_XX_DEQA, FFE_AB_XX_TXDRV_DEQ_DEF, | |
53 | FRF_AB_XX_DTXD, FFE_AB_XX_TXDRV_DTX_DEF, | |
54 | FRF_AB_XX_DTXC, FFE_AB_XX_TXDRV_DTX_DEF, | |
55 | FRF_AB_XX_DTXB, FFE_AB_XX_TXDRV_DTX_DEF, | |
56 | FRF_AB_XX_DTXA, FFE_AB_XX_TXDRV_DTX_DEF); | |
12d00cad | 57 | efx_writeo(efx, &txdrv, FR_AB_XX_TXDRV_CTL); |
8ceee660 BH |
58 | } |
59 | ||
ef08af03 | 60 | int falcon_reset_xaui(struct efx_nic *efx) |
8ceee660 | 61 | { |
55edc6e6 | 62 | struct falcon_nic_data *nic_data = efx->nic_data; |
c1e5fcc9 | 63 | efx_oword_t reg; |
8ceee660 BH |
64 | int count; |
65 | ||
55edc6e6 BH |
66 | /* Don't fetch MAC statistics over an XMAC reset */ |
67 | WARN_ON(nic_data->stats_disable_count == 0); | |
68 | ||
d4ec09ac | 69 | /* Start reset sequence */ |
80cb9a0f | 70 | EFX_POPULATE_OWORD_1(reg, FRF_AB_XX_RST_XX_EN, 1); |
12d00cad | 71 | efx_writeo(efx, ®, FR_AB_XX_PWR_RST); |
8ceee660 | 72 | |
d4ec09ac BH |
73 | /* Wait up to 10 ms for completion, then reinitialise */ |
74 | for (count = 0; count < 1000; count++) { | |
12d00cad | 75 | efx_reado(efx, ®, FR_AB_XX_PWR_RST); |
3e6c4538 BH |
76 | if (EFX_OWORD_FIELD(reg, FRF_AB_XX_RST_XX_EN) == 0 && |
77 | EFX_OWORD_FIELD(reg, FRF_AB_XX_SD_RST_ACT) == 0) { | |
8ceee660 BH |
78 | falcon_setup_xaui(efx); |
79 | return 0; | |
80 | } | |
81 | udelay(10); | |
82 | } | |
62776d03 BH |
83 | netif_err(efx, hw, efx->net_dev, |
84 | "timed out waiting for XAUI/XGXS reset\n"); | |
8ceee660 BH |
85 | return -ETIMEDOUT; |
86 | } | |
87 | ||
ef524f2e | 88 | static void falcon_ack_status_intr(struct efx_nic *efx) |
8ceee660 | 89 | { |
cef68bde | 90 | struct falcon_nic_data *nic_data = efx->nic_data; |
c1e5fcc9 | 91 | efx_oword_t reg; |
8ceee660 | 92 | |
daeda630 | 93 | if ((efx_nic_rev(efx) != EFX_REV_FALCON_B0) || LOOPBACK_INTERNAL(efx)) |
177dfcd8 | 94 | return; |
8ceee660 | 95 | |
ef524f2e | 96 | /* We expect xgmii faults if the wireside link is down */ |
eb50c0d6 | 97 | if (!EFX_WORKAROUND_5147(efx) || !efx->link_state.up) |
177dfcd8 | 98 | return; |
8ceee660 | 99 | |
177dfcd8 BH |
100 | /* We can only use this interrupt to signal the negative edge of |
101 | * xaui_align [we have to poll the positive edge]. */ | |
cef68bde | 102 | if (nic_data->xmac_poll_required) |
8ceee660 BH |
103 | return; |
104 | ||
ef524f2e | 105 | efx_reado(efx, ®, FR_AB_XM_MGT_INT_MSK); |
8ceee660 BH |
106 | } |
107 | ||
a355020a | 108 | static bool falcon_xgxs_link_ok(struct efx_nic *efx) |
8ceee660 | 109 | { |
c1e5fcc9 | 110 | efx_oword_t reg; |
dc8cfa55 BH |
111 | bool align_done, link_ok = false; |
112 | int sync_status; | |
8ceee660 BH |
113 | |
114 | /* Read link status */ | |
12d00cad | 115 | efx_reado(efx, ®, FR_AB_XX_CORE_STAT); |
8ceee660 | 116 | |
3e6c4538 BH |
117 | align_done = EFX_OWORD_FIELD(reg, FRF_AB_XX_ALIGN_DONE); |
118 | sync_status = EFX_OWORD_FIELD(reg, FRF_AB_XX_SYNC_STAT); | |
119 | if (align_done && (sync_status == FFE_AB_XX_STAT_ALL_LANES)) | |
dc8cfa55 | 120 | link_ok = true; |
8ceee660 BH |
121 | |
122 | /* Clear link status ready for next read */ | |
3e6c4538 BH |
123 | EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_COMMA_DET, FFE_AB_XX_STAT_ALL_LANES); |
124 | EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_CHAR_ERR, FFE_AB_XX_STAT_ALL_LANES); | |
125 | EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_DISPERR, FFE_AB_XX_STAT_ALL_LANES); | |
12d00cad | 126 | efx_writeo(efx, ®, FR_AB_XX_CORE_STAT); |
8ceee660 | 127 | |
8ceee660 BH |
128 | return link_ok; |
129 | } | |
130 | ||
a355020a BH |
131 | static bool falcon_xmac_link_ok(struct efx_nic *efx) |
132 | { | |
133 | /* | |
134 | * Check MAC's XGXS link status except when using XGMII loopback | |
135 | * which bypasses the XGXS block. | |
136 | * If possible, check PHY's XGXS link status except when using | |
137 | * MAC loopback. | |
138 | */ | |
139 | return (efx->loopback_mode == LOOPBACK_XGMII || | |
140 | falcon_xgxs_link_ok(efx)) && | |
141 | (!(efx->mdio.mmds & (1 << MDIO_MMD_PHYXS)) || | |
142 | LOOPBACK_INTERNAL(efx) || | |
143 | efx_mdio_phyxgxs_lane_sync(efx)); | |
144 | } | |
145 | ||
d215697f | 146 | static void falcon_reconfigure_xmac_core(struct efx_nic *efx) |
8ceee660 BH |
147 | { |
148 | unsigned int max_frame_len; | |
c1e5fcc9 | 149 | efx_oword_t reg; |
eb50c0d6 | 150 | bool rx_fc = !!(efx->link_state.fc & EFX_FC_RX); |
4b0d29dc | 151 | bool tx_fc = !!(efx->link_state.fc & EFX_FC_TX); |
8ceee660 BH |
152 | |
153 | /* Configure MAC - cut-thru mode is hard wired on */ | |
80cb9a0f | 154 | EFX_POPULATE_OWORD_3(reg, |
3e6c4538 BH |
155 | FRF_AB_XM_RX_JUMBO_MODE, 1, |
156 | FRF_AB_XM_TX_STAT_EN, 1, | |
157 | FRF_AB_XM_RX_STAT_EN, 1); | |
12d00cad | 158 | efx_writeo(efx, ®, FR_AB_XM_GLB_CFG); |
8ceee660 BH |
159 | |
160 | /* Configure TX */ | |
80cb9a0f | 161 | EFX_POPULATE_OWORD_6(reg, |
3e6c4538 BH |
162 | FRF_AB_XM_TXEN, 1, |
163 | FRF_AB_XM_TX_PRMBL, 1, | |
164 | FRF_AB_XM_AUTO_PAD, 1, | |
165 | FRF_AB_XM_TXCRC, 1, | |
4b0d29dc | 166 | FRF_AB_XM_FCNTL, tx_fc, |
3e6c4538 | 167 | FRF_AB_XM_IPG, 0x3); |
12d00cad | 168 | efx_writeo(efx, ®, FR_AB_XM_TX_CFG); |
8ceee660 BH |
169 | |
170 | /* Configure RX */ | |
80cb9a0f | 171 | EFX_POPULATE_OWORD_5(reg, |
3e6c4538 BH |
172 | FRF_AB_XM_RXEN, 1, |
173 | FRF_AB_XM_AUTO_DEPAD, 0, | |
174 | FRF_AB_XM_ACPT_ALL_MCAST, 1, | |
175 | FRF_AB_XM_ACPT_ALL_UCAST, efx->promiscuous, | |
176 | FRF_AB_XM_PASS_CRC_ERR, 1); | |
12d00cad | 177 | efx_writeo(efx, ®, FR_AB_XM_RX_CFG); |
8ceee660 BH |
178 | |
179 | /* Set frame length */ | |
180 | max_frame_len = EFX_MAX_FRAME_LEN(efx->net_dev->mtu); | |
80cb9a0f | 181 | EFX_POPULATE_OWORD_1(reg, FRF_AB_XM_MAX_RX_FRM_SIZE, max_frame_len); |
12d00cad | 182 | efx_writeo(efx, ®, FR_AB_XM_RX_PARAM); |
80cb9a0f | 183 | EFX_POPULATE_OWORD_2(reg, |
3e6c4538 BH |
184 | FRF_AB_XM_MAX_TX_FRM_SIZE, max_frame_len, |
185 | FRF_AB_XM_TX_JUMBO_MODE, 1); | |
12d00cad | 186 | efx_writeo(efx, ®, FR_AB_XM_TX_PARAM); |
8ceee660 | 187 | |
80cb9a0f | 188 | EFX_POPULATE_OWORD_2(reg, |
3e6c4538 BH |
189 | FRF_AB_XM_PAUSE_TIME, 0xfffe, /* MAX PAUSE TIME */ |
190 | FRF_AB_XM_DIS_FCNTL, !rx_fc); | |
12d00cad | 191 | efx_writeo(efx, ®, FR_AB_XM_FC); |
8ceee660 BH |
192 | |
193 | /* Set MAC address */ | |
3e6c4538 | 194 | memcpy(®, &efx->net_dev->dev_addr[0], 4); |
12d00cad | 195 | efx_writeo(efx, ®, FR_AB_XM_ADR_LO); |
3e6c4538 | 196 | memcpy(®, &efx->net_dev->dev_addr[4], 2); |
12d00cad | 197 | efx_writeo(efx, ®, FR_AB_XM_ADR_HI); |
8ceee660 BH |
198 | } |
199 | ||
3273c2e8 BH |
200 | static void falcon_reconfigure_xgxs_core(struct efx_nic *efx) |
201 | { | |
c1e5fcc9 | 202 | efx_oword_t reg; |
dc8cfa55 BH |
203 | bool xgxs_loopback = (efx->loopback_mode == LOOPBACK_XGXS); |
204 | bool xaui_loopback = (efx->loopback_mode == LOOPBACK_XAUI); | |
205 | bool xgmii_loopback = (efx->loopback_mode == LOOPBACK_XGMII); | |
3273c2e8 BH |
206 | |
207 | /* XGXS block is flaky and will need to be reset if moving | |
208 | * into our out of XGMII, XGXS or XAUI loopbacks. */ | |
209 | if (EFX_WORKAROUND_5147(efx)) { | |
dc8cfa55 BH |
210 | bool old_xgmii_loopback, old_xgxs_loopback, old_xaui_loopback; |
211 | bool reset_xgxs; | |
3273c2e8 | 212 | |
12d00cad | 213 | efx_reado(efx, ®, FR_AB_XX_CORE_STAT); |
3e6c4538 BH |
214 | old_xgxs_loopback = EFX_OWORD_FIELD(reg, FRF_AB_XX_XGXS_LB_EN); |
215 | old_xgmii_loopback = | |
216 | EFX_OWORD_FIELD(reg, FRF_AB_XX_XGMII_LB_EN); | |
3273c2e8 | 217 | |
12d00cad | 218 | efx_reado(efx, ®, FR_AB_XX_SD_CTL); |
3e6c4538 | 219 | old_xaui_loopback = EFX_OWORD_FIELD(reg, FRF_AB_XX_LPBKA); |
3273c2e8 BH |
220 | |
221 | /* The PHY driver may have turned XAUI off */ | |
222 | reset_xgxs = ((xgxs_loopback != old_xgxs_loopback) || | |
223 | (xaui_loopback != old_xaui_loopback) || | |
224 | (xgmii_loopback != old_xgmii_loopback)); | |
8c8661e4 BH |
225 | |
226 | if (reset_xgxs) | |
227 | falcon_reset_xaui(efx); | |
3273c2e8 BH |
228 | } |
229 | ||
12d00cad | 230 | efx_reado(efx, ®, FR_AB_XX_CORE_STAT); |
3e6c4538 | 231 | EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_FORCE_SIG, |
3273c2e8 | 232 | (xgxs_loopback || xaui_loopback) ? |
3e6c4538 BH |
233 | FFE_AB_XX_FORCE_SIG_ALL_LANES : 0); |
234 | EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_XGXS_LB_EN, xgxs_loopback); | |
235 | EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_XGMII_LB_EN, xgmii_loopback); | |
12d00cad | 236 | efx_writeo(efx, ®, FR_AB_XX_CORE_STAT); |
3e6c4538 | 237 | |
12d00cad | 238 | efx_reado(efx, ®, FR_AB_XX_SD_CTL); |
3e6c4538 BH |
239 | EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_LPBKD, xaui_loopback); |
240 | EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_LPBKC, xaui_loopback); | |
241 | EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_LPBKB, xaui_loopback); | |
242 | EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_LPBKA, xaui_loopback); | |
12d00cad | 243 | efx_writeo(efx, ®, FR_AB_XX_SD_CTL); |
3273c2e8 BH |
244 | } |
245 | ||
246 | ||
9007b9fa | 247 | /* Try to bring up the Falcon side of the Falcon-Phy XAUI link */ |
a355020a | 248 | static bool falcon_xmac_link_ok_retry(struct efx_nic *efx, int tries) |
8ceee660 | 249 | { |
a355020a | 250 | bool mac_up = falcon_xmac_link_ok(efx); |
8ceee660 | 251 | |
e58f69f4 | 252 | if (LOOPBACK_MASK(efx) & LOOPBACKS_EXTERNAL(efx) & LOOPBACKS_WS || |
f8b87c17 | 253 | efx_phy_mode_disabled(efx->phy_mode)) |
177dfcd8 | 254 | /* XAUI link is expected to be down */ |
9007b9fa | 255 | return mac_up; |
8ceee660 | 256 | |
55edc6e6 BH |
257 | falcon_stop_nic_stats(efx); |
258 | ||
9007b9fa | 259 | while (!mac_up && tries) { |
62776d03 | 260 | netif_dbg(efx, hw, efx->net_dev, "bashing xaui\n"); |
91ad757c | 261 | falcon_reset_xaui(efx); |
8ceee660 | 262 | udelay(200); |
8ceee660 | 263 | |
a355020a | 264 | mac_up = falcon_xmac_link_ok(efx); |
177dfcd8 BH |
265 | --tries; |
266 | } | |
55edc6e6 BH |
267 | |
268 | falcon_start_nic_stats(efx); | |
9007b9fa BH |
269 | |
270 | return mac_up; | |
271 | } | |
272 | ||
273 | static bool falcon_xmac_check_fault(struct efx_nic *efx) | |
274 | { | |
a355020a | 275 | return !falcon_xmac_link_ok_retry(efx, 5); |
8ceee660 BH |
276 | } |
277 | ||
d3245b28 | 278 | static int falcon_reconfigure_xmac(struct efx_nic *efx) |
8ceee660 | 279 | { |
cef68bde BH |
280 | struct falcon_nic_data *nic_data = efx->nic_data; |
281 | ||
3273c2e8 | 282 | falcon_reconfigure_xgxs_core(efx); |
8ceee660 | 283 | falcon_reconfigure_xmac_core(efx); |
3273c2e8 | 284 | |
8ceee660 BH |
285 | falcon_reconfigure_mac_wrapper(efx); |
286 | ||
cef68bde | 287 | nic_data->xmac_poll_required = !falcon_xmac_link_ok_retry(efx, 5); |
ef524f2e | 288 | falcon_ack_status_intr(efx); |
d3245b28 BH |
289 | |
290 | return 0; | |
8ceee660 BH |
291 | } |
292 | ||
177dfcd8 | 293 | static void falcon_update_stats_xmac(struct efx_nic *efx) |
8ceee660 BH |
294 | { |
295 | struct efx_mac_stats *mac_stats = &efx->mac_stats; | |
8ceee660 BH |
296 | |
297 | /* Update MAC stats from DMAed values */ | |
298 | FALCON_STAT(efx, XgRxOctets, rx_bytes); | |
299 | FALCON_STAT(efx, XgRxOctetsOK, rx_good_bytes); | |
300 | FALCON_STAT(efx, XgRxPkts, rx_packets); | |
301 | FALCON_STAT(efx, XgRxPktsOK, rx_good); | |
302 | FALCON_STAT(efx, XgRxBroadcastPkts, rx_broadcast); | |
303 | FALCON_STAT(efx, XgRxMulticastPkts, rx_multicast); | |
304 | FALCON_STAT(efx, XgRxUnicastPkts, rx_unicast); | |
305 | FALCON_STAT(efx, XgRxUndersizePkts, rx_lt64); | |
306 | FALCON_STAT(efx, XgRxOversizePkts, rx_gtjumbo); | |
307 | FALCON_STAT(efx, XgRxJabberPkts, rx_bad_gtjumbo); | |
308 | FALCON_STAT(efx, XgRxUndersizeFCSerrorPkts, rx_bad_lt64); | |
309 | FALCON_STAT(efx, XgRxDropEvents, rx_overflow); | |
310 | FALCON_STAT(efx, XgRxFCSerrorPkts, rx_bad); | |
311 | FALCON_STAT(efx, XgRxAlignError, rx_align_error); | |
312 | FALCON_STAT(efx, XgRxSymbolError, rx_symbol_error); | |
313 | FALCON_STAT(efx, XgRxInternalMACError, rx_internal_error); | |
314 | FALCON_STAT(efx, XgRxControlPkts, rx_control); | |
315 | FALCON_STAT(efx, XgRxPausePkts, rx_pause); | |
316 | FALCON_STAT(efx, XgRxPkts64Octets, rx_64); | |
317 | FALCON_STAT(efx, XgRxPkts65to127Octets, rx_65_to_127); | |
318 | FALCON_STAT(efx, XgRxPkts128to255Octets, rx_128_to_255); | |
319 | FALCON_STAT(efx, XgRxPkts256to511Octets, rx_256_to_511); | |
320 | FALCON_STAT(efx, XgRxPkts512to1023Octets, rx_512_to_1023); | |
321 | FALCON_STAT(efx, XgRxPkts1024to15xxOctets, rx_1024_to_15xx); | |
322 | FALCON_STAT(efx, XgRxPkts15xxtoMaxOctets, rx_15xx_to_jumbo); | |
323 | FALCON_STAT(efx, XgRxLengthError, rx_length_error); | |
324 | FALCON_STAT(efx, XgTxPkts, tx_packets); | |
325 | FALCON_STAT(efx, XgTxOctets, tx_bytes); | |
326 | FALCON_STAT(efx, XgTxMulticastPkts, tx_multicast); | |
327 | FALCON_STAT(efx, XgTxBroadcastPkts, tx_broadcast); | |
328 | FALCON_STAT(efx, XgTxUnicastPkts, tx_unicast); | |
329 | FALCON_STAT(efx, XgTxControlPkts, tx_control); | |
330 | FALCON_STAT(efx, XgTxPausePkts, tx_pause); | |
331 | FALCON_STAT(efx, XgTxPkts64Octets, tx_64); | |
332 | FALCON_STAT(efx, XgTxPkts65to127Octets, tx_65_to_127); | |
333 | FALCON_STAT(efx, XgTxPkts128to255Octets, tx_128_to_255); | |
334 | FALCON_STAT(efx, XgTxPkts256to511Octets, tx_256_to_511); | |
335 | FALCON_STAT(efx, XgTxPkts512to1023Octets, tx_512_to_1023); | |
336 | FALCON_STAT(efx, XgTxPkts1024to15xxOctets, tx_1024_to_15xx); | |
337 | FALCON_STAT(efx, XgTxPkts1519toMaxOctets, tx_15xx_to_jumbo); | |
338 | FALCON_STAT(efx, XgTxUndersizePkts, tx_lt64); | |
339 | FALCON_STAT(efx, XgTxOversizePkts, tx_gtjumbo); | |
340 | FALCON_STAT(efx, XgTxNonTcpUdpPkt, tx_non_tcpudp); | |
341 | FALCON_STAT(efx, XgTxMacSrcErrPkt, tx_mac_src_error); | |
342 | FALCON_STAT(efx, XgTxIpSrcErrPkt, tx_ip_src_error); | |
343 | ||
344 | /* Update derived statistics */ | |
345 | mac_stats->tx_good_bytes = | |
c264361d BH |
346 | (mac_stats->tx_bytes - mac_stats->tx_bad_bytes - |
347 | mac_stats->tx_control * 64); | |
8ceee660 | 348 | mac_stats->rx_bad_bytes = |
c264361d BH |
349 | (mac_stats->rx_bytes - mac_stats->rx_good_bytes - |
350 | mac_stats->rx_control * 64); | |
8ceee660 BH |
351 | } |
352 | ||
9007b9fa | 353 | void falcon_poll_xmac(struct efx_nic *efx) |
766ca0fa | 354 | { |
cef68bde BH |
355 | struct falcon_nic_data *nic_data = efx->nic_data; |
356 | ||
9007b9fa | 357 | if (!EFX_WORKAROUND_5147(efx) || !efx->link_state.up || |
cef68bde | 358 | !nic_data->xmac_poll_required) |
766ca0fa | 359 | return; |
3273c2e8 | 360 | |
cef68bde | 361 | nic_data->xmac_poll_required = !falcon_xmac_link_ok_retry(efx, 1); |
ef524f2e | 362 | falcon_ack_status_intr(efx); |
8ceee660 BH |
363 | } |
364 | ||
177dfcd8 BH |
365 | struct efx_mac_operations falcon_xmac_operations = { |
366 | .reconfigure = falcon_reconfigure_xmac, | |
367 | .update_stats = falcon_update_stats_xmac, | |
9007b9fa | 368 | .check_fault = falcon_xmac_check_fault, |
177dfcd8 | 369 | }; |