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.33-rc2 368 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 114/* Get status of XAUI link */ 115static bool falcon_xaui_link_ok(struct efx_nic *efx) 116{ 117 efx_oword_t reg; 118 bool align_done, link_ok = false; 119 int sync_status; 120 121 if (LOOPBACK_INTERNAL(efx)) 122 return true; 123 124 /* Read link status */ 125 efx_reado(efx, &reg, FR_AB_XX_CORE_STAT); 126 127 align_done = EFX_OWORD_FIELD(reg, FRF_AB_XX_ALIGN_DONE); 128 sync_status = EFX_OWORD_FIELD(reg, FRF_AB_XX_SYNC_STAT); 129 if (align_done && (sync_status == FFE_AB_XX_STAT_ALL_LANES)) 130 link_ok = true; 131 132 /* Clear link status ready for next read */ 133 EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_COMMA_DET, FFE_AB_XX_STAT_ALL_LANES); 134 EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_CHAR_ERR, FFE_AB_XX_STAT_ALL_LANES); 135 EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_DISPERR, FFE_AB_XX_STAT_ALL_LANES); 136 efx_writeo(efx, &reg, FR_AB_XX_CORE_STAT); 137 138 /* If the link is up, then check the phy side of the xaui link */ 139 if (efx->link_state.up && link_ok) 140 if (efx->mdio.mmds & (1 << MDIO_MMD_PHYXS)) 141 link_ok = efx_mdio_phyxgxs_lane_sync(efx); 142 143 return link_ok; 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, &reg, 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, &reg, 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, &reg, 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, &reg, 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, &reg, 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, &reg, FR_AB_XM_FC); 192 193 /* Set MAC address */ 194 memcpy(&reg, &efx->net_dev->dev_addr[0], 4); 195 efx_writeo(efx, &reg, FR_AB_XM_ADR_LO); 196 memcpy(&reg, &efx->net_dev->dev_addr[4], 2); 197 efx_writeo(efx, &reg, 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, &reg, 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, &reg, 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, &reg, 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, &reg, FR_AB_XX_CORE_STAT); 237 238 efx_reado(efx, &reg, 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, &reg, 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_check_xaui_link_up(struct efx_nic *efx, int tries) 249{ 250 bool mac_up = falcon_xaui_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 EFX_LOG(efx, "bashing xaui\n"); 261 falcon_reset_xaui(efx); 262 udelay(200); 263 264 mac_up = falcon_xaui_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_check_xaui_link_up(efx, 5); 276} 277 278static int falcon_reconfigure_xmac(struct efx_nic *efx) 279{ 280 falcon_mask_status_intr(efx, false); 281 282 falcon_reconfigure_xgxs_core(efx); 283 falcon_reconfigure_xmac_core(efx); 284 285 falcon_reconfigure_mac_wrapper(efx); 286 287 efx->xmac_poll_required = !falcon_check_xaui_link_up(efx, 5); 288 falcon_mask_status_intr(efx, true); 289 290 return 0; 291} 292 293static void falcon_update_stats_xmac(struct efx_nic *efx) 294{ 295 struct efx_mac_stats *mac_stats = &efx->mac_stats; 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 = 346 (mac_stats->tx_bytes - mac_stats->tx_bad_bytes - 347 mac_stats->tx_control * 64); 348 mac_stats->rx_bad_bytes = 349 (mac_stats->rx_bytes - mac_stats->rx_good_bytes - 350 mac_stats->rx_control * 64); 351} 352 353void falcon_poll_xmac(struct efx_nic *efx) 354{ 355 if (!EFX_WORKAROUND_5147(efx) || !efx->link_state.up || 356 !efx->xmac_poll_required) 357 return; 358 359 falcon_mask_status_intr(efx, false); 360 efx->xmac_poll_required = !falcon_check_xaui_link_up(efx, 1); 361 falcon_mask_status_intr(efx, true); 362} 363 364struct efx_mac_operations falcon_xmac_operations = { 365 .reconfigure = falcon_reconfigure_xmac, 366 .update_stats = falcon_update_stats_xmac, 367 .check_fault = falcon_xmac_check_fault, 368};