Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.34-rc3 374 lines 12 kB view raw
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 */ 29static 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 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, &reg, 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, &reg, 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 EFX_ERR(efx, "timed out waiting for XAUI/XGXS reset\n"); 85 return -ETIMEDOUT; 86} 87 88static void falcon_mask_status_intr(struct efx_nic *efx, bool enable) 89{ 90 efx_oword_t reg; 91 92 if ((efx_nic_rev(efx) != EFX_REV_FALCON_B0) || LOOPBACK_INTERNAL(efx)) 93 return; 94 95 /* We expect xgmii faults if the wireside link is up */ 96 if (!EFX_WORKAROUND_5147(efx) || !efx->link_state.up) 97 return; 98 99 /* We can only use this interrupt to signal the negative edge of 100 * xaui_align [we have to poll the positive edge]. */ 101 if (efx->xmac_poll_required) 102 return; 103 104 /* Flush the ISR */ 105 if (enable) 106 efx_reado(efx, &reg, FR_AB_XM_MGT_INT_MSK); 107 108 EFX_POPULATE_OWORD_2(reg, 109 FRF_AB_XM_MSK_RMTFLT, !enable, 110 FRF_AB_XM_MSK_LCLFLT, !enable); 111 efx_writeo(efx, &reg, FR_AB_XM_MGT_INT_MASK); 112} 113 114static bool falcon_xgxs_link_ok(struct efx_nic *efx) 115{ 116 efx_oword_t reg; 117 bool align_done, link_ok = false; 118 int sync_status; 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 return link_ok; 135} 136 137static bool falcon_xmac_link_ok(struct efx_nic *efx) 138{ 139 /* 140 * Check MAC's XGXS link status except when using XGMII loopback 141 * which bypasses the XGXS block. 142 * If possible, check PHY's XGXS link status except when using 143 * MAC loopback. 144 */ 145 return (efx->loopback_mode == LOOPBACK_XGMII || 146 falcon_xgxs_link_ok(efx)) && 147 (!(efx->mdio.mmds & (1 << MDIO_MMD_PHYXS)) || 148 LOOPBACK_INTERNAL(efx) || 149 efx_mdio_phyxgxs_lane_sync(efx)); 150} 151 152void falcon_reconfigure_xmac_core(struct efx_nic *efx) 153{ 154 unsigned int max_frame_len; 155 efx_oword_t reg; 156 bool rx_fc = !!(efx->link_state.fc & EFX_FC_RX); 157 bool tx_fc = !!(efx->link_state.fc & EFX_FC_TX); 158 159 /* Configure MAC - cut-thru mode is hard wired on */ 160 EFX_POPULATE_OWORD_3(reg, 161 FRF_AB_XM_RX_JUMBO_MODE, 1, 162 FRF_AB_XM_TX_STAT_EN, 1, 163 FRF_AB_XM_RX_STAT_EN, 1); 164 efx_writeo(efx, &reg, FR_AB_XM_GLB_CFG); 165 166 /* Configure TX */ 167 EFX_POPULATE_OWORD_6(reg, 168 FRF_AB_XM_TXEN, 1, 169 FRF_AB_XM_TX_PRMBL, 1, 170 FRF_AB_XM_AUTO_PAD, 1, 171 FRF_AB_XM_TXCRC, 1, 172 FRF_AB_XM_FCNTL, tx_fc, 173 FRF_AB_XM_IPG, 0x3); 174 efx_writeo(efx, &reg, FR_AB_XM_TX_CFG); 175 176 /* Configure RX */ 177 EFX_POPULATE_OWORD_5(reg, 178 FRF_AB_XM_RXEN, 1, 179 FRF_AB_XM_AUTO_DEPAD, 0, 180 FRF_AB_XM_ACPT_ALL_MCAST, 1, 181 FRF_AB_XM_ACPT_ALL_UCAST, efx->promiscuous, 182 FRF_AB_XM_PASS_CRC_ERR, 1); 183 efx_writeo(efx, &reg, FR_AB_XM_RX_CFG); 184 185 /* Set frame length */ 186 max_frame_len = EFX_MAX_FRAME_LEN(efx->net_dev->mtu); 187 EFX_POPULATE_OWORD_1(reg, FRF_AB_XM_MAX_RX_FRM_SIZE, max_frame_len); 188 efx_writeo(efx, &reg, FR_AB_XM_RX_PARAM); 189 EFX_POPULATE_OWORD_2(reg, 190 FRF_AB_XM_MAX_TX_FRM_SIZE, max_frame_len, 191 FRF_AB_XM_TX_JUMBO_MODE, 1); 192 efx_writeo(efx, &reg, FR_AB_XM_TX_PARAM); 193 194 EFX_POPULATE_OWORD_2(reg, 195 FRF_AB_XM_PAUSE_TIME, 0xfffe, /* MAX PAUSE TIME */ 196 FRF_AB_XM_DIS_FCNTL, !rx_fc); 197 efx_writeo(efx, &reg, FR_AB_XM_FC); 198 199 /* Set MAC address */ 200 memcpy(&reg, &efx->net_dev->dev_addr[0], 4); 201 efx_writeo(efx, &reg, FR_AB_XM_ADR_LO); 202 memcpy(&reg, &efx->net_dev->dev_addr[4], 2); 203 efx_writeo(efx, &reg, FR_AB_XM_ADR_HI); 204} 205 206static void falcon_reconfigure_xgxs_core(struct efx_nic *efx) 207{ 208 efx_oword_t reg; 209 bool xgxs_loopback = (efx->loopback_mode == LOOPBACK_XGXS); 210 bool xaui_loopback = (efx->loopback_mode == LOOPBACK_XAUI); 211 bool xgmii_loopback = (efx->loopback_mode == LOOPBACK_XGMII); 212 213 /* XGXS block is flaky and will need to be reset if moving 214 * into our out of XGMII, XGXS or XAUI loopbacks. */ 215 if (EFX_WORKAROUND_5147(efx)) { 216 bool old_xgmii_loopback, old_xgxs_loopback, old_xaui_loopback; 217 bool reset_xgxs; 218 219 efx_reado(efx, &reg, FR_AB_XX_CORE_STAT); 220 old_xgxs_loopback = EFX_OWORD_FIELD(reg, FRF_AB_XX_XGXS_LB_EN); 221 old_xgmii_loopback = 222 EFX_OWORD_FIELD(reg, FRF_AB_XX_XGMII_LB_EN); 223 224 efx_reado(efx, &reg, FR_AB_XX_SD_CTL); 225 old_xaui_loopback = EFX_OWORD_FIELD(reg, FRF_AB_XX_LPBKA); 226 227 /* The PHY driver may have turned XAUI off */ 228 reset_xgxs = ((xgxs_loopback != old_xgxs_loopback) || 229 (xaui_loopback != old_xaui_loopback) || 230 (xgmii_loopback != old_xgmii_loopback)); 231 232 if (reset_xgxs) 233 falcon_reset_xaui(efx); 234 } 235 236 efx_reado(efx, &reg, FR_AB_XX_CORE_STAT); 237 EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_FORCE_SIG, 238 (xgxs_loopback || xaui_loopback) ? 239 FFE_AB_XX_FORCE_SIG_ALL_LANES : 0); 240 EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_XGXS_LB_EN, xgxs_loopback); 241 EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_XGMII_LB_EN, xgmii_loopback); 242 efx_writeo(efx, &reg, FR_AB_XX_CORE_STAT); 243 244 efx_reado(efx, &reg, FR_AB_XX_SD_CTL); 245 EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_LPBKD, xaui_loopback); 246 EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_LPBKC, xaui_loopback); 247 EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_LPBKB, xaui_loopback); 248 EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_LPBKA, xaui_loopback); 249 efx_writeo(efx, &reg, FR_AB_XX_SD_CTL); 250} 251 252 253/* Try to bring up the Falcon side of the Falcon-Phy XAUI link */ 254static bool falcon_xmac_link_ok_retry(struct efx_nic *efx, int tries) 255{ 256 bool mac_up = falcon_xmac_link_ok(efx); 257 258 if (LOOPBACK_MASK(efx) & LOOPBACKS_EXTERNAL(efx) & LOOPBACKS_WS || 259 efx_phy_mode_disabled(efx->phy_mode)) 260 /* XAUI link is expected to be down */ 261 return mac_up; 262 263 falcon_stop_nic_stats(efx); 264 265 while (!mac_up && tries) { 266 EFX_LOG(efx, "bashing xaui\n"); 267 falcon_reset_xaui(efx); 268 udelay(200); 269 270 mac_up = falcon_xmac_link_ok(efx); 271 --tries; 272 } 273 274 falcon_start_nic_stats(efx); 275 276 return mac_up; 277} 278 279static bool falcon_xmac_check_fault(struct efx_nic *efx) 280{ 281 return !falcon_xmac_link_ok_retry(efx, 5); 282} 283 284static int falcon_reconfigure_xmac(struct efx_nic *efx) 285{ 286 falcon_mask_status_intr(efx, false); 287 288 falcon_reconfigure_xgxs_core(efx); 289 falcon_reconfigure_xmac_core(efx); 290 291 falcon_reconfigure_mac_wrapper(efx); 292 293 efx->xmac_poll_required = !falcon_xmac_link_ok_retry(efx, 5); 294 falcon_mask_status_intr(efx, true); 295 296 return 0; 297} 298 299static void falcon_update_stats_xmac(struct efx_nic *efx) 300{ 301 struct efx_mac_stats *mac_stats = &efx->mac_stats; 302 303 /* Update MAC stats from DMAed values */ 304 FALCON_STAT(efx, XgRxOctets, rx_bytes); 305 FALCON_STAT(efx, XgRxOctetsOK, rx_good_bytes); 306 FALCON_STAT(efx, XgRxPkts, rx_packets); 307 FALCON_STAT(efx, XgRxPktsOK, rx_good); 308 FALCON_STAT(efx, XgRxBroadcastPkts, rx_broadcast); 309 FALCON_STAT(efx, XgRxMulticastPkts, rx_multicast); 310 FALCON_STAT(efx, XgRxUnicastPkts, rx_unicast); 311 FALCON_STAT(efx, XgRxUndersizePkts, rx_lt64); 312 FALCON_STAT(efx, XgRxOversizePkts, rx_gtjumbo); 313 FALCON_STAT(efx, XgRxJabberPkts, rx_bad_gtjumbo); 314 FALCON_STAT(efx, XgRxUndersizeFCSerrorPkts, rx_bad_lt64); 315 FALCON_STAT(efx, XgRxDropEvents, rx_overflow); 316 FALCON_STAT(efx, XgRxFCSerrorPkts, rx_bad); 317 FALCON_STAT(efx, XgRxAlignError, rx_align_error); 318 FALCON_STAT(efx, XgRxSymbolError, rx_symbol_error); 319 FALCON_STAT(efx, XgRxInternalMACError, rx_internal_error); 320 FALCON_STAT(efx, XgRxControlPkts, rx_control); 321 FALCON_STAT(efx, XgRxPausePkts, rx_pause); 322 FALCON_STAT(efx, XgRxPkts64Octets, rx_64); 323 FALCON_STAT(efx, XgRxPkts65to127Octets, rx_65_to_127); 324 FALCON_STAT(efx, XgRxPkts128to255Octets, rx_128_to_255); 325 FALCON_STAT(efx, XgRxPkts256to511Octets, rx_256_to_511); 326 FALCON_STAT(efx, XgRxPkts512to1023Octets, rx_512_to_1023); 327 FALCON_STAT(efx, XgRxPkts1024to15xxOctets, rx_1024_to_15xx); 328 FALCON_STAT(efx, XgRxPkts15xxtoMaxOctets, rx_15xx_to_jumbo); 329 FALCON_STAT(efx, XgRxLengthError, rx_length_error); 330 FALCON_STAT(efx, XgTxPkts, tx_packets); 331 FALCON_STAT(efx, XgTxOctets, tx_bytes); 332 FALCON_STAT(efx, XgTxMulticastPkts, tx_multicast); 333 FALCON_STAT(efx, XgTxBroadcastPkts, tx_broadcast); 334 FALCON_STAT(efx, XgTxUnicastPkts, tx_unicast); 335 FALCON_STAT(efx, XgTxControlPkts, tx_control); 336 FALCON_STAT(efx, XgTxPausePkts, tx_pause); 337 FALCON_STAT(efx, XgTxPkts64Octets, tx_64); 338 FALCON_STAT(efx, XgTxPkts65to127Octets, tx_65_to_127); 339 FALCON_STAT(efx, XgTxPkts128to255Octets, tx_128_to_255); 340 FALCON_STAT(efx, XgTxPkts256to511Octets, tx_256_to_511); 341 FALCON_STAT(efx, XgTxPkts512to1023Octets, tx_512_to_1023); 342 FALCON_STAT(efx, XgTxPkts1024to15xxOctets, tx_1024_to_15xx); 343 FALCON_STAT(efx, XgTxPkts1519toMaxOctets, tx_15xx_to_jumbo); 344 FALCON_STAT(efx, XgTxUndersizePkts, tx_lt64); 345 FALCON_STAT(efx, XgTxOversizePkts, tx_gtjumbo); 346 FALCON_STAT(efx, XgTxNonTcpUdpPkt, tx_non_tcpudp); 347 FALCON_STAT(efx, XgTxMacSrcErrPkt, tx_mac_src_error); 348 FALCON_STAT(efx, XgTxIpSrcErrPkt, tx_ip_src_error); 349 350 /* Update derived statistics */ 351 mac_stats->tx_good_bytes = 352 (mac_stats->tx_bytes - mac_stats->tx_bad_bytes - 353 mac_stats->tx_control * 64); 354 mac_stats->rx_bad_bytes = 355 (mac_stats->rx_bytes - mac_stats->rx_good_bytes - 356 mac_stats->rx_control * 64); 357} 358 359void falcon_poll_xmac(struct efx_nic *efx) 360{ 361 if (!EFX_WORKAROUND_5147(efx) || !efx->link_state.up || 362 !efx->xmac_poll_required) 363 return; 364 365 falcon_mask_status_intr(efx, false); 366 efx->xmac_poll_required = !falcon_xmac_link_ok_retry(efx, 1); 367 falcon_mask_status_intr(efx, true); 368} 369 370struct efx_mac_operations falcon_xmac_operations = { 371 .reconfigure = falcon_reconfigure_xmac, 372 .update_stats = falcon_update_stats_xmac, 373 .check_fault = falcon_xmac_check_fault, 374};