1/**************************************************************************** 2 * Driver for Solarflare Solarstorm network controllers and boards 3 * Copyright 2005-2006 Fen Systems Ltd. 4 * Copyright 2006-2009 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 "nic.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 */ 29void 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 61int falcon_reset_xaui(struct efx_nic *efx) 62{ 63 struct falcon_nic_data *nic_data = efx->nic_data; 64 efx_oword_t reg; 65 int count; 66 67 /* Don't fetch MAC statistics over an XMAC reset */ 68 WARN_ON(nic_data->stats_disable_count == 0); 69 70 /* Start reset sequence */ 71 EFX_POPULATE_OWORD_1(reg, FRF_AB_XX_RST_XX_EN, 1); 72 efx_writeo(efx, ®, FR_AB_XX_PWR_RST); 73 74 /* Wait up to 10 ms for completion, then reinitialise */ 75 for (count = 0; count < 1000; count++) { 76 efx_reado(efx, ®, FR_AB_XX_PWR_RST); 77 if (EFX_OWORD_FIELD(reg, FRF_AB_XX_RST_XX_EN) == 0 && 78 EFX_OWORD_FIELD(reg, FRF_AB_XX_SD_RST_ACT) == 0) { 79 falcon_setup_xaui(efx); 80 return 0; 81 } 82 udelay(10); 83 } 84 netif_err(efx, hw, efx->net_dev, 85 "timed out waiting for XAUI/XGXS reset\n"); 86 return -ETIMEDOUT; 87} 88 89static void falcon_ack_status_intr(struct efx_nic *efx) 90{ 91 efx_oword_t reg; 92 93 if ((efx_nic_rev(efx) != EFX_REV_FALCON_B0) || LOOPBACK_INTERNAL(efx)) 94 return; 95 96 /* We expect xgmii faults if the wireside link is down */ 97 if (!EFX_WORKAROUND_5147(efx) || !efx->link_state.up) 98 return; 99 100 /* We can only use this interrupt to signal the negative edge of 101 * xaui_align [we have to poll the positive edge]. */ 102 if (efx->xmac_poll_required) 103 return; 104 105 efx_reado(efx, ®, FR_AB_XM_MGT_INT_MSK); 106} 107 108static bool falcon_xgxs_link_ok(struct efx_nic *efx) 109{ 110 efx_oword_t reg; 111 bool align_done, link_ok = false; 112 int sync_status; 113 114 /* Read link status */ 115 efx_reado(efx, ®, FR_AB_XX_CORE_STAT); 116 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)) 120 link_ok = true; 121 122 /* Clear link status ready for next read */ 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); 126 efx_writeo(efx, ®, FR_AB_XX_CORE_STAT); 127 128 return link_ok; 129} 130 131static 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 146void falcon_reconfigure_xmac_core(struct efx_nic *efx) 147{ 148 unsigned int max_frame_len; 149 efx_oword_t reg; 150 bool rx_fc = !!(efx->link_state.fc & EFX_FC_RX); 151 bool tx_fc = !!(efx->link_state.fc & EFX_FC_TX); 152 153 /* Configure MAC - cut-thru mode is hard wired on */ 154 EFX_POPULATE_OWORD_3(reg, 155 FRF_AB_XM_RX_JUMBO_MODE, 1, 156 FRF_AB_XM_TX_STAT_EN, 1, 157 FRF_AB_XM_RX_STAT_EN, 1); 158 efx_writeo(efx, ®, FR_AB_XM_GLB_CFG); 159 160 /* Configure TX */ 161 EFX_POPULATE_OWORD_6(reg, 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, 166 FRF_AB_XM_FCNTL, tx_fc, 167 FRF_AB_XM_IPG, 0x3); 168 efx_writeo(efx, ®, FR_AB_XM_TX_CFG); 169 170 /* Configure RX */ 171 EFX_POPULATE_OWORD_5(reg, 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); 177 efx_writeo(efx, ®, FR_AB_XM_RX_CFG); 178 179 /* Set frame length */ 180 max_frame_len = EFX_MAX_FRAME_LEN(efx->net_dev->mtu); 181 EFX_POPULATE_OWORD_1(reg, FRF_AB_XM_MAX_RX_FRM_SIZE, max_frame_len); 182 efx_writeo(efx, ®, FR_AB_XM_RX_PARAM); 183 EFX_POPULATE_OWORD_2(reg, 184 FRF_AB_XM_MAX_TX_FRM_SIZE, max_frame_len, 185 FRF_AB_XM_TX_JUMBO_MODE, 1); 186 efx_writeo(efx, ®, FR_AB_XM_TX_PARAM); 187 188 EFX_POPULATE_OWORD_2(reg, 189 FRF_AB_XM_PAUSE_TIME, 0xfffe, /* MAX PAUSE TIME */ 190 FRF_AB_XM_DIS_FCNTL, !rx_fc); 191 efx_writeo(efx, ®, FR_AB_XM_FC); 192 193 /* Set MAC address */ 194 memcpy(®, &efx->net_dev->dev_addr[0], 4); 195 efx_writeo(efx, ®, FR_AB_XM_ADR_LO); 196 memcpy(®, &efx->net_dev->dev_addr[4], 2); 197 efx_writeo(efx, ®, FR_AB_XM_ADR_HI); 198} 199 200static void falcon_reconfigure_xgxs_core(struct efx_nic *efx) 201{ 202 efx_oword_t reg; 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); 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)) { 210 bool old_xgmii_loopback, old_xgxs_loopback, old_xaui_loopback; 211 bool reset_xgxs; 212 213 efx_reado(efx, ®, FR_AB_XX_CORE_STAT); 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); 217 218 efx_reado(efx, ®, FR_AB_XX_SD_CTL); 219 old_xaui_loopback = EFX_OWORD_FIELD(reg, FRF_AB_XX_LPBKA); 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)); 225 226 if (reset_xgxs) 227 falcon_reset_xaui(efx); 228 } 229 230 efx_reado(efx, ®, FR_AB_XX_CORE_STAT); 231 EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_FORCE_SIG, 232 (xgxs_loopback || xaui_loopback) ? 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); 236 efx_writeo(efx, ®, FR_AB_XX_CORE_STAT); 237 238 efx_reado(efx, ®, FR_AB_XX_SD_CTL); 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); 243 efx_writeo(efx, ®, FR_AB_XX_SD_CTL); 244} 245 246 247/* Try to bring up the Falcon side of the Falcon-Phy XAUI link */ 248static bool falcon_xmac_link_ok_retry(struct efx_nic *efx, int tries) 249{ 250 bool mac_up = falcon_xmac_link_ok(efx); 251 252 if (LOOPBACK_MASK(efx) & LOOPBACKS_EXTERNAL(efx) & LOOPBACKS_WS || 253 efx_phy_mode_disabled(efx->phy_mode)) 254 /* XAUI link is expected to be down */ 255 return mac_up; 256 257 falcon_stop_nic_stats(efx); 258 259 while (!mac_up && tries) { 260 netif_dbg(efx, hw, efx->net_dev, "bashing xaui\n"); 261 falcon_reset_xaui(efx); 262 udelay(200); 263 264 mac_up = falcon_xmac_link_ok(efx); 265 --tries; 266 } 267 268 falcon_start_nic_stats(efx); 269 270 return mac_up; 271} 272 273static bool falcon_xmac_check_fault(struct efx_nic *efx) 274{ 275 return !falcon_xmac_link_ok_retry(efx, 5); 276} 277 278static int falcon_reconfigure_xmac(struct efx_nic *efx) 279{ 280 falcon_reconfigure_xgxs_core(efx); 281 falcon_reconfigure_xmac_core(efx); 282 283 falcon_reconfigure_mac_wrapper(efx); 284 285 efx->xmac_poll_required = !falcon_xmac_link_ok_retry(efx, 5); 286 falcon_ack_status_intr(efx); 287 288 return 0; 289} 290 291static void falcon_update_stats_xmac(struct efx_nic *efx) 292{ 293 struct efx_mac_stats *mac_stats = &efx->mac_stats; 294 295 /* Update MAC stats from DMAed values */ 296 FALCON_STAT(efx, XgRxOctets, rx_bytes); 297 FALCON_STAT(efx, XgRxOctetsOK, rx_good_bytes); 298 FALCON_STAT(efx, XgRxPkts, rx_packets); 299 FALCON_STAT(efx, XgRxPktsOK, rx_good); 300 FALCON_STAT(efx, XgRxBroadcastPkts, rx_broadcast); 301 FALCON_STAT(efx, XgRxMulticastPkts, rx_multicast); 302 FALCON_STAT(efx, XgRxUnicastPkts, rx_unicast); 303 FALCON_STAT(efx, XgRxUndersizePkts, rx_lt64); 304 FALCON_STAT(efx, XgRxOversizePkts, rx_gtjumbo); 305 FALCON_STAT(efx, XgRxJabberPkts, rx_bad_gtjumbo); 306 FALCON_STAT(efx, XgRxUndersizeFCSerrorPkts, rx_bad_lt64); 307 FALCON_STAT(efx, XgRxDropEvents, rx_overflow); 308 FALCON_STAT(efx, XgRxFCSerrorPkts, rx_bad); 309 FALCON_STAT(efx, XgRxAlignError, rx_align_error); 310 FALCON_STAT(efx, XgRxSymbolError, rx_symbol_error); 311 FALCON_STAT(efx, XgRxInternalMACError, rx_internal_error); 312 FALCON_STAT(efx, XgRxControlPkts, rx_control); 313 FALCON_STAT(efx, XgRxPausePkts, rx_pause); 314 FALCON_STAT(efx, XgRxPkts64Octets, rx_64); 315 FALCON_STAT(efx, XgRxPkts65to127Octets, rx_65_to_127); 316 FALCON_STAT(efx, XgRxPkts128to255Octets, rx_128_to_255); 317 FALCON_STAT(efx, XgRxPkts256to511Octets, rx_256_to_511); 318 FALCON_STAT(efx, XgRxPkts512to1023Octets, rx_512_to_1023); 319 FALCON_STAT(efx, XgRxPkts1024to15xxOctets, rx_1024_to_15xx); 320 FALCON_STAT(efx, XgRxPkts15xxtoMaxOctets, rx_15xx_to_jumbo); 321 FALCON_STAT(efx, XgRxLengthError, rx_length_error); 322 FALCON_STAT(efx, XgTxPkts, tx_packets); 323 FALCON_STAT(efx, XgTxOctets, tx_bytes); 324 FALCON_STAT(efx, XgTxMulticastPkts, tx_multicast); 325 FALCON_STAT(efx, XgTxBroadcastPkts, tx_broadcast); 326 FALCON_STAT(efx, XgTxUnicastPkts, tx_unicast); 327 FALCON_STAT(efx, XgTxControlPkts, tx_control); 328 FALCON_STAT(efx, XgTxPausePkts, tx_pause); 329 FALCON_STAT(efx, XgTxPkts64Octets, tx_64); 330 FALCON_STAT(efx, XgTxPkts65to127Octets, tx_65_to_127); 331 FALCON_STAT(efx, XgTxPkts128to255Octets, tx_128_to_255); 332 FALCON_STAT(efx, XgTxPkts256to511Octets, tx_256_to_511); 333 FALCON_STAT(efx, XgTxPkts512to1023Octets, tx_512_to_1023); 334 FALCON_STAT(efx, XgTxPkts1024to15xxOctets, tx_1024_to_15xx); 335 FALCON_STAT(efx, XgTxPkts1519toMaxOctets, tx_15xx_to_jumbo); 336 FALCON_STAT(efx, XgTxUndersizePkts, tx_lt64); 337 FALCON_STAT(efx, XgTxOversizePkts, tx_gtjumbo); 338 FALCON_STAT(efx, XgTxNonTcpUdpPkt, tx_non_tcpudp); 339 FALCON_STAT(efx, XgTxMacSrcErrPkt, tx_mac_src_error); 340 FALCON_STAT(efx, XgTxIpSrcErrPkt, tx_ip_src_error); 341 342 /* Update derived statistics */ 343 mac_stats->tx_good_bytes = 344 (mac_stats->tx_bytes - mac_stats->tx_bad_bytes - 345 mac_stats->tx_control * 64); 346 mac_stats->rx_bad_bytes = 347 (mac_stats->rx_bytes - mac_stats->rx_good_bytes - 348 mac_stats->rx_control * 64); 349} 350 351void falcon_poll_xmac(struct efx_nic *efx) 352{ 353 if (!EFX_WORKAROUND_5147(efx) || !efx->link_state.up || 354 !efx->xmac_poll_required) 355 return; 356 357 efx->xmac_poll_required = !falcon_xmac_link_ok_retry(efx, 1); 358 falcon_ack_status_intr(efx); 359} 360 361struct efx_mac_operations falcon_xmac_operations = { 362 .reconfigure = falcon_reconfigure_xmac, 363 .update_stats = falcon_update_stats_xmac, 364 .check_fault = falcon_xmac_check_fault, 365}; 366