diff options
| author | Jack F Vogel <jfv@FreeBSD.org> | 2009-12-07 21:30:54 +0000 |
|---|---|---|
| committer | Jack F Vogel <jfv@FreeBSD.org> | 2009-12-07 21:30:54 +0000 |
| commit | 2969bf0e467c14c149c45a81b6505ec443d15938 (patch) | |
| tree | eb771079f6b223fe24a5557c0c86f0cea1dbe80c /sys | |
| parent | 406930fba4f38478e7a005d46e118c54775ffb37 (diff) | |
Notes
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/dev/ixgbe/ixgbe.c | 1225 | ||||
| -rw-r--r-- | sys/dev/ixgbe/ixgbe.h | 52 | ||||
| -rw-r--r-- | sys/dev/ixgbe/ixgbe_82598.c | 240 | ||||
| -rw-r--r-- | sys/dev/ixgbe/ixgbe_82599.c | 857 | ||||
| -rw-r--r-- | sys/dev/ixgbe/ixgbe_api.c | 44 | ||||
| -rw-r--r-- | sys/dev/ixgbe/ixgbe_api.h | 6 | ||||
| -rw-r--r-- | sys/dev/ixgbe/ixgbe_common.c | 970 | ||||
| -rw-r--r-- | sys/dev/ixgbe/ixgbe_common.h | 27 | ||||
| -rw-r--r-- | sys/dev/ixgbe/ixgbe_osdep.h | 10 | ||||
| -rw-r--r-- | sys/dev/ixgbe/ixgbe_phy.c | 221 | ||||
| -rw-r--r-- | sys/dev/ixgbe/ixgbe_phy.h | 3 | ||||
| -rw-r--r-- | sys/dev/ixgbe/ixgbe_type.h | 116 |
12 files changed, 2506 insertions, 1265 deletions
diff --git a/sys/dev/ixgbe/ixgbe.c b/sys/dev/ixgbe/ixgbe.c index d994529ea461..10a0e04df488 100644 --- a/sys/dev/ixgbe/ixgbe.c +++ b/sys/dev/ixgbe/ixgbe.c @@ -46,7 +46,7 @@ int ixgbe_display_debug_stats = 0; /********************************************************************* * Driver version *********************************************************************/ -char ixgbe_driver_version[] = "1.8.9"; +char ixgbe_driver_version[] = "2.0.7"; /********************************************************************* * PCI Device ID Table @@ -64,16 +64,19 @@ static ixgbe_vendor_info_t ixgbe_vendor_info_array[] = {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_SINGLE_PORT, 0, 0, 0}, {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_CX4, 0, 0, 0}, {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT, 0, 0, 0}, + {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT2, 0, 0, 0}, {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598, 0, 0, 0}, {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_DA_DUAL_PORT, 0, 0, 0}, {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_CX4_DUAL_PORT, 0, 0, 0}, {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_XF_LR, 0, 0, 0}, - {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT, 0, 0, 0}, {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM, 0, 0, 0}, {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_SFP_LOM, 0, 0, 0}, {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KX4, 0, 0, 0}, + {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KX4_MEZZ, 0, 0, 0}, {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP, 0, 0, 0}, {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_XAUI_LOM, 0, 0, 0}, + {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_CX4, 0, 0, 0}, + {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_COMBO_BACKPLANE, 0, 0, 0}, /* required last entry */ {0, 0, 0, 0, 0} }; @@ -102,7 +105,6 @@ static int ixgbe_mq_start_locked(struct ifnet *, static void ixgbe_qflush(struct ifnet *); #endif static int ixgbe_ioctl(struct ifnet *, u_long, caddr_t); -static void ixgbe_watchdog(struct adapter *); static void ixgbe_init(void *); static void ixgbe_init_locked(struct adapter *); static void ixgbe_stop(void *); @@ -116,8 +118,8 @@ static int ixgbe_allocate_queues(struct adapter *); static int ixgbe_setup_msix(struct adapter *); static void ixgbe_free_pci_resources(struct adapter *); static void ixgbe_local_timer(void *); -static int ixgbe_hardware_init(struct adapter *); static void ixgbe_setup_interface(device_t, struct adapter *); +static void ixgbe_config_link(struct adapter *); static int ixgbe_allocate_transmit_buffers(struct tx_ring *); static int ixgbe_setup_transmit_structures(struct adapter *); @@ -132,6 +134,7 @@ static int ixgbe_setup_receive_ring(struct rx_ring *); static void ixgbe_initialize_receive_units(struct adapter *); static void ixgbe_free_receive_structures(struct adapter *); static void ixgbe_free_receive_buffers(struct rx_ring *); +static void ixgbe_setup_hw_rsc(struct rx_ring *); static void ixgbe_init_moderation(struct adapter *); static void ixgbe_enable_intr(struct adapter *); @@ -146,7 +149,7 @@ static void ixgbe_set_multi(struct adapter *); static void ixgbe_print_hw_stats(struct adapter *); static void ixgbe_print_debug_info(struct adapter *); static void ixgbe_update_link_status(struct adapter *); -static int ixgbe_get_buf(struct rx_ring *, int, u8); +static int ixgbe_get_buf(struct rx_ring *, int, int); static int ixgbe_xmit(struct tx_ring *, struct mbuf **); static int ixgbe_sysctl_stats(SYSCTL_HANDLER_ARGS); static int ixgbe_sysctl_debug(SYSCTL_HANDLER_ARGS); @@ -186,6 +189,10 @@ static void ixgbe_handle_link(void *, int); static void ixgbe_handle_msf(void *, int); static void ixgbe_handle_mod(void *, int); +#ifdef IXGBE_FDIR +static void ixgbe_atr(struct tx_ring *, struct mbuf *); +static void ixgbe_reinit_fdir(void *, int); +#endif /********************************************************************* * FreeBSD Device Interface Entry Points @@ -239,6 +246,15 @@ static int ixgbe_flow_control = ixgbe_fc_full; TUNABLE_INT("hw.ixgbe.flow_control", &ixgbe_flow_control); /* +** Smart speed setting, default to on +** this only works as a compile option +** right now as its during attach, set +** this to 'ixgbe_smart_speed_off' to +** disable. +*/ +static int ixgbe_smart_speed = ixgbe_smart_speed_on; + +/* * MSIX should be the default for best performance, * but this allows it to be forced off for testing. */ @@ -271,7 +287,7 @@ TUNABLE_INT("hw.ixgbe.txd", &ixgbe_txd); static int ixgbe_rxd = DEFAULT_RXD; TUNABLE_INT("hw.ixgbe.rxd", &ixgbe_rxd); -/* Total number of Interfaces - need for config sanity check */ +/* Keep running tab on them for sanity check */ static int ixgbe_total_ports; /* @@ -288,6 +304,27 @@ static u32 ixgbe_shadow_vfta[IXGBE_VFTA_SIZE]; */ static int ixgbe_num_segs = IXGBE_82598_SCATTER; +#ifdef IXGBE_FDIR +/* +** For Flow Director: this is the +** number of TX packets we sample +** for the filter pool, this means +** every 20th packet will be probed. +** +** This feature can be disabled by +** setting this to 0. +*/ +static int atr_sample_rate = 20; +/* +** Flow Director actually 'steals' +** part of the packet buffer as its +** filter pool, this variable controls +** how much it uses: +** 0 = 64K, 1 = 128K, 2 = 256K +*/ +static int fdir_pballoc = 1; +#endif + /********************************************************************* * Device identification routine * @@ -356,7 +393,7 @@ ixgbe_attach(device_t dev) struct adapter *adapter; struct ixgbe_hw *hw; int error = 0; - u16 pci_device_id; + u16 pci_device_id, csum; u32 ctrl_ext; INIT_DEBUGOUT("ixgbe_attach: begin"); @@ -376,10 +413,14 @@ ixgbe_attach(device_t dev) case IXGBE_DEV_ID_82598EB_CX4 : adapter->optics = IFM_10G_CX4; break; + case IXGBE_DEV_ID_82598 : case IXGBE_DEV_ID_82598AF_DUAL_PORT : case IXGBE_DEV_ID_82598_DA_DUAL_PORT : case IXGBE_DEV_ID_82598AF_SINGLE_PORT : + case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM : + case IXGBE_DEV_ID_82598EB_SFP_LOM : case IXGBE_DEV_ID_82598AT : + case IXGBE_DEV_ID_82598AT2 : adapter->optics = IFM_10G_SR; break; case IXGBE_DEV_ID_82598EB_XF_LR : @@ -390,10 +431,13 @@ ixgbe_attach(device_t dev) ixgbe_num_segs = IXGBE_82599_SCATTER; break; case IXGBE_DEV_ID_82599_KX4 : + case IXGBE_DEV_ID_82599_KX4_MEZZ: + case IXGBE_DEV_ID_82599_CX4 : adapter->optics = IFM_10G_CX4; ixgbe_num_segs = IXGBE_82599_SCATTER; break; case IXGBE_DEV_ID_82599_XAUI_LOM : + case IXGBE_DEV_ID_82599_COMBO_BACKPLANE : ixgbe_num_segs = IXGBE_82599_SCATTER; default: break; @@ -504,13 +548,40 @@ ixgbe_attach(device_t dev) goto err_late; } - /* Initialize the hardware */ - if (ixgbe_hardware_init(adapter)) { - device_printf(dev,"Unable to initialize the hardware\n"); + /* Make sure we have a good EEPROM before we read from it */ + if (ixgbe_validate_eeprom_checksum(&adapter->hw, &csum) < 0) { + device_printf(dev,"The EEPROM Checksum Is Not Valid\n"); error = EIO; goto err_late; } + /* Pick up the smart speed setting */ + if (hw->mac.type == ixgbe_mac_82599EB) + hw->phy.smart_speed = ixgbe_smart_speed; + + /* Get Hardware Flow Control setting */ + hw->fc.requested_mode = ixgbe_fc_full; + hw->fc.pause_time = IXGBE_FC_PAUSE; + hw->fc.low_water = IXGBE_FC_LO; + hw->fc.high_water = IXGBE_FC_HI; + hw->fc.send_xon = TRUE; + + error = ixgbe_init_hw(hw); + if (error == IXGBE_ERR_EEPROM_VERSION) { + device_printf(dev, "This device is a pre-production adapter/" + "LOM. Please be aware there may be issues associated " + "with your hardware.\n If you are experiencing problems " + "please contact your Intel or hardware representative " + "who provided you with this hardware.\n"); + } else if (error == IXGBE_ERR_SFP_NOT_SUPPORTED) + device_printf(dev,"Unsupported SFP+ Module\n"); + + if (error) { + error = EIO; + device_printf(dev,"Hardware Initialization Failure\n"); + goto err_late; + } + if ((adapter->msix > 1) && (ixgbe_enable_msix)) error = ixgbe_allocate_msix(adapter); else @@ -529,10 +600,10 @@ ixgbe_attach(device_t dev) adapter->cycles.mask = (u64)-1; adapter->cycles.mult = 1; adapter->cycles.shift = IXGBE_TSYNC_SHIFT; - IXGBE_WRITE_REG(&adapter->hw, IXGBE_TIMINCA, (1<<24) | + IXGBE_WRITE_REG(hw, IXGBE_TIMINCA, (1<<24) | IXGBE_TSYNC_CYCLE_TIME * IXGBE_TSYNC_SHIFT); - IXGBE_WRITE_REG(&adapter->hw, IXGBE_SYSTIML, 0x00000000); - IXGBE_WRITE_REG(&adapter->hw, IXGBE_SYSTIMH, 0xFF800000); + IXGBE_WRITE_REG(hw, IXGBE_SYSTIML, 0x00000000); + IXGBE_WRITE_REG(hw, IXGBE_SYSTIMH, 0xFF800000); // JFV - this is not complete yet #endif @@ -551,6 +622,24 @@ ixgbe_attach(device_t dev) adapter->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig, ixgbe_unregister_vlan, adapter, EVENTHANDLER_PRI_FIRST); + /* Print PCIE bus type/speed/width info */ + ixgbe_get_bus_info(hw); + device_printf(dev,"PCI Express Bus: Speed %s %s\n", + ((hw->bus.speed == ixgbe_bus_speed_5000) ? "5.0Gb/s": + (hw->bus.speed == ixgbe_bus_speed_2500) ? "2.5Gb/s":"Unknown"), + (hw->bus.width == ixgbe_bus_width_pcie_x8) ? "Width x8" : + (hw->bus.width == ixgbe_bus_width_pcie_x4) ? "Width x4" : + (hw->bus.width == ixgbe_bus_width_pcie_x1) ? "Width x1" : + ("Unknown")); + + if (hw->bus.width <= ixgbe_bus_width_pcie_x4) { + device_printf(dev, "PCI-Express bandwidth available" + " for this card\n is not sufficient for" + " optimal performance.\n"); + device_printf(dev, "For optimal performance a x8 " + "PCI-Express slot is required.\n"); + } + /* let hardware know driver is loaded */ ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); ctrl_ext |= IXGBE_CTRL_EXT_DRV_LOAD; @@ -616,6 +705,9 @@ ixgbe_detach(device_t dev) taskqueue_drain(adapter->tq, &adapter->link_task); taskqueue_drain(adapter->tq, &adapter->mod_task); taskqueue_drain(adapter->tq, &adapter->msf_task); +#ifdef IXGBE_FDIR + taskqueue_drain(adapter->tq, &adapter->fdir_task); +#endif taskqueue_free(adapter->tq); } @@ -700,8 +792,8 @@ ixgbe_start_locked(struct tx_ring *txr, struct ifnet * ifp) /* Send a copy of the frame to the BPF listener */ ETHER_BPF_MTAP(ifp, m_head); - /* Set timeout in case hardware has problems transmitting */ - txr->watchdog_timer = IXGBE_TX_TIMEOUT; + /* Set watchdog on */ + txr->watchdog_check = TRUE; } return; @@ -770,16 +862,17 @@ ixgbe_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr, struct mbuf *m) /* If nothing queued go right to xmit */ if (drbr_empty(ifp, txr->br)) { - if (ixgbe_xmit(txr, &m)) { - if (m && (err = drbr_enqueue(ifp, txr->br, m)) != 0) - return (err); + if ((err = ixgbe_xmit(txr, &m)) != 0) { + if (m != NULL) + err = drbr_enqueue(ifp, txr->br, m); + return (err); } else { /* Success, update stats */ drbr_stats_update(ifp, m->m_pkthdr.len, m->m_flags); /* Send a copy of the frame to the BPF listener */ ETHER_BPF_MTAP(ifp, m); /* Set the watchdog */ - txr->watchdog_timer = IXGBE_TX_TIMEOUT; + txr->watchdog_check = TRUE; } } else if ((err = drbr_enqueue(ifp, txr->br, m)) != 0) @@ -796,11 +889,15 @@ process: next = drbr_dequeue(ifp, txr->br); if (next == NULL) break; - if (ixgbe_xmit(txr, &next)) + if ((err = ixgbe_xmit(txr, &next)) != 0) { + if (next != NULL) + err = drbr_enqueue(ifp, txr->br, next); break; + } + drbr_stats_update(ifp, next->m_pkthdr.len, next->m_flags); ETHER_BPF_MTAP(ifp, next); /* Set the watchdog */ - txr->watchdog_timer = IXGBE_TX_TIMEOUT; + txr->watchdog_check = TRUE; } if (txr->tx_avail <= IXGBE_TX_OP_THRESHOLD) @@ -843,27 +940,10 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data) { struct adapter *adapter = ifp->if_softc; struct ifreq *ifr = (struct ifreq *) data; -#ifdef INET - struct ifaddr *ifa = (struct ifaddr *) data; -#endif int error = 0; switch (command) { - case SIOCSIFADDR: -#ifdef INET - IOCTL_DEBUGOUT("ioctl: SIOCxIFADDR (Get/Set Interface Addr)"); - if (ifa->ifa_addr->sa_family == AF_INET) { - ifp->if_flags |= IFF_UP; - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - IXGBE_CORE_LOCK(adapter); - ixgbe_init_locked(adapter); - IXGBE_CORE_UNLOCK(adapter); - } - arp_ifinit(ifp, ifa); - } else -#endif - ether_ioctl(ifp, command, data); - break; + case SIOCSIFMTU: IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)"); if (ifr->ifr_mtu > IXGBE_MAX_FRAME_SIZE - ETHER_HDR_LEN) { @@ -919,7 +999,8 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data) ifp->if_capenable ^= IFCAP_HWCSUM; if (mask & IFCAP_TSO4) ifp->if_capenable ^= IFCAP_TSO4; - if (mask & IFCAP_LRO) + /* Only allow changing when using header split */ + if ((mask & IFCAP_LRO) && (ixgbe_header_split)) ifp->if_capenable ^= IFCAP_LRO; if (mask & IFCAP_VLAN_HWTAGGING) ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; @@ -948,84 +1029,6 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data) } /********************************************************************* - * Watchdog entry point - * - * This routine is called by the local timer - * to detect hardware hangs . - * - **********************************************************************/ - -static void -ixgbe_watchdog(struct adapter *adapter) -{ - device_t dev = adapter->dev; - struct tx_ring *txr = adapter->tx_rings; - struct ixgbe_hw *hw = &adapter->hw; - bool tx_hang = FALSE; - - IXGBE_CORE_LOCK_ASSERT(adapter); - - /* - * The timer is set to 5 every time ixgbe_start() queues a packet. - * Then ixgbe_txeof() keeps resetting to 5 as long as it cleans at - * least one descriptor. - * Finally, anytime all descriptors are clean the timer is - * set to 0. - */ - for (int i = 0; i < adapter->num_queues; i++, txr++) { - u32 head, tail; - - IXGBE_TX_LOCK(txr); - if (txr->watchdog_timer == 0 || --txr->watchdog_timer) { - IXGBE_TX_UNLOCK(txr); - continue; - } else { - head = IXGBE_READ_REG(hw, IXGBE_TDH(i)); - tail = IXGBE_READ_REG(hw, IXGBE_TDT(i)); - if (head == tail) { /* last minute check */ - IXGBE_TX_UNLOCK(txr); - continue; - } - /* Well, seems something is really hung */ - tx_hang = TRUE; - IXGBE_TX_UNLOCK(txr); - break; - } - } - if (tx_hang == FALSE) - return; - - /* - * If we are in this routine because of pause frames, then don't - * reset the hardware. - */ - if (IXGBE_READ_REG(hw, IXGBE_TFCS) & IXGBE_TFCS_TXOFF) { - txr = adapter->tx_rings; /* reset pointer */ - for (int i = 0; i < adapter->num_queues; i++, txr++) { - IXGBE_TX_LOCK(txr); - txr->watchdog_timer = IXGBE_TX_TIMEOUT; - IXGBE_TX_UNLOCK(txr); - } - return; - } - - - device_printf(adapter->dev, "Watchdog timeout -- resetting\n"); - for (int i = 0; i < adapter->num_queues; i++, txr++) { - device_printf(dev,"Queue(%d) tdh = %d, hw tdt = %d\n", i, - IXGBE_READ_REG(hw, IXGBE_TDH(i)), - IXGBE_READ_REG(hw, IXGBE_TDT(i))); - device_printf(dev,"TX(%d) desc avail = %d," - "Next TX to Clean = %d\n", - i, txr->tx_avail, txr->next_tx_to_clean); - } - adapter->ifp->if_drv_flags &= ~IFF_DRV_RUNNING; - adapter->watchdog_events++; - - ixgbe_init_locked(adapter); -} - -/********************************************************************* * Init entry point * * This routine is used in two ways. It is used by the stack as @@ -1052,19 +1055,14 @@ ixgbe_init_locked(struct adapter *adapter) hw = &adapter->hw; mtx_assert(&adapter->core_mtx, MA_OWNED); - ixgbe_stop(adapter); - /* Get the latest mac address, User can use a LAA */ - bcopy(IF_LLADDR(adapter->ifp), adapter->hw.mac.addr, + bcopy(IF_LLADDR(adapter->ifp), hw->mac.addr, IXGBE_ETH_LENGTH_OF_ADDRESS); - ixgbe_set_rar(&adapter->hw, 0, adapter->hw.mac.addr, 0, 1); - adapter->hw.addr_ctrl.rar_used_count = 1; + ixgbe_set_rar(hw, 0, hw->mac.addr, 0, 1); + hw->addr_ctrl.rar_used_count = 1; - /* Initialize the hardware */ - if (ixgbe_hardware_init(adapter)) { - device_printf(dev, "Unable to initialize the hardware\n"); - return; - } + /* Do a warm reset */ + ixgbe_reset_hw(hw); /* Prepare transmit descriptors and buffers */ if (ixgbe_setup_transmit_structures(adapter)) { @@ -1102,7 +1100,7 @@ ixgbe_init_locked(struct adapter *adapter) gpie = IXGBE_READ_REG(&adapter->hw, IXGBE_GPIE); - if (adapter->hw.mac.type == ixgbe_mac_82599EB) { + if (hw->mac.type == ixgbe_mac_82599EB) { gpie |= IXGBE_SDP1_GPIEN; gpie |= IXGBE_SDP2_GPIEN; } @@ -1117,7 +1115,7 @@ ixgbe_init_locked(struct adapter *adapter) gpie |= IXGBE_GPIE_EIAME | IXGBE_GPIE_PBA_SUPPORT | IXGBE_GPIE_OCD; } - IXGBE_WRITE_REG(&adapter->hw, IXGBE_GPIE, gpie); + IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie); /* Set the various hardware offload abilities */ ifp->if_hwassist = 0; @@ -1128,28 +1126,35 @@ ixgbe_init_locked(struct adapter *adapter) /* Set MTU size */ if (ifp->if_mtu > ETHERMTU) { - mhadd = IXGBE_READ_REG(&adapter->hw, IXGBE_MHADD); + mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD); mhadd &= ~IXGBE_MHADD_MFS_MASK; mhadd |= adapter->max_frame_size << IXGBE_MHADD_MFS_SHIFT; - IXGBE_WRITE_REG(&adapter->hw, IXGBE_MHADD, mhadd); + IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd); } /* Now enable all the queues */ for (int i = 0; i < adapter->num_queues; i++) { - txdctl = IXGBE_READ_REG(&adapter->hw, IXGBE_TXDCTL(i)); + txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(i)); txdctl |= IXGBE_TXDCTL_ENABLE; /* Set WTHRESH to 8, burst writeback */ txdctl |= (8 << 16); - IXGBE_WRITE_REG(&adapter->hw, IXGBE_TXDCTL(i), txdctl); + IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(i), txdctl); } for (int i = 0; i < adapter->num_queues; i++) { - rxdctl = IXGBE_READ_REG(&adapter->hw, IXGBE_RXDCTL(i)); - /* PTHRESH set to 32 */ - rxdctl |= 0x0020; + rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i)); + if (hw->mac.type == ixgbe_mac_82598EB) { + /* + ** PTHRESH = 21 + ** HTHRESH = 4 + ** WTHRESH = 8 + */ + rxdctl &= ~0x3FFFFF; + rxdctl |= 0x080420; + } rxdctl |= IXGBE_RXDCTL_ENABLE; - IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXDCTL(i), rxdctl); + IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(i), rxdctl); for (k = 0; k < 10; k++) { if (IXGBE_READ_REG(hw, IXGBE_RXDCTL(i)) & IXGBE_RXDCTL_ENABLE) @@ -1166,7 +1171,7 @@ ixgbe_init_locked(struct adapter *adapter) /* Enable Receive engine */ rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); - if (adapter->hw.mac.type == ixgbe_mac_82598EB) + if (hw->mac.type == ixgbe_mac_82598EB) rxctrl |= IXGBE_RXCTRL_DMBYPS; rxctrl |= IXGBE_RXCTRL_RXEN; IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl); @@ -1181,7 +1186,11 @@ ixgbe_init_locked(struct adapter *adapter) ixgbe_set_ivar(adapter, 0, 0, 1); } - ixgbe_enable_intr(adapter); +#ifdef IXGBE_FDIR + /* Init Flow director */ + if (adapter->hw.mac.type == ixgbe_mac_82599EB) + ixgbe_init_fdir_signature_82599(&adapter->hw, fdir_pballoc); +#endif /* ** Check on any SFP devices that @@ -1194,14 +1203,12 @@ ixgbe_init_locked(struct adapter *adapter) ixgbe_detach(dev); return; } - if (ixgbe_is_sfp(hw)) { - if (hw->phy.multispeed_fiber) { - hw->mac.ops.setup_sfp(hw); - taskqueue_enqueue(adapter->tq, &adapter->msf_task); - } else - taskqueue_enqueue(adapter->tq, &adapter->mod_task); - } else - taskqueue_enqueue(adapter->tq, &adapter->link_task); + + /* Config/Enable Link */ + ixgbe_config_link(adapter); + + /* And now turn on interrupts */ + ixgbe_enable_intr(adapter); /* Now inform the stack we're ready */ ifp->if_drv_flags |= IFF_DRV_RUNNING; @@ -1269,7 +1276,7 @@ ixgbe_disable_queue(struct adapter *adapter, u32 vector) } static inline void -ixgbe_rearm_rx_queues(struct adapter *adapter, u64 queues) +ixgbe_rearm_queues(struct adapter *adapter, u64 queues) { u32 mask; @@ -1464,11 +1471,25 @@ ixgbe_msix_link(void *arg) taskqueue_enqueue(adapter->tq, &adapter->link_task); if (adapter->hw.mac.type == ixgbe_mac_82599EB) { +#ifdef IXGBE_FDIR + if (reg_eicr & IXGBE_EICR_FLOW_DIR) { + /* This is probably overkill :) */ + if (!atomic_cmpset_int(&adapter->fdir_reinit, 0, 1)) + return; + /* Clear the interrupt */ + IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_FLOW_DIR); + /* Turn off the interface */ + adapter->ifp->if_drv_flags &= ~IFF_DRV_RUNNING; + taskqueue_enqueue(adapter->tq, &adapter->fdir_task); + } else +#endif if (reg_eicr & IXGBE_EICR_ECC) { device_printf(adapter->dev, "\nCRITICAL: ECC ERROR!! " "Please Reboot!!\n"); IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_ECC); - } else if (reg_eicr & IXGBE_EICR_GPI_SDP1) { + } else + + if (reg_eicr & IXGBE_EICR_GPI_SDP1) { /* Clear the interrupt */ IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1); taskqueue_enqueue(adapter->tq, &adapter->msf_task); @@ -1553,11 +1574,9 @@ ixgbe_init_moderation(struct adapter *adapter) } /* TX irq moderation rate is fixed */ - for (int i = 0; i < adapter->num_queues; i++, txr++) { + for (int i = 0; i < adapter->num_queues; i++, txr++) IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(txr->msix), ixgbe_ave_latency); - txr->watchdog_timer = FALSE; - } /* RX moderation will be adapted over time, set default */ for (int i = 0; i < adapter->num_queues; i++, rxr++) { @@ -1633,7 +1652,6 @@ ixgbe_media_change(struct ifnet * ifp) switch (IFM_SUBTYPE(ifm->ifm_media)) { case IFM_AUTO: - adapter->hw.mac.autoneg = TRUE; adapter->hw.phy.autoneg_advertised = IXGBE_LINK_SPEED_1GB_FULL | IXGBE_LINK_SPEED_10GB_FULL; break; @@ -1690,7 +1708,7 @@ ixgbe_xmit(struct tx_ring *txr, struct mbuf **m_headp) * used because it will contain the index of * the one we tell the hardware to report back */ - first = txr->next_avail_tx_desc; + first = txr->next_avail_desc; txbuf = &txr->tx_buffers[first]; txbuf_mapped = txbuf; map = txbuf->map; @@ -1767,12 +1785,22 @@ ixgbe_xmit(struct tx_ring *txr, struct mbuf **m_headp) cmd_type_len |= IXGBE_ADVTXD_MAC_TSTAMP; #endif +#ifdef IXGBE_FDIR + /* Do the flow director magic */ + if ((txr->atr_sample) && (!adapter->fdir_reinit)) { + ++txr->atr_count; + if (txr->atr_count >= atr_sample_rate) { + ixgbe_atr(txr, m_head); + txr->atr_count = 0; + } + } +#endif /* Record payload length */ if (paylen == 0) olinfo_status |= m_head->m_pkthdr.len << IXGBE_ADVTXD_PAYLEN_SHIFT; - i = txr->next_avail_tx_desc; + i = txr->next_avail_desc; for (j = 0; j < nsegs; j++) { bus_size_t seglen; bus_addr_t segaddr; @@ -1798,7 +1826,7 @@ ixgbe_xmit(struct tx_ring *txr, struct mbuf **m_headp) txd->read.cmd_type_len |= htole32(IXGBE_TXD_CMD_EOP | IXGBE_TXD_CMD_RS); txr->tx_avail -= nsegs; - txr->next_avail_tx_desc = i; + txr->next_avail_desc = i; txbuf->m_head = m_head; txbuf->map = map; @@ -1939,7 +1967,7 @@ ixgbe_mc_array_itr(struct ixgbe_hw *hw, u8 **update_ptr, u32 *vmdq) * Timer routine * * This routine checks for link status,updates statistics, - * and runs the watchdog timer. + * and runs the watchdog check. * **********************************************************************/ @@ -1948,6 +1976,9 @@ ixgbe_local_timer(void *arg) { struct adapter *adapter = arg; struct ifnet *ifp = adapter->ifp; + device_t dev = adapter->dev; + struct tx_ring *txr = adapter->tx_rings; + bool tx_hung = FALSE; mtx_assert(&adapter->core_mtx, MA_OWNED); @@ -1962,16 +1993,31 @@ ixgbe_local_timer(void *arg) ixgbe_print_hw_stats(adapter); } /* - * Each tick we check the watchdog - * to protect against hardware hangs. - */ - ixgbe_watchdog(adapter); - + ** Check for time since any descriptor was cleaned + */ + for (int i = 0; i < adapter->num_queues; i++, txr++) { + if (txr->watchdog_check == FALSE) + continue; + if ((ticks - txr->watchdog_time) > IXGBE_WATCHDOG) { + tx_hung = TRUE; + goto hung; + } + } out: - /* Trigger an RX interrupt on all queues */ - ixgbe_rearm_rx_queues(adapter, adapter->rx_mask); - callout_reset(&adapter->timer, hz, ixgbe_local_timer, adapter); + return; + +hung: + device_printf(adapter->dev, "Watchdog timeout -- resetting\n"); + device_printf(dev,"Queue(%d) tdh = %d, hw tdt = %d\n", txr->me, + IXGBE_READ_REG(&adapter->hw, IXGBE_TDH(txr->me)), + IXGBE_READ_REG(&adapter->hw, IXGBE_TDT(txr->me))); + device_printf(dev,"TX(%d) desc avail = %d," + "Next TX to Clean = %d\n", + txr->me, txr->tx_avail, txr->next_to_clean); + adapter->ifp->if_drv_flags &= ~IFF_DRV_RUNNING; + adapter->watchdog_events++; + ixgbe_init_locked(adapter); } /* @@ -2004,7 +2050,7 @@ ixgbe_update_link_status(struct adapter *adapter) adapter->link_active = FALSE; for (int i = 0; i < adapter->num_queues; i++, txr++) - txr->watchdog_timer = FALSE; + txr->watchdog_check = FALSE; } } @@ -2113,6 +2159,9 @@ ixgbe_allocate_legacy(struct adapter *adapter) TASK_INIT(&adapter->link_task, 0, ixgbe_handle_link, adapter); TASK_INIT(&adapter->mod_task, 0, ixgbe_handle_mod, adapter); TASK_INIT(&adapter->msf_task, 0, ixgbe_handle_msf, adapter); +#ifdef IXGBE_FDIR + TASK_INIT(&adapter->fdir_task, 0, ixgbe_reinit_fdir, adapter); +#endif adapter->tq = taskqueue_create_fast("ixgbe_link", M_NOWAIT, taskqueue_thread_enqueue, &adapter->tq); taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s linkq", @@ -2242,6 +2291,9 @@ ixgbe_allocate_msix(struct adapter *adapter) TASK_INIT(&adapter->link_task, 0, ixgbe_handle_link, adapter); TASK_INIT(&adapter->mod_task, 0, ixgbe_handle_mod, adapter); TASK_INIT(&adapter->msf_task, 0, ixgbe_handle_msf, adapter); +#ifdef IXGBE_FDIR + TASK_INIT(&adapter->fdir_task, 0, ixgbe_reinit_fdir, adapter); +#endif adapter->tq = taskqueue_create_fast("ixgbe_link", M_NOWAIT, taskqueue_thread_enqueue, &adapter->tq); taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s linkq", @@ -2432,65 +2484,15 @@ mem: /********************************************************************* * - * Initialize the hardware to a configuration as specified by the - * adapter structure. The controller is reset, the EEPROM is - * verified, the MAC address is set, then the shared initialization - * routines are called. - * - **********************************************************************/ -static int -ixgbe_hardware_init(struct adapter *adapter) -{ - device_t dev = adapter->dev; - u32 ret; - u16 csum; - - csum = 0; - /* Issue a global reset */ - adapter->hw.adapter_stopped = FALSE; - ixgbe_stop_adapter(&adapter->hw); - - /* Make sure we have a good EEPROM before we read from it */ - if (ixgbe_validate_eeprom_checksum(&adapter->hw, &csum) < 0) { - device_printf(dev,"The EEPROM Checksum Is Not Valid\n"); - return (EIO); - } - - /* Get Hardware Flow Control setting */ - adapter->hw.fc.requested_mode = ixgbe_fc_full; - adapter->hw.fc.pause_time = IXGBE_FC_PAUSE; - adapter->hw.fc.low_water = IXGBE_FC_LO; - adapter->hw.fc.high_water = IXGBE_FC_HI; - adapter->hw.fc.send_xon = TRUE; - - ret = ixgbe_init_hw(&adapter->hw); - if (ret == IXGBE_ERR_EEPROM_VERSION) { - device_printf(dev, "This device is a pre-production adapter/" - "LOM. Please be aware there may be issues associated " - "with your hardware.\n If you are experiencing problems " - "please contact your Intel or hardware representative " - "who provided you with this hardware.\n"); - } else if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) { - device_printf(dev,"Unsupported SFP+ Module\n"); - return (EIO); - } else if (ret != 0 ) { - device_printf(dev,"Hardware Initialization Failure\n"); - return (EIO); - } - - return (0); -} - -/********************************************************************* - * * Setup networking device structure and register an interface. * **********************************************************************/ static void ixgbe_setup_interface(device_t dev, struct adapter *adapter) { - struct ifnet *ifp; struct ixgbe_hw *hw = &adapter->hw; + struct ifnet *ifp; + INIT_DEBUGOUT("ixgbe_setup_interface: begin"); ifp = adapter->ifp = if_alloc(IFT_ETHER); @@ -2522,17 +2524,12 @@ ixgbe_setup_interface(device_t dev, struct adapter *adapter) ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_TSO4 | IFCAP_VLAN_HWCSUM; ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU; - ifp->if_capabilities |= IFCAP_JUMBO_MTU | IFCAP_LRO; + ifp->if_capabilities |= IFCAP_JUMBO_MTU; + if (ixgbe_header_split) + ifp->if_capabilities |= IFCAP_LRO; ifp->if_capenable = ifp->if_capabilities; - if (hw->device_id == IXGBE_DEV_ID_82598AT) - ixgbe_setup_link_speed(hw, (IXGBE_LINK_SPEED_10GB_FULL | - IXGBE_LINK_SPEED_1GB_FULL), TRUE, TRUE); - else - ixgbe_setup_link_speed(hw, IXGBE_LINK_SPEED_10GB_FULL, - TRUE, FALSE); - /* * Specify the media types supported by this adapter and register * callbacks to update media and link information @@ -2549,7 +2546,51 @@ ixgbe_setup_interface(device_t dev, struct adapter *adapter) } ifmedia_add(&adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL); ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO); + return; +} + +static void +ixgbe_config_link(struct adapter *adapter) +{ + struct ixgbe_hw *hw = &adapter->hw; + u32 autoneg, err = 0; + bool sfp, negotiate; + switch (hw->phy.type) { + case ixgbe_phy_sfp_avago: + case ixgbe_phy_sfp_ftl: + case ixgbe_phy_sfp_intel: + case ixgbe_phy_sfp_unknown: + case ixgbe_phy_tw_tyco: + case ixgbe_phy_tw_unknown: + sfp = TRUE; + default: + sfp = FALSE; + } + + if (sfp) { + if (hw->phy.multispeed_fiber) { + hw->mac.ops.setup_sfp(hw); + taskqueue_enqueue(adapter->tq, &adapter->msf_task); + } else + taskqueue_enqueue(adapter->tq, &adapter->mod_task); + } else { + if (hw->mac.ops.check_link) + err = ixgbe_check_link(hw, &autoneg, + &adapter->link_up, FALSE); + if (err) + goto out; + autoneg = hw->phy.autoneg_advertised; + if ((!autoneg) && (hw->mac.ops.get_link_capabilities)) + err = hw->mac.ops.get_link_capabilities(hw, + &autoneg, &negotiate); + if (err) + goto out; + if (hw->mac.ops.setup_link) + err = hw->mac.ops.setup_link(hw, autoneg, + negotiate, adapter->link_up); + } +out: return; } @@ -2833,8 +2874,8 @@ ixgbe_setup_transmit_ring(struct tx_ring *txr) bzero((void *)txr->tx_base, (sizeof(union ixgbe_adv_tx_desc)) * adapter->num_tx_desc); /* Reset indices */ - txr->next_avail_tx_desc = 0; - txr->next_tx_to_clean = 0; + txr->next_avail_desc = 0; + txr->next_to_clean = 0; /* Free any existing tx buffers. */ txbuf = txr->tx_buffers; @@ -2850,6 +2891,12 @@ ixgbe_setup_transmit_ring(struct tx_ring *txr) txbuf->eop_index = -1; } +#ifdef IXGBE_FDIR + /* Set the rate at which we sample packets */ + if (adapter->hw.mac.type == ixgbe_mac_82599EB) + txr->atr_sample = atr_sample_rate; +#endif + /* Set number of descriptors available */ txr->tx_avail = adapter->num_tx_desc; @@ -2888,6 +2935,7 @@ ixgbe_initialize_transmit_units(struct adapter *adapter) for (int i = 0; i < adapter->num_queues; i++, txr++) { u64 tdba = txr->txdma.dma_paddr; + u32 txctrl; IXGBE_WRITE_REG(hw, IXGBE_TDBAL(i), (tdba & 0x00000000ffffffffULL)); @@ -2901,15 +2949,43 @@ ixgbe_initialize_transmit_units(struct adapter *adapter) /* Setup Transmit Descriptor Cmd Settings */ txr->txd_cmd = IXGBE_TXD_CMD_IFCS; + txr->watchdog_check = FALSE; + + /* Disable Head Writeback */ + switch (hw->mac.type) { + case ixgbe_mac_82598EB: + txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(i)); + break; + case ixgbe_mac_82599EB: + default: + txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i)); + break; + } + txctrl &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN; + switch (hw->mac.type) { + case ixgbe_mac_82598EB: + IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(i), txctrl); + break; + case ixgbe_mac_82599EB: + default: + IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), txctrl); + break; + } - txr->watchdog_timer = 0; } if (hw->mac.type == ixgbe_mac_82599EB) { - u32 dmatxctl; + u32 dmatxctl, rttdcs; dmatxctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL); dmatxctl |= IXGBE_DMATXCTL_TE; IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, dmatxctl); + /* Disable arbiter to set MTQC */ + rttdcs = IXGBE_READ_REG(hw, IXGBE_RTTDCS); + rttdcs |= IXGBE_RTTDCS_ARBDIS; + IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs); + IXGBE_WRITE_REG(hw, IXGBE_MTQC, IXGBE_MTQC_64Q_1PB); + rttdcs &= ~IXGBE_RTTDCS_ARBDIS; + IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs); } return; @@ -3009,7 +3085,7 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp) u16 etype; u8 ipproto = 0; bool offload = TRUE; - int ctxd = txr->next_avail_tx_desc; + int ctxd = txr->next_avail_desc; u16 vtag = 0; @@ -3099,7 +3175,7 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp) /* We've consumed the first desc, adjust counters */ if (++ctxd == adapter->num_tx_desc) ctxd = 0; - txr->next_avail_tx_desc = ctxd; + txr->next_avail_desc = ctxd; --txr->tx_avail; return (offload); @@ -3140,7 +3216,7 @@ ixgbe_tso_setup(struct tx_ring *txr, struct mbuf *mp, u32 *paylen) if (mp->m_len < ehdrlen + sizeof(struct ip) + sizeof(struct tcphdr)) return FALSE; - ctxd = txr->next_avail_tx_desc; + ctxd = txr->next_avail_desc; tx_buffer = &txr->tx_buffers[ctxd]; TXD = (struct ixgbe_adv_tx_context_desc *) &txr->tx_base[ctxd]; @@ -3188,10 +3264,88 @@ ixgbe_tso_setup(struct tx_ring *txr, struct mbuf *mp, u32 *paylen) ctxd = 0; txr->tx_avail--; - txr->next_avail_tx_desc = ctxd; + txr->next_avail_desc = ctxd; return TRUE; } +#ifdef IXGBE_FDIR +/* +** This routine parses packet headers so that Flow +** Director can make a hashed filter table entry +** allowing traffic flows to be identified and kept +** on the same cpu. This would be a performance +** hit, but we only do it at IXGBE_FDIR_RATE of +** packets. +*/ +static void +ixgbe_atr(struct tx_ring *txr, struct mbuf *mp) +{ + struct adapter *adapter = txr->adapter; + struct ixgbe_atr_input atr_input; + struct ip *ip; + struct tcphdr *th; + struct udphdr *uh; + struct ether_vlan_header *eh; + int ehdrlen, ip_hlen; + u16 etype, vlan_id, src_port, dst_port, flex_bytes; + u32 src_ipv4_addr, dst_ipv4_addr; + u8 l4type = 0, ipproto = 0; + + eh = mtod(mp, struct ether_vlan_header *); + if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) + ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; + else + ehdrlen = ETHER_HDR_LEN; + etype = ntohs(eh->evl_proto); + + /* Only handling IPv4 */ + if (etype != ETHERTYPE_IP) + return; + + ip = (struct ip *)(mp->m_data + ehdrlen); + ipproto = ip->ip_p; + ip_hlen = ip->ip_hl << 2; + src_port = dst_port = 0; + + /* check if we're UDP or TCP */ + switch (ipproto) { + case IPPROTO_TCP: + th = (struct tcphdr *)((caddr_t)ip + ip_hlen); + src_port = th->th_sport; + dst_port = th->th_dport; + l4type |= IXGBE_ATR_L4TYPE_TCP; + break; + case IPPROTO_UDP: + uh = (struct udphdr *)((caddr_t)ip + ip_hlen); + src_port = uh->uh_sport; + dst_port = uh->uh_dport; + l4type |= IXGBE_ATR_L4TYPE_UDP; + break; + default: + return; + } + + memset(&atr_input, 0, sizeof(struct ixgbe_atr_input)); + + vlan_id = htole16(mp->m_pkthdr.ether_vtag); + src_ipv4_addr = ip->ip_src.s_addr; + dst_ipv4_addr = ip->ip_dst.s_addr; + flex_bytes = etype; + + ixgbe_atr_set_vlan_id_82599(&atr_input, vlan_id); + ixgbe_atr_set_src_port_82599(&atr_input, dst_port); + ixgbe_atr_set_dst_port_82599(&atr_input, src_port); + ixgbe_atr_set_flex_byte_82599(&atr_input, flex_bytes); + ixgbe_atr_set_l4type_82599(&atr_input, l4type); + /* src and dst are inverted, think how the receiver sees them */ + ixgbe_atr_set_src_ipv4_82599(&atr_input, dst_ipv4_addr); + ixgbe_atr_set_dst_ipv4_82599(&atr_input, src_ipv4_addr); + + /* This assumes the Rx queue and Tx queue are bound to the same CPU */ + ixgbe_fdir_add_signature_filter_82599(&adapter->hw, + &atr_input, txr->msix); +} +#endif /********************************************************************** * @@ -3203,10 +3357,9 @@ ixgbe_tso_setup(struct tx_ring *txr, struct mbuf *mp, u32 *paylen) static boolean_t ixgbe_txeof(struct tx_ring *txr) { - struct adapter * adapter = txr->adapter; + struct adapter *adapter = txr->adapter; struct ifnet *ifp = adapter->ifp; - u32 first, last, done, num_avail; - u32 cleaned = 0; + u32 first, last, done; struct ixgbe_tx_buf *tx_buffer; struct ixgbe_legacy_tx_desc *tx_desc, *eop_desc; @@ -3215,17 +3368,15 @@ ixgbe_txeof(struct tx_ring *txr) if (txr->tx_avail == adapter->num_tx_desc) return FALSE; - num_avail = txr->tx_avail; - first = txr->next_tx_to_clean; - + first = txr->next_to_clean; tx_buffer = &txr->tx_buffers[first]; /* For cleanup we just use legacy struct */ tx_desc = (struct ixgbe_legacy_tx_desc *)&txr->tx_base[first]; last = tx_buffer->eop_index; if (last == -1) return FALSE; - eop_desc = (struct ixgbe_legacy_tx_desc *)&txr->tx_base[last]; + /* ** Get the index of the first descriptor ** BEYOND the EOP and call that 'done'. @@ -3247,7 +3398,7 @@ ixgbe_txeof(struct tx_ring *txr) tx_desc->upper.data = 0; tx_desc->lower.data = 0; tx_desc->buffer_addr = 0; - num_avail++; cleaned++; + ++txr->tx_avail; if (tx_buffer->m_head) { ifp->if_opackets++; @@ -3261,6 +3412,7 @@ ixgbe_txeof(struct tx_ring *txr) tx_buffer->map = NULL; } tx_buffer->eop_index = -1; + txr->watchdog_time = ticks; if (++first == adapter->num_tx_desc) first = 0; @@ -3283,7 +3435,7 @@ ixgbe_txeof(struct tx_ring *txr) bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - txr->next_tx_to_clean = first; + txr->next_to_clean = first; /* * If we have enough room, clear IFF_DRV_OACTIVE to tell the stack that @@ -3291,98 +3443,101 @@ ixgbe_txeof(struct tx_ring *txr) * clear the timeout. Otherwise, if some descriptors have been freed, * restart the timeout. */ - if (num_avail > IXGBE_TX_CLEANUP_THRESHOLD) { + if (txr->tx_avail > IXGBE_TX_CLEANUP_THRESHOLD) { ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - /* If all are clean turn off the timer */ - if (num_avail == adapter->num_tx_desc) { - txr->watchdog_timer = 0; - txr->tx_avail = num_avail; + if (txr->tx_avail == adapter->num_tx_desc) { + txr->watchdog_check = FALSE; return FALSE; } } - /* Some were cleaned, so reset timer */ - if (cleaned) - txr->watchdog_timer = IXGBE_TX_TIMEOUT; - txr->tx_avail = num_avail; return TRUE; } /********************************************************************* * - * Get a buffer from system mbuf buffer pool. + * Refresh mbuf buffers for a range of descriptors * **********************************************************************/ static int -ixgbe_get_buf(struct rx_ring *rxr, int i, u8 clean) +ixgbe_get_buf(struct rx_ring *rxr, int first, int limit) { struct adapter *adapter = rxr->adapter; bus_dma_segment_t seg[2]; struct ixgbe_rx_buf *rxbuf; struct mbuf *mh, *mp; bus_dmamap_t map; - int nsegs, error; - int merr = 0; + int i, nsegs, error; + i = first; + while (i != limit) { + rxbuf = &rxr->rx_buffers[i]; - rxbuf = &rxr->rx_buffers[i]; + if (rxbuf->m_head == NULL) { + mh = m_gethdr(M_DONTWAIT, MT_DATA); + if (mh == NULL) + goto failure; + } else /* reuse */ + mh = rxbuf->m_head; - /* First get our header and payload mbuf */ - if (clean & IXGBE_CLEAN_HDR) { - mh = m_gethdr(M_DONTWAIT, MT_DATA); - if (mh == NULL) - goto remap; - } else /* reuse */ - mh = rxr->rx_buffers[i].m_head; + mh->m_len = MHLEN; + mh->m_flags |= M_PKTHDR; - mh->m_len = MHLEN; - mh->m_flags |= M_PKTHDR; + if (rxbuf->m_pack == NULL) { + mp = m_getjcl(M_DONTWAIT, MT_DATA, + M_PKTHDR, adapter->rx_mbuf_sz); + if (mp == NULL) + goto failure; + mp->m_len = adapter->rx_mbuf_sz; + mp->m_flags &= ~M_PKTHDR; + } else { /* reusing */ + mp = rxbuf->m_pack; + mp->m_len = adapter->rx_mbuf_sz; + mp->m_flags &= ~M_PKTHDR; + } - if (clean & IXGBE_CLEAN_PKT) { - mp = m_getjcl(M_DONTWAIT, MT_DATA, - M_PKTHDR, adapter->rx_mbuf_sz); - if (mp == NULL) - goto remap; - mp->m_len = adapter->rx_mbuf_sz; - mp->m_flags &= ~M_PKTHDR; - } else { /* reusing */ - mp = rxr->rx_buffers[i].m_pack; - mp->m_len = adapter->rx_mbuf_sz; - mp->m_flags &= ~M_PKTHDR; - } - /* - ** Need to create a chain for the following - ** dmamap call at this point. - */ - mh->m_next = mp; - mh->m_pkthdr.len = mh->m_len + mp->m_len; + /* + ** Need to create a chain for the following + ** dmamap call at this point. + */ + mh->m_next = mp; + mh->m_pkthdr.len = mh->m_len + mp->m_len; - /* Get the memory mapping */ - error = bus_dmamap_load_mbuf_sg(rxr->rxtag, - rxr->spare_map, mh, seg, &nsegs, BUS_DMA_NOWAIT); - if (error != 0) { - printf("GET BUF: dmamap load failure - %d\n", error); - m_free(mh); - return (error); - } + /* Get the memory mapping */ + error = bus_dmamap_load_mbuf_sg(rxr->rxtag, + rxr->spare_map, mh, seg, &nsegs, BUS_DMA_NOWAIT); + if (error != 0) { + printf("GET BUF: dmamap load failure - %d\n", error); + m_free(mh); + return (error); + } - /* Unload old mapping and update buffer struct */ - if (rxbuf->m_head != NULL) - bus_dmamap_unload(rxr->rxtag, rxbuf->map); - map = rxbuf->map; - rxbuf->map = rxr->spare_map; - rxr->spare_map = map; - rxbuf->m_head = mh; - rxbuf->m_pack = mp; - bus_dmamap_sync(rxr->rxtag, - rxbuf->map, BUS_DMASYNC_PREREAD); + /* Unload old mapping and update buffer struct */ + if (rxbuf->m_head != NULL) + bus_dmamap_unload(rxr->rxtag, rxbuf->map); + map = rxbuf->map; + rxbuf->map = rxr->spare_map; + rxr->spare_map = map; + rxbuf->m_head = mh; + rxbuf->m_pack = mp; + bus_dmamap_sync(rxr->rxtag, + rxbuf->map, BUS_DMASYNC_PREREAD); - /* Update descriptor */ - rxr->rx_base[i].read.hdr_addr = htole64(seg[0].ds_addr); - rxr->rx_base[i].read.pkt_addr = htole64(seg[1].ds_addr); + /* Update descriptor */ + rxr->rx_base[i].read.hdr_addr = htole64(seg[0].ds_addr); + rxr->rx_base[i].read.pkt_addr = htole64(seg[1].ds_addr); + + /* Calculate next index */ + if (++i == adapter->num_rx_desc) + i = 0; + } return (0); +failure: + panic("GET BUF: ENOBUFS\n"); + +#if 0 /* ** If we get here, we have an mbuf resource ** issue, so we discard the incoming packet @@ -3415,9 +3570,9 @@ remap: rxr->rx_base[i].read.pkt_addr = htole64(seg[1].ds_addr); return (merr); +#endif } - /********************************************************************* * * Allocate memory for rx_buffer structures. Since we use one @@ -3491,6 +3646,62 @@ fail: return (error); } + +/* +** Used to detect a descriptor that has +** been merged by Hardware RSC. +*/ +static inline u32 +ixgbe_rsc_count(union ixgbe_adv_rx_desc *rx) +{ + return (le32toh(rx->wb.lower.lo_dword.data) & + IXGBE_RXDADV_RSCCNT_MASK) >> IXGBE_RXDADV_RSCCNT_SHIFT; +} + +/********************************************************************* + * + * Initialize Hardware RSC (LRO) feature on 82599 + * for an RX ring, this is toggled by the LRO capability + * even though it is transparent to the stack. + * + **********************************************************************/ +static void +ixgbe_setup_hw_rsc(struct rx_ring *rxr) +{ + struct adapter *adapter = rxr->adapter; + struct ixgbe_hw *hw = &adapter->hw; + u32 rscctrl, rdrxctl; + + rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL); + rdrxctl &= ~IXGBE_RDRXCTL_RSCFRSTSIZE; + rdrxctl |= IXGBE_RDRXCTL_CRCSTRIP; + IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl); + + rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(rxr->me)); + rscctrl |= IXGBE_RSCCTL_RSCEN; + /* + ** Limit the total number of descriptors that + ** can be combined, so it does not exceed 64K + */ + if (adapter->rx_mbuf_sz == MCLBYTES) + rscctrl |= IXGBE_RSCCTL_MAXDESC_16; + else /* using 4K clusters */ + rscctrl |= IXGBE_RSCCTL_MAXDESC_8; + IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(rxr->me), rscctrl); + + /* Enable TCP header recognition */ + IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(0), + (IXGBE_READ_REG(hw, IXGBE_PSRTYPE(0)) | + IXGBE_PSRTYPE_TCPHDR)); + + /* Disable RSC for ACK packets */ + IXGBE_WRITE_REG(hw, IXGBE_RSCDBU, + (IXGBE_RSCDBU_RSCACKDIS | IXGBE_READ_REG(hw, IXGBE_RSCDBU))); + + rxr->hw_rsc = TRUE; +} + + /********************************************************************* * * Initialize a receive ring and its buffers. @@ -3503,8 +3714,9 @@ ixgbe_setup_receive_ring(struct rx_ring *rxr) struct ifnet *ifp; device_t dev; struct ixgbe_rx_buf *rxbuf; + bus_dma_segment_t seg[2]; struct lro_ctrl *lro = &rxr->lro; - int j, rsize; + int rsize, nsegs, error; adapter = rxr->adapter; ifp = adapter->ifp; @@ -3533,48 +3745,74 @@ ixgbe_setup_receive_ring(struct rx_ring *rxr) } } - /* Now refresh the mbufs */ - for (j = 0; j < adapter->num_rx_desc; j++) { - if (ixgbe_get_buf(rxr, j, IXGBE_CLEAN_ALL) == ENOBUFS) { - rxr->rx_buffers[j].m_head = NULL; - rxr->rx_buffers[j].m_pack = NULL; - rxr->rx_base[j].read.hdr_addr = 0; - rxr->rx_base[j].read.pkt_addr = 0; - goto fail; - } + /* Now replenish the mbufs */ + for (int j = 0; j != adapter->num_rx_desc; ++j) { + + rxbuf = &rxr->rx_buffers[j]; + rxbuf->m_head = m_gethdr(M_DONTWAIT, MT_DATA); + if (rxbuf->m_head == NULL) + panic("RX ring hdr initialization failed!\n"); + rxbuf->m_head->m_len = MHLEN; + rxbuf->m_head->m_flags |= M_PKTHDR; + rxbuf->m_head->m_pkthdr.len = rxbuf->m_head->m_len; + + rxbuf->m_pack = m_getjcl(M_DONTWAIT, MT_DATA, + M_PKTHDR, adapter->rx_mbuf_sz); + if (rxbuf->m_pack == NULL) + panic("RX ring pkt initialization failed!\n"); + rxbuf->m_pack->m_len = adapter->rx_mbuf_sz; + rxbuf->m_head->m_next = rxbuf->m_pack; + rxbuf->m_head->m_pkthdr.len += rxbuf->m_pack->m_len; + + /* Get the memory mapping */ + error = bus_dmamap_load_mbuf_sg(rxr->rxtag, + rxbuf->map, rxbuf->m_head, seg, + &nsegs, BUS_DMA_NOWAIT); + if (error != 0) + panic("RX ring dma initialization failed!\n"); + bus_dmamap_sync(rxr->rxtag, + rxbuf->map, BUS_DMASYNC_PREREAD); + + /* Update descriptor */ + rxr->rx_base[j].read.hdr_addr = htole64(seg[0].ds_addr); + rxr->rx_base[j].read.pkt_addr = htole64(seg[1].ds_addr); } + /* Setup our descriptor indices */ rxr->next_to_check = 0; - rxr->last_cleaned = 0; + rxr->last_refreshed = 0; rxr->lro_enabled = FALSE; /* Use header split if configured */ if (ixgbe_header_split) rxr->hdr_split = TRUE; + else + ifp->if_capabilities &= ~IFCAP_LRO; bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); /* - ** Now set up the LRO interface, we - ** also only do head split when LRO - ** is enabled, since so often they - ** are undesireable in similar setups. + ** Now set up the LRO interface: + ** 82598 uses software LRO, the + ** 82599 on the other hand uses a + ** hardware assist to do the same. + ** We only do LRO when header split + ** is enabled, its simpler that way. */ - if (ifp->if_capenable & IFCAP_LRO) { + if ((ifp->if_capenable & IFCAP_LRO) && (rxr->hdr_split)) { int err = tcp_lro_init(lro); - if (err) { - INIT_DEBUGOUT("LRO Initialization failed!\n"); - goto fail; - } - INIT_DEBUGOUT("RX LRO Initialized\n"); + if (err) + panic("LRO Initialization failed!\n"); + INIT_DEBUGOUT("RX Soft LRO Initialized\n"); rxr->lro_enabled = TRUE; lro->ifp = adapter->ifp; + ixgbe_setup_hw_rsc(rxr); } return (0); - +#if 0 fail: /* * We need to clean up any buffers allocated @@ -3591,6 +3829,7 @@ fail: } } return (ENOBUFS); +#endif } /********************************************************************* @@ -3844,7 +4083,7 @@ ixgbe_rxeof(struct rx_ring *rxr, int count) struct ifnet *ifp = adapter->ifp; struct lro_ctrl *lro = &rxr->lro; struct lro_entry *queued; - int i; + int i, processed = 0; u32 staterr; union ixgbe_adv_rx_desc *cur; @@ -3865,31 +4104,69 @@ ixgbe_rxeof(struct rx_ring *rxr, int count) while ((staterr & IXGBE_RXD_STAT_DD) && (count != 0) && (ifp->if_drv_flags & IFF_DRV_RUNNING)) { - struct mbuf *sendmp, *mh, *mp; - u16 hlen, plen, hdr, vtag; - u8 dopayload, accept_frame, eop; + struct mbuf *sendmp, *mh, *mp, *nh, *np; + struct ixgbe_rx_buf *nxtbuf; + u32 rsc; + u16 hlen, plen, hdr, nextp, vtag; + bool accept_frame, eop; - accept_frame = 1; - hlen = plen = vtag = 0; - sendmp = mh = mp = NULL; + accept_frame = TRUE; + hlen = plen = rsc = nextp = 0; + sendmp = mh = mp = nh = np = NULL; /* Sync the buffers */ bus_dmamap_sync(rxr->rxtag, rxr->rx_buffers[i].map, BUS_DMASYNC_POSTREAD); + mh = rxr->rx_buffers[i].m_head; + mp = rxr->rx_buffers[i].m_pack; + vtag = le16toh(cur->wb.upper.vlan); + eop = ((staterr & IXGBE_RXD_STAT_EOP) != 0); + + if (!eop) { + /* + ** On 82599 which supports a hardware + ** LRO (called HW RSC), packets need + ** not be fragmented across sequential + ** descriptors, rather the next descriptor + ** is indicated in bits of the current. + ** This also means that we might proceses + ** more than one packet at a time, something + ** that has never been true before, it + ** required eliminating global chain pointers + ** in favor of what we are doing here. -jfv + */ + if (rxr->hw_rsc == TRUE) { + rsc = ixgbe_rsc_count(cur); + rxr->rsc_num += (rsc - 1); + } + if (rsc) { + nextp = ((staterr & + IXGBE_RXDADV_NEXTP_MASK) >> + IXGBE_RXDADV_NEXTP_SHIFT); + } else { + nextp = i + 1; + if (nextp == adapter->num_rx_desc) + nextp = 0; + } + nxtbuf = &rxr->rx_buffers[nextp]; + prefetch(nxtbuf); + } /* ** The way the hardware is configured to ** split, it will ONLY use the header buffer ** when header split is enabled, otherwise we - ** get normal behavior, ie, both header and - ** payload are DMA'd into the payload buffer. + ** get legacy behavior, ie, both header and + ** payload are DMA'd into JUST the payload buffer. + ** + ** Rather than using the fmp/lmp global pointers + ** we now keep the head of a packet chain in the + ** m_nextpkt pointer and pass this along from one + ** descriptor to the next, until we get EOP. ** - ** The fmp test is to catch the case where a - ** packet spans multiple descriptors, in that - ** case only the first header is valid. */ - if ((rxr->hdr_split) && (rxr->fmp == NULL)){ + if ((rxr->hdr_split) && (mh->m_nextpkt == NULL)) { hdr = le16toh(cur-> wb.lower.lo_dword.hs_rss.hdr_info); hlen = (hdr & IXGBE_RXDADV_HDRBUFLEN_MASK) >> @@ -3897,182 +4174,168 @@ ixgbe_rxeof(struct rx_ring *rxr, int count) if (hlen > IXGBE_RX_HDR) hlen = IXGBE_RX_HDR; plen = le16toh(cur->wb.upper.length); - /* Handle the header mbuf */ - mh = rxr->rx_buffers[i].m_head; mh->m_len = hlen; - dopayload = IXGBE_CLEAN_HDR; + mh->m_flags |= M_PKTHDR; + mh->m_next = NULL; + mh->m_pkthdr.len = mh->m_len; + /* Null this so getbuf replenishes */ + rxr->rx_buffers[i].m_head = NULL; /* ** Get the payload length, this ** could be zero if its a small ** packet. */ if (plen) { - mp = rxr->rx_buffers[i].m_pack; mp->m_len = plen; mp->m_next = NULL; mp->m_flags &= ~M_PKTHDR; mh->m_next = mp; - mh->m_flags |= M_PKTHDR; - dopayload = IXGBE_CLEAN_ALL; + mh->m_pkthdr.len += mp->m_len; + /* Null this so getbuf replenishes */ + rxr->rx_buffers[i].m_pack = NULL; rxr->rx_split_packets++; - } else { /* small packets */ - mh->m_flags &= ~M_PKTHDR; - mh->m_next = NULL; + } + /* Setup the forward chain */ + if (eop == 0) { + nh = rxr->rx_buffers[nextp].m_head; + np = rxr->rx_buffers[nextp].m_pack; + nh->m_nextpkt = mh; + if (plen) + mp->m_next = np; + else + mh->m_next = np; + } else { + sendmp = mh; + if (staterr & IXGBE_RXD_STAT_VP) { + sendmp->m_pkthdr.ether_vtag = vtag; + sendmp->m_flags |= M_VLANTAG; + } } } else { /* ** Either no header split, or a ** secondary piece of a fragmented - ** split packet. + ** packet. */ - mh = rxr->rx_buffers[i].m_pack; - mh->m_flags |= M_PKTHDR; - mh->m_len = le16toh(cur->wb.upper.length); - dopayload = IXGBE_CLEAN_PKT; + mp->m_len = le16toh(cur->wb.upper.length); + rxr->rx_buffers[i].m_pack = NULL; + /* stored head pointer */ + sendmp = mh->m_nextpkt; + if (sendmp != NULL) { + sendmp->m_pkthdr.len += mp->m_len; + sendmp->m_nextpkt = NULL; + } else { + /* first desc of a non-ps chain */ + sendmp = mp; + sendmp->m_flags |= M_PKTHDR; + sendmp->m_pkthdr.len = mp->m_len; + if (staterr & IXGBE_RXD_STAT_VP) { + sendmp->m_pkthdr.ether_vtag = vtag; + sendmp->m_flags |= M_VLANTAG; + } + } + /* Carry head forward */ + if (eop == 0) { + nh = rxr->rx_buffers[nextp].m_head; + np = rxr->rx_buffers[nextp].m_pack; + nh->m_nextpkt = sendmp; + mp->m_next = np; + sendmp = NULL; + } + mh->m_nextpkt = NULL; } - if (staterr & IXGBE_RXD_STAT_EOP) { - count--; - eop = 1; - } else - eop = 0; - -#ifdef IXGBE_IEEE1588 - This code needs to be converted to work here - ----------------------------------------------------- - if (unlikely(staterr & IXGBE_RXD_STAT_TS)) { - u64 regval; - u64 ns; -// Create an mtag and set it up - struct skb_shared_hwtstamps *shhwtstamps = - skb_hwtstamps(skb); - - rd32(IXGBE_TSYNCRXCTL) & IXGBE_TSYNCRXCTL_VALID), - "igb: no RX time stamp available for time stamped packet"); - regval = rd32(IXGBE_RXSTMPL); - regval |= (u64)rd32(IXGBE_RXSTMPH) << 32; -// Do time conversion from the register - ns = timecounter_cyc2time(&adapter->clock, regval); - clocksync_update(&adapter->sync, ns); - memset(shhwtstamps, 0, sizeof(*shhwtstamps)); - shhwtstamps->hwtstamp = ns_to_ktime(ns); - shhwtstamps->syststamp = - clocksync_hw2sys(&adapter->sync, ns); - } -#endif - if (staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK) - accept_frame = 0; + accept_frame = FALSE; if (accept_frame) { - /* - ** Save the vlan id, because get_buf will - ** clobber the writeback descriptor... - */ - vtag = le16toh(cur->wb.upper.vlan); - if (ixgbe_get_buf(rxr, i, dopayload) != 0) { - ifp->if_iqdrops++; - goto discard; - } - /* Initial frame - setup */ - if (rxr->fmp == NULL) { - mh->m_flags |= M_PKTHDR; - mh->m_pkthdr.len = mh->m_len; - rxr->fmp = mh; /* Store the first mbuf */ - rxr->lmp = mh; - if (mp) { /* Add payload if split */ - mh->m_pkthdr.len += mp->m_len; - rxr->lmp = mh->m_next; - } - } else { - /* Chain mbuf's together */ - mh->m_flags &= ~M_PKTHDR; - rxr->lmp->m_next = mh; - rxr->lmp = rxr->lmp->m_next; - rxr->fmp->m_pkthdr.len += mh->m_len; - } - + ++processed; if (eop) { - rxr->fmp->m_pkthdr.rcvif = ifp; + --count; + sendmp->m_pkthdr.rcvif = ifp; ifp->if_ipackets++; rxr->rx_packets++; /* capture data for AIM */ - rxr->bytes += rxr->fmp->m_pkthdr.len; + rxr->bytes += sendmp->m_pkthdr.len; rxr->rx_bytes += rxr->bytes; if (ifp->if_capenable & IFCAP_RXCSUM) - ixgbe_rx_checksum(staterr, rxr->fmp); + ixgbe_rx_checksum(staterr, sendmp); else - rxr->fmp->m_pkthdr.csum_flags = 0; - if (staterr & IXGBE_RXD_STAT_VP) { - rxr->fmp->m_pkthdr.ether_vtag = vtag; - rxr->fmp->m_flags |= M_VLANTAG; - } + sendmp->m_pkthdr.csum_flags = 0; #if __FreeBSD_version >= 800000 - rxr->fmp->m_pkthdr.flowid = curcpu; - rxr->fmp->m_flags |= M_FLOWID; + /* Get the RSS Hash */ + sendmp->m_pkthdr.flowid = + le16toh(cur->wb.lower.hi_dword.rss); + sendmp->m_flags |= M_FLOWID; #endif - sendmp = rxr->fmp; - rxr->fmp = NULL; - rxr->lmp = NULL; } } else { ifp->if_ierrors++; -discard: /* Reuse loaded DMA map and just update mbuf chain */ - if (hlen) { - mh = rxr->rx_buffers[i].m_head; - mh->m_len = MHLEN; - mh->m_next = NULL; - } - mp = rxr->rx_buffers[i].m_pack; + mh->m_len = MHLEN; + mh->m_flags |= M_PKTHDR; + mh->m_next = NULL; mp->m_len = mp->m_pkthdr.len = adapter->rx_mbuf_sz; mp->m_data = mp->m_ext.ext_buf; + if (mp->m_next) { /* Free chain */ + sendmp = mp->m_next; + m_free(sendmp); + } mp->m_next = NULL; if (adapter->max_frame_size <= (MCLBYTES - ETHER_ALIGN)) m_adj(mp, ETHER_ALIGN); - if (rxr->fmp != NULL) { - /* handles the whole chain */ - m_freem(rxr->fmp); - rxr->fmp = NULL; - rxr->lmp = NULL; - } sendmp = NULL; } bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - rxr->last_cleaned = i; /* for updating tail */ - + rxr->last_refreshed = i; /* for updating tail */ if (++i == adapter->num_rx_desc) i = 0; + /* Prefetch next descriptor */ + cur = &rxr->rx_base[i]; + prefetch(cur); /* ** Now send up to the stack, - ** note the the value of next_to_check - ** is safe because we keep the RX lock - ** thru this call. + ** note that the RX lock is + ** held thru this call. */ if (sendmp != NULL) { /* ** Send to the stack if: - ** - LRO not enabled, or - ** - no LRO resources, or - ** - lro enqueue fails + ** - Soft LRO not enabled, or + ** - no Soft LRO resources, or + ** - soft lro enqueue fails */ if ((!rxr->lro_enabled) || ((!lro->lro_cnt) || (tcp_lro_rx(lro, sendmp, 0)))) (*ifp->if_input)(ifp, sendmp); } - /* Get next descriptor */ - cur = &rxr->rx_base[i]; + /* Replenish every 8 max */ + if (processed == 8) { + ixgbe_get_buf(rxr, rxr->next_to_check, i); + processed = 0; + IXGBE_WRITE_REG(&adapter->hw, + IXGBE_RDT(rxr->me), rxr->last_refreshed); + rxr->next_to_check = i; + } + + /* Next iteration */ staterr = cur->wb.upper.status_error; } - rxr->next_to_check = i; - /* Advance the IXGB's Receive Queue "Tail Pointer" */ - IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDT(rxr->me), rxr->last_cleaned); + /* Replenish remaining work */ + if (processed != 0) { + ixgbe_get_buf(rxr, rxr->next_to_check, i); + processed = 0; + IXGBE_WRITE_REG(&adapter->hw, + IXGBE_RDT(rxr->me), rxr->last_refreshed); + } + + rxr->next_to_check = i; /* * Flush any outstanding LRO work @@ -4090,7 +4353,7 @@ discard: ** then schedule another interrupt. */ if (staterr & IXGBE_RXD_STAT_DD) { - ixgbe_rearm_rx_queues(adapter, (u64)(1 << rxr->msix)); + ixgbe_rearm_queues(adapter, (u64)(1 << rxr->msix)); return TRUE; } @@ -4244,6 +4507,9 @@ ixgbe_enable_intr(struct adapter *adapter) mask |= IXGBE_EIMS_ECC; mask |= IXGBE_EIMS_GPI_SDP1; mask |= IXGBE_EIMS_GPI_SDP2; +#ifdef IXGBE_FDIR + mask |= IXGBE_EIMS_FLOW_DIR; +#endif } IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask); @@ -4435,7 +4701,12 @@ ixgbe_handle_mod(void *context, int pending) "Unsupported SFP+ module type was detected.\n"); return; } - hw->mac.ops.setup_sfp(hw); + err = hw->mac.ops.setup_sfp(hw); + if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { + device_printf(dev, + "Setup failure - unsupported SFP+ module type.\n"); + return; + } taskqueue_enqueue(adapter->tq, &adapter->msf_task); return; } @@ -4450,18 +4721,40 @@ ixgbe_handle_msf(void *context, int pending) struct adapter *adapter = context; struct ixgbe_hw *hw = &adapter->hw; u32 autoneg; + bool negotiate; - if (hw->mac.ops.get_link_capabilities) - hw->mac.ops.get_link_capabilities(hw, &autoneg, - &hw->mac.autoneg); - if (hw->mac.ops.setup_link_speed) - hw->mac.ops.setup_link_speed(hw, autoneg, TRUE, TRUE); - ixgbe_check_link(&adapter->hw, - &adapter->link_speed, &adapter->link_up, 0); + autoneg = hw->phy.autoneg_advertised; + if ((!autoneg) && (hw->mac.ops.get_link_capabilities)) + hw->mac.ops.get_link_capabilities(hw, &autoneg, &negotiate); + if (hw->mac.ops.setup_link) + hw->mac.ops.setup_link(hw, autoneg, negotiate, TRUE); +#if 0 + ixgbe_check_link(&adapter->hw, &speed, &adapter->link_up, 0); ixgbe_update_link_status(adapter); +#endif return; } +#ifdef IXGBE_FDIR +/* +** Tasklet for reinitializing the Flow Director filter table +*/ +static void +ixgbe_reinit_fdir(void *context, int pending) +{ + struct adapter *adapter = context; + struct ifnet *ifp = adapter->ifp;; + + if (adapter->fdir_reinit != 1) /* Shouldn't happen */ + return; + ixgbe_reinit_fdir_tables_82599(&adapter->hw); + adapter->fdir_reinit = 0; + /* Restart the interface */ + ifp->if_drv_flags |= IFF_DRV_RUNNING; + return; +} +#endif + /********************************************************************** * * Update the board statistics counters. @@ -4482,12 +4775,12 @@ ixgbe_update_stats_counters(struct adapter *adapter) mp = IXGBE_READ_REG(hw, IXGBE_MPC(i)); /* missed_rx tallies misses for the gprc workaround */ missed_rx += mp; + /* global total per queue */ adapter->stats.mpc[i] += mp; /* Running comprehensive total for stats display */ total_missed_rx += adapter->stats.mpc[i]; if (hw->mac.type == ixgbe_mac_82598EB) - adapter->stats.rnbc[i] += - IXGBE_READ_REG(hw, IXGBE_RNBC(i)); + adapter->stats.rnbc[i] += IXGBE_READ_REG(hw, IXGBE_RNBC(i)); } /* Hardware workaround, gprc counts missed packets */ @@ -4508,7 +4801,7 @@ ixgbe_update_stats_counters(struct adapter *adapter) adapter->stats.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXC); /* 82598 only has a counter in the high register */ adapter->stats.gorc += IXGBE_READ_REG(hw, IXGBE_GORCH); - adapter->stats.gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH); + adapter->stats.gorc += IXGBE_READ_REG(hw, IXGBE_GOTCH); adapter->stats.tor += IXGBE_READ_REG(hw, IXGBE_TORH); } @@ -4653,6 +4946,8 @@ ixgbe_print_debug_info(struct adapter *adapter) rxr->me, lro->lro_queued); device_printf(dev,"RX(%d) LRO Flushed= %d\n", rxr->me, lro->lro_flushed); + device_printf(dev,"RX(%d) HW LRO Merges= %lu\n", + rxr->me, (long)rxr->rsc_num); } for (int i = 0; i < adapter->num_queues; i++, txr++) { diff --git a/sys/dev/ixgbe/ixgbe.h b/sys/dev/ixgbe/ixgbe.h index 848820a8e956..d52eed3a07e3 100644 --- a/sys/dev/ixgbe/ixgbe.h +++ b/sys/dev/ixgbe/ixgbe.h @@ -134,9 +134,11 @@ #define MAX_LOOP 10 /* - * This parameter controls the duration of transmit watchdog timer. + * This is the max watchdog interval, ie. the time that can + * pass between any two TX clean operations, such only happening + * when the TX hardware is functioning. */ -#define IXGBE_TX_TIMEOUT 5 /* set to 5 seconds */ +#define IXGBE_WATCHDOG (10 * hz) /* * This parameters control when the driver calls the routine to reclaim @@ -148,7 +150,7 @@ #define IXGBE_MAX_FRAME_SIZE 0x3F00 /* Flow control constants */ -#define IXGBE_FC_PAUSE 0x680 +#define IXGBE_FC_PAUSE 0xFFFF #define IXGBE_FC_HI 0x20000 #define IXGBE_FC_LO 0x10000 @@ -174,7 +176,7 @@ #define MSIX_82599_BAR 4 #define IXGBE_TSO_SIZE 65535 #define IXGBE_TX_BUFFER_SIZE ((u32) 1514) -#define IXGBE_RX_HDR 128 +#define IXGBE_RX_HDR 256 #define IXGBE_VFTA_SIZE 128 #define IXGBE_BR_SIZE 4096 #define CSUM_OFFLOAD 7 /* Bits in csum flags */ @@ -253,14 +255,15 @@ struct tx_ring { struct mtx tx_mtx; u32 me; u32 msix; - u32 watchdog_timer; + bool watchdog_check; + int watchdog_time; union ixgbe_adv_tx_desc *tx_base; volatile u32 tx_hwb; struct ixgbe_dma_alloc txdma; struct task tx_task; struct taskqueue *tq; - u32 next_avail_tx_desc; - u32 next_tx_to_clean; + u32 next_avail_desc; + u32 next_to_clean; struct ixgbe_tx_buf *tx_buffers; volatile u16 tx_avail; u32 txd_cmd; @@ -272,7 +275,10 @@ struct tx_ring { /* Interrupt resources */ void *tag; struct resource *res; - +#ifdef IXGBE_FDIR + u16 atr_sample; + u16 atr_count; +#endif /* Soft Stats */ u32 no_tx_desc_avail; u32 no_tx_desc_late; @@ -297,13 +303,12 @@ struct rx_ring { struct lro_ctrl lro; bool lro_enabled; bool hdr_split; - unsigned int last_cleaned; + bool hw_rsc; + unsigned int last_refreshed; unsigned int next_to_check; struct ixgbe_rx_buf *rx_buffers; bus_dma_tag_t rxtag; bus_dmamap_t spare_map; - struct mbuf *fmp; - struct mbuf *lmp; char mtx_name[16]; u32 bytes; /* Used for AIM calc */ @@ -318,6 +323,10 @@ struct rx_ring { u64 rx_split_packets; u64 rx_packets; u64 rx_bytes; + u64 rsc_num; +#ifdef IXGBE_FDIR + u64 flm; +#endif }; /* Our adapter structure */ @@ -349,21 +358,16 @@ struct adapter { eventhandler_tag vlan_attach; eventhandler_tag vlan_detach; - u32 num_vlans; + u16 num_vlans; u16 num_queues; /* Info about the board itself */ - u32 part_num; u32 optics; bool link_active; u16 max_frame_size; u32 link_speed; bool link_up; u32 linkvec; - u32 tx_int_delay; - u32 tx_abs_int_delay; - u32 rx_int_delay; - u32 rx_abs_int_delay; /* Mbuf cluster size */ u32 rx_mbuf_sz; @@ -373,6 +377,10 @@ struct adapter { struct task link_task; /* Link tasklet */ struct task mod_task; /* SFP tasklet */ struct task msf_task; /* Multispeed Fiber tasklet */ +#ifdef IXGBE_FDIR + int fdir_reinit; + struct task fdir_task; +#endif struct taskqueue *tq; /* @@ -423,12 +431,12 @@ struct adapter { #define IXGBE_CORE_LOCK_INIT(_sc, _name) \ mtx_init(&(_sc)->core_mtx, _name, "IXGBE Core Lock", MTX_DEF) #define IXGBE_CORE_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->core_mtx) -#define IXGBE_TX_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->tx_mtx) -#define IXGBE_RX_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->rx_mtx) +#define IXGBE_TX_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->tx_mtx) +#define IXGBE_RX_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->rx_mtx) #define IXGBE_CORE_LOCK(_sc) mtx_lock(&(_sc)->core_mtx) -#define IXGBE_TX_LOCK(_sc) mtx_lock(&(_sc)->tx_mtx) -#define IXGBE_TX_TRYLOCK(_sc) mtx_trylock(&(_sc)->tx_mtx) -#define IXGBE_RX_LOCK(_sc) mtx_lock(&(_sc)->rx_mtx) +#define IXGBE_TX_LOCK(_sc) mtx_lock(&(_sc)->tx_mtx) +#define IXGBE_TX_TRYLOCK(_sc) mtx_trylock(&(_sc)->tx_mtx) +#define IXGBE_RX_LOCK(_sc) mtx_lock(&(_sc)->rx_mtx) #define IXGBE_CORE_UNLOCK(_sc) mtx_unlock(&(_sc)->core_mtx) #define IXGBE_TX_UNLOCK(_sc) mtx_unlock(&(_sc)->tx_mtx) #define IXGBE_RX_UNLOCK(_sc) mtx_unlock(&(_sc)->rx_mtx) diff --git a/sys/dev/ixgbe/ixgbe_82598.c b/sys/dev/ixgbe/ixgbe_82598.c index fb711c621ad5..12711b0a9b4d 100644 --- a/sys/dev/ixgbe/ixgbe_82598.c +++ b/sys/dev/ixgbe/ixgbe_82598.c @@ -44,20 +44,21 @@ static s32 ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw, bool *autoneg); static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw); s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num); -static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw); +static s32 ixgbe_start_mac_link_82598(struct ixgbe_hw *hw, + bool autoneg_wait_to_complete); static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up, bool link_up_wait_to_complete); -static s32 ixgbe_setup_mac_link_speed_82598(struct ixgbe_hw *hw, +static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete); -static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw); -static s32 ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw, +static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete); static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw); +s32 ixgbe_start_hw_82598(struct ixgbe_hw *hw); s32 ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq); static s32 ixgbe_clear_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq); s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan, @@ -70,7 +71,50 @@ s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset, u32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw); s32 ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw); void ixgbe_set_lan_id_multi_port_pcie_82598(struct ixgbe_hw *hw); +void ixgbe_set_pcie_completion_timeout(struct ixgbe_hw *hw); +static s32 ixgbe_validate_link_ready(struct ixgbe_hw *hw); +/** + * ixgbe_set_pcie_completion_timeout - set pci-e completion timeout + * @hw: pointer to the HW structure + * + * The defaults for 82598 should be in the range of 50us to 50ms, + * however the hardware default for these parts is 500us to 1ms which is less + * than the 10ms recommended by the pci-e spec. To address this we need to + * increase the value to either 10ms to 250ms for capability version 1 config, + * or 16ms to 55ms for version 2. + **/ +void ixgbe_set_pcie_completion_timeout(struct ixgbe_hw *hw) +{ + u32 gcr = IXGBE_READ_REG(hw, IXGBE_GCR); + u16 pcie_devctl2; + + /* only take action if timeout value is defaulted to 0 */ + if (gcr & IXGBE_GCR_CMPL_TMOUT_MASK) + goto out; + + /* + * if capababilities version is type 1 we can write the + * timeout of 10ms to 250ms through the GCR register + */ + if (!(gcr & IXGBE_GCR_CAP_VER2)) { + gcr |= IXGBE_GCR_CMPL_TMOUT_10ms; + goto out; + } + + /* + * for version 2 capabilities we need to write the config space + * directly in order to set the completion timeout value for + * 16ms to 55ms + */ + pcie_devctl2 = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_CONTROL2); + pcie_devctl2 |= IXGBE_PCI_DEVICE_CONTROL2_16ms; + IXGBE_WRITE_PCIE_WORD(hw, IXGBE_PCI_DEVICE_CONTROL2, pcie_devctl2); +out: + /* disable completion timeout resend */ + gcr &= ~IXGBE_GCR_CMPL_TMOUT_RESEND; + IXGBE_WRITE_REG(hw, IXGBE_GCR, gcr); +} /** * ixgbe_get_pcie_msix_count_82598 - Gets MSI-X vector count @@ -83,6 +127,8 @@ u32 ixgbe_get_pcie_msix_count_82598(struct ixgbe_hw *hw) { u32 msix_count = 18; + DEBUGFUNC("ixgbe_get_pcie_msix_count_82598"); + if (hw->mac.msix_vectors_from_pcie) { msix_count = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCIE_MSIX_82598_CAPS); @@ -108,6 +154,8 @@ s32 ixgbe_init_ops_82598(struct ixgbe_hw *hw) struct ixgbe_phy_info *phy = &hw->phy; s32 ret_val; + DEBUGFUNC("ixgbe_init_ops_82598"); + ret_val = ixgbe_init_phy_ops_generic(hw); ret_val = ixgbe_init_ops_generic(hw); @@ -115,6 +163,7 @@ s32 ixgbe_init_ops_82598(struct ixgbe_hw *hw) phy->ops.init = &ixgbe_init_phy_ops_82598; /* MAC */ + mac->ops.start_hw = &ixgbe_start_hw_82598; mac->ops.reset_hw = &ixgbe_reset_hw_82598; mac->ops.get_media_type = &ixgbe_get_media_type_82598; mac->ops.get_supported_physical_layer = @@ -145,7 +194,6 @@ s32 ixgbe_init_ops_82598(struct ixgbe_hw *hw) /* Link */ mac->ops.check_link = &ixgbe_check_mac_link_82598; mac->ops.setup_link = &ixgbe_setup_mac_link_82598; - mac->ops.setup_link_speed = &ixgbe_setup_mac_link_speed_82598; mac->ops.get_link_capabilities = &ixgbe_get_link_capabilities_82598; @@ -168,6 +216,7 @@ s32 ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw) s32 ret_val = IXGBE_SUCCESS; u16 list_offset, data_offset; + DEBUGFUNC("ixgbe_init_phy_ops_82598"); /* Identify the PHY */ phy->ops.identify(hw); @@ -175,21 +224,20 @@ s32 ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw) /* Overwrite the link function pointers if copper PHY */ if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) { mac->ops.setup_link = &ixgbe_setup_copper_link_82598; - mac->ops.setup_link_speed = - &ixgbe_setup_copper_link_speed_82598; mac->ops.get_link_capabilities = &ixgbe_get_copper_link_capabilities_generic; } switch (hw->phy.type) { case ixgbe_phy_tn: + phy->ops.setup_link = &ixgbe_setup_phy_link_tnx; phy->ops.check_link = &ixgbe_check_phy_link_tnx; phy->ops.get_firmware_version = &ixgbe_get_phy_firmware_version_tnx; break; case ixgbe_phy_aq: phy->ops.get_firmware_version = - &ixgbe_get_phy_firmware_version_aq; + &ixgbe_get_phy_firmware_version_generic; break; case ixgbe_phy_nl: phy->ops.reset = &ixgbe_reset_phy_nl; @@ -221,6 +269,46 @@ out: } /** + * ixgbe_start_hw_82598 - Prepare hardware for Tx/Rx + * @hw: pointer to hardware structure + * + * Starts the hardware using the generic start_hw function. + * Then set pcie completion timeout + **/ +s32 ixgbe_start_hw_82598(struct ixgbe_hw *hw) +{ + u32 regval; + u32 i; + s32 ret_val = IXGBE_SUCCESS; + + DEBUGFUNC("ixgbe_start_hw_82598"); + + ret_val = ixgbe_start_hw_generic(hw); + + /* Disable relaxed ordering */ + for (i = 0; ((i < hw->mac.max_tx_queues) && + (i < IXGBE_DCA_MAX_QUEUES_82598)); i++) { + regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(i)); + regval &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN; + IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(i), regval); + } + + for (i = 0; ((i < hw->mac.max_rx_queues) && + (i < IXGBE_DCA_MAX_QUEUES_82598)); i++) { + regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i)); + regval &= ~(IXGBE_DCA_RXCTRL_DESC_WRO_EN | + IXGBE_DCA_RXCTRL_DESC_HSRO_EN); + IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval); + } + + /* set the completion timeout for interface */ + if (ret_val == IXGBE_SUCCESS) + ixgbe_set_pcie_completion_timeout(hw); + + return ret_val; +} + +/** * ixgbe_get_link_capabilities_82598 - Determines link capabilities * @hw: pointer to hardware structure * @speed: pointer to link speed @@ -235,6 +323,8 @@ static s32 ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw, s32 status = IXGBE_SUCCESS; u32 autoc = 0; + DEBUGFUNC("ixgbe_get_link_capabilities_82598"); + /* * Determine link capabilities based on the stored value of AUTOC, * which represents EEPROM defaults. If AUTOC value has not been @@ -289,6 +379,8 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw) { enum ixgbe_media_type media_type; + DEBUGFUNC("ixgbe_get_media_type_82598"); + /* Detect if there is a copper PHY attached. */ if (hw->phy.type == ixgbe_phy_cu_unknown || hw->phy.type == ixgbe_phy_tn || @@ -306,15 +398,18 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw) break; case IXGBE_DEV_ID_82598AF_DUAL_PORT: case IXGBE_DEV_ID_82598AF_SINGLE_PORT: - case IXGBE_DEV_ID_82598EB_CX4: - case IXGBE_DEV_ID_82598_CX4_DUAL_PORT: case IXGBE_DEV_ID_82598_DA_DUAL_PORT: case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM: case IXGBE_DEV_ID_82598EB_XF_LR: case IXGBE_DEV_ID_82598EB_SFP_LOM: media_type = ixgbe_media_type_fiber; break; + case IXGBE_DEV_ID_82598EB_CX4: + case IXGBE_DEV_ID_82598_CX4_DUAL_PORT: + media_type = ixgbe_media_type_cx4; + break; case IXGBE_DEV_ID_82598AT: + case IXGBE_DEV_ID_82598AT2: media_type = ixgbe_media_type_copper; break; default: @@ -338,9 +433,23 @@ s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num) u32 fctrl_reg; u32 rmcs_reg; u32 reg; + u32 link_speed = 0; + bool link_up; DEBUGFUNC("ixgbe_fc_enable_82598"); + /* + * On 82598 backplane having FC on causes resets while doing + * KX, so turn off here. + */ + hw->mac.ops.check_link(hw, &link_speed, &link_up, FALSE); + if (link_up && + link_speed == IXGBE_LINK_SPEED_1GB_FULL && + hw->mac.ops.get_media_type(hw) == ixgbe_media_type_backplane) { + hw->fc.disable_fc_autoneg = TRUE; + hw->fc.requested_mode = ixgbe_fc_none; + } + /* Negotiate the fc mode to use */ ret_val = ixgbe_fc_autoneg(hw); if (ret_val) @@ -394,7 +503,7 @@ s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num) break; default: DEBUGOUT("Flow control param set incorrectly\n"); - ret_val = -IXGBE_ERR_CONFIG; + ret_val = IXGBE_ERR_CONFIG; goto out; break; } @@ -433,26 +542,29 @@ out: } /** - * ixgbe_setup_mac_link_82598 - Configures MAC link settings + * ixgbe_start_mac_link_82598 - Configures MAC link settings * @hw: pointer to hardware structure * * Configures link settings based on values in the ixgbe_hw struct. * Restarts the link. Performs autonegotiation if needed. **/ -static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw) +static s32 ixgbe_start_mac_link_82598(struct ixgbe_hw *hw, + bool autoneg_wait_to_complete) { u32 autoc_reg; u32 links_reg; u32 i; s32 status = IXGBE_SUCCESS; + DEBUGFUNC("ixgbe_start_mac_link_82598"); + /* Restart link */ autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); autoc_reg |= IXGBE_AUTOC_AN_RESTART; IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); /* Only poll for autoneg to complete if specified to do so */ - if (hw->phy.autoneg_wait_to_complete) { + if (autoneg_wait_to_complete) { if ((autoc_reg & IXGBE_AUTOC_LMS_MASK) == IXGBE_AUTOC_LMS_KX4_AN || (autoc_reg & IXGBE_AUTOC_LMS_MASK) == @@ -494,6 +606,8 @@ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, u32 i; u16 link_reg, adapt_comp_reg; + DEBUGFUNC("ixgbe_check_mac_link_82598"); + /* * SERDES PHY requires us to read link status from undocumented * register 0xC79F. Bit 0 set indicates link is up/ready; clear @@ -558,17 +672,22 @@ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, else *speed = IXGBE_LINK_SPEED_1GB_FULL; + if ((hw->device_id == IXGBE_DEV_ID_82598AT2) && (*link_up == TRUE) && + (ixgbe_validate_link_ready(hw) != IXGBE_SUCCESS)) + *link_up = FALSE; + /* if link is down, zero out the current_mode */ if (*link_up == FALSE) { hw->fc.current_mode = ixgbe_fc_none; hw->fc.fc_was_autonegged = FALSE; } + out: return IXGBE_SUCCESS; } /** - * ixgbe_setup_mac_link_speed_82598 - Set MAC link speed + * ixgbe_setup_mac_link_82598 - Set MAC link speed * @hw: pointer to hardware structure * @speed: new link speed * @autoneg: TRUE if autonegotiation enabled @@ -576,7 +695,7 @@ out: * * Set the link speed in the AUTOC register and restarts link. **/ -static s32 ixgbe_setup_mac_link_speed_82598(struct ixgbe_hw *hw, +static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete) { @@ -586,6 +705,8 @@ static s32 ixgbe_setup_mac_link_speed_82598(struct ixgbe_hw *hw, u32 autoc = curr_autoc; u32 link_mode = autoc & IXGBE_AUTOC_LMS_MASK; + DEBUGFUNC("ixgbe_setup_mac_link_82598"); + /* Check to see if speed passed in is supported. */ ixgbe_get_link_capabilities(hw, &link_capabilities, &autoneg); speed &= link_capabilities; @@ -606,14 +727,13 @@ static s32 ixgbe_setup_mac_link_speed_82598(struct ixgbe_hw *hw, } if (status == IXGBE_SUCCESS) { - hw->phy.autoneg_wait_to_complete = autoneg_wait_to_complete; - /* * Setup and restart the link based on the new values in * ixgbe_hw This will write the AUTOC register based on the new * stored values */ - status = ixgbe_setup_mac_link_82598(hw); + status = ixgbe_start_mac_link_82598(hw, + autoneg_wait_to_complete); } return status; @@ -621,29 +741,7 @@ static s32 ixgbe_setup_mac_link_speed_82598(struct ixgbe_hw *hw, /** - * ixgbe_setup_copper_link_82598 - Setup copper link settings - * @hw: pointer to hardware structure - * - * Configures link settings based on values in the ixgbe_hw struct. - * Restarts the link. Performs autonegotiation if needed. Restart - * phy and wait for autonegotiate to finish. Then synchronize the - * MAC and PHY. - **/ -static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw) -{ - s32 status; - - /* Restart autonegotiation on PHY */ - status = hw->phy.ops.setup_link(hw); - - /* Set up MAC */ - ixgbe_setup_mac_link_82598(hw); - - return status; -} - -/** - * ixgbe_setup_copper_link_speed_82598 - Set the PHY autoneg advertised field + * ixgbe_setup_copper_link_82598 - Set the PHY autoneg advertised field * @hw: pointer to hardware structure * @speed: new link speed * @autoneg: TRUE if autonegotiation enabled @@ -651,18 +749,20 @@ static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw) * * Sets the link speed in the AUTOC register in the MAC and restarts link. **/ -static s32 ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw, +static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete) { s32 status; + DEBUGFUNC("ixgbe_setup_copper_link_82598"); + /* Setup the PHY according to input speed */ status = hw->phy.ops.setup_link_speed(hw, speed, autoneg, autoneg_wait_to_complete); /* Set up MAC */ - ixgbe_setup_mac_link_82598(hw); + ixgbe_start_mac_link_82598(hw, autoneg_wait_to_complete); return status; } @@ -685,6 +785,8 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw) u32 autoc; u8 analog_val; + DEBUGFUNC("ixgbe_reset_hw_82598"); + /* Call adapter stop to disable tx/rx and clear interrupts */ hw->mac.ops.stop_adapter(hw); @@ -811,6 +913,8 @@ s32 ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq) { u32 rar_high; + DEBUGFUNC("ixgbe_set_vmdq_82598"); + rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar)); rar_high &= ~IXGBE_RAH_VIND_MASK; rar_high |= ((vmdq << IXGBE_RAH_VIND_SHIFT) & IXGBE_RAH_VIND_MASK); @@ -861,6 +965,8 @@ s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan, u32 vind, u32 bits; u32 vftabyte; + DEBUGFUNC("ixgbe_set_vfta_82598"); + if (vlan > 4095) return IXGBE_ERR_PARAM; @@ -903,6 +1009,8 @@ static s32 ixgbe_clear_vfta_82598(struct ixgbe_hw *hw) u32 offset; u32 vlanbyte; + DEBUGFUNC("ixgbe_clear_vfta_82598"); + for (offset = 0; offset < hw->mac.vft_size; offset++) IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0); @@ -926,6 +1034,8 @@ s32 ixgbe_read_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 *val) { u32 atlas_ctl; + DEBUGFUNC("ixgbe_read_analog_reg8_82598"); + IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL, IXGBE_ATLASCTL_WRITE_CMD | (reg << 8)); IXGBE_WRITE_FLUSH(hw); @@ -948,6 +1058,8 @@ s32 ixgbe_write_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 val) { u32 atlas_ctl; + DEBUGFUNC("ixgbe_write_analog_reg8_82598"); + atlas_ctl = (reg << 8) | val; IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL, atlas_ctl); IXGBE_WRITE_FLUSH(hw); @@ -973,6 +1085,8 @@ s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset, u16 sfp_stat = 0; u32 i; + DEBUGFUNC("ixgbe_read_i2c_eeprom_82598"); + if (hw->phy.type == ixgbe_phy_nl) { /* * NetLogic phy SDA/SCL registers are at addresses 0xC30A to @@ -1032,6 +1146,8 @@ u32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw) u32 pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK; u16 ext_ability = 0; + DEBUGFUNC("ixgbe_get_supported_physical_layer_82598"); + hw->phy.ops.identify(hw); /* Copper PHY must be checked before AUTOC LMS to determine correct @@ -1128,6 +1244,8 @@ void ixgbe_set_lan_id_multi_port_pcie_82598(struct ixgbe_hw *hw) struct ixgbe_bus_info *bus = &hw->bus; u16 pci_gen, pci_ctrl2; + DEBUGFUNC("ixgbe_set_lan_id_multi_port_pcie_82598"); + ixgbe_set_lan_id_multi_port_pcie(hw); /* check if LAN0 is disabled */ @@ -1146,4 +1264,38 @@ void ixgbe_set_lan_id_multi_port_pcie_82598(struct ixgbe_hw *hw) } } +/** + * ixgbe_validate_link_ready - Function looks for phy link + * @hw: pointer to hardware structure + * + * Function indicates success when phy link is available. If phy is not ready + * within 5 seconds of MAC indicating link, the function returns error. + **/ +static s32 ixgbe_validate_link_ready(struct ixgbe_hw *hw) +{ + u32 timeout; + u16 an_reg; + + if (hw->device_id != IXGBE_DEV_ID_82598AT2) + return IXGBE_SUCCESS; + + for (timeout = 0; + timeout < IXGBE_VALIDATE_LINK_READY_TIMEOUT; timeout++) { + hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &an_reg); + + if ((an_reg & IXGBE_MII_AUTONEG_COMPLETE) && + (an_reg & IXGBE_MII_AUTONEG_LINK_UP)) + break; + + msec_delay(100); + } + + if (timeout == IXGBE_VALIDATE_LINK_READY_TIMEOUT) { + DEBUGOUT("Link was indicated but link is down\n"); + return IXGBE_ERR_LINK_SETUP; + } + + return IXGBE_SUCCESS; +} diff --git a/sys/dev/ixgbe/ixgbe_82599.c b/sys/dev/ixgbe/ixgbe_82599.c index c3d23afde550..97b655a26ac7 100644 --- a/sys/dev/ixgbe/ixgbe_82599.c +++ b/sys/dev/ixgbe/ixgbe_82599.c @@ -37,39 +37,30 @@ #include "ixgbe_common.h" #include "ixgbe_phy.h" -u32 ixgbe_get_pcie_msix_count_82599(struct ixgbe_hw *hw); s32 ixgbe_init_ops_82599(struct ixgbe_hw *hw); s32 ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *autoneg); enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw); -s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw); -s32 ixgbe_setup_mac_link_speed_multispeed_fiber(struct ixgbe_hw *hw, +s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete); -s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw); -s32 ixgbe_check_mac_link_82599(struct ixgbe_hw *hw, - ixgbe_link_speed *speed, - bool *link_up, bool link_up_wait_to_complete); -s32 ixgbe_setup_mac_link_speed_82599(struct ixgbe_hw *hw, +s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw, + ixgbe_link_speed speed, bool autoneg, + bool autoneg_wait_to_complete); +s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw, + bool autoneg_wait_to_complete); +s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete); -static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw); -static s32 ixgbe_setup_copper_link_speed_82599(struct ixgbe_hw *hw, +static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete); s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw); void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw); s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw); -s32 ixgbe_set_vmdq_82599(struct ixgbe_hw *hw, u32 rar, u32 vmdq); -s32 ixgbe_clear_vmdq_82599(struct ixgbe_hw *hw, u32 rar, u32 vmdq); -s32 ixgbe_insert_mac_addr_82599(struct ixgbe_hw *hw, u8 *addr, u32 vmdq); -s32 ixgbe_set_vfta_82599(struct ixgbe_hw *hw, u32 vlan, - u32 vind, bool vlan_on); -s32 ixgbe_clear_vfta_82599(struct ixgbe_hw *hw); -s32 ixgbe_init_uta_tables_82599(struct ixgbe_hw *hw); s32 ixgbe_read_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 *val); s32 ixgbe_write_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 val); s32 ixgbe_start_hw_rev_1_82599(struct ixgbe_hw *hw); @@ -77,14 +68,9 @@ s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw); s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw); u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw); s32 ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, u32 regval); -s32 ixgbe_get_san_mac_addr_offset_82599(struct ixgbe_hw *hw, - u16 *san_mac_offset); -s32 ixgbe_get_san_mac_addr_82599(struct ixgbe_hw *hw, u8 *san_mac_addr); -s32 ixgbe_set_san_mac_addr_82599(struct ixgbe_hw *hw, u8 *san_mac_addr); s32 ixgbe_get_device_caps_82599(struct ixgbe_hw *hw, u16 *device_caps); static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw); - void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw) { struct ixgbe_mac_info *mac = &hw->mac; @@ -93,15 +79,14 @@ void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw) if (hw->phy.multispeed_fiber) { /* Set up dual speed SFP+ support */ - mac->ops.setup_link = - &ixgbe_setup_mac_link_multispeed_fiber; - mac->ops.setup_link_speed = - &ixgbe_setup_mac_link_speed_multispeed_fiber; + mac->ops.setup_link = &ixgbe_setup_mac_link_multispeed_fiber; } else { - mac->ops.setup_link = - &ixgbe_setup_mac_link_82599; - mac->ops.setup_link_speed = - &ixgbe_setup_mac_link_speed_82599; + if ((ixgbe_get_media_type(hw) == ixgbe_media_type_backplane) && + (hw->phy.smart_speed == ixgbe_smart_speed_auto || + hw->phy.smart_speed == ixgbe_smart_speed_on)) + mac->ops.setup_link = &ixgbe_setup_mac_link_smartspeed; + else + mac->ops.setup_link = &ixgbe_setup_mac_link_82599; } } @@ -135,8 +120,6 @@ s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw) /* If copper media, overwrite with copper function pointers */ if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) { mac->ops.setup_link = &ixgbe_setup_copper_link_82599; - mac->ops.setup_link_speed = - &ixgbe_setup_copper_link_speed_82599; mac->ops.get_link_capabilities = &ixgbe_get_copper_link_capabilities_generic; } @@ -144,13 +127,14 @@ s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw) /* Set necessary function pointers based on phy type */ switch (hw->phy.type) { case ixgbe_phy_tn: + phy->ops.setup_link = &ixgbe_setup_phy_link_tnx; phy->ops.check_link = &ixgbe_check_phy_link_tnx; phy->ops.get_firmware_version = &ixgbe_get_phy_firmware_version_tnx; break; case ixgbe_phy_aq: phy->ops.get_firmware_version = - &ixgbe_get_phy_firmware_version_aq; + &ixgbe_get_phy_firmware_version_generic; break; default: break; @@ -204,30 +188,6 @@ setup_sfp_out: } /** - * ixgbe_get_pcie_msix_count_82599 - Gets MSI-X vector count - * @hw: pointer to hardware structure - * - * Read PCIe configuration space, and get the MSI-X vector count from - * the capabilities table. - **/ -u32 ixgbe_get_pcie_msix_count_82599(struct ixgbe_hw *hw) -{ - u32 msix_count = 64; - - if (hw->mac.msix_vectors_from_pcie) { - msix_count = IXGBE_READ_PCIE_WORD(hw, - IXGBE_PCIE_MSIX_82599_CAPS); - msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK; - - /* MSI-X count is zero-based in HW, so increment to give - * proper value */ - msix_count++; - } - - return msix_count; -} - -/** * ixgbe_init_ops_82599 - Inits func ptrs and MAC type * @hw: pointer to hardware structure * @@ -241,6 +201,8 @@ s32 ixgbe_init_ops_82599(struct ixgbe_hw *hw) struct ixgbe_phy_info *phy = &hw->phy; s32 ret_val; + DEBUGFUNC("ixgbe_init_ops_82599"); + ret_val = ixgbe_init_phy_ops_generic(hw); ret_val = ixgbe_init_ops_generic(hw); @@ -257,23 +219,24 @@ s32 ixgbe_init_ops_82599(struct ixgbe_hw *hw) mac->ops.read_analog_reg8 = &ixgbe_read_analog_reg8_82599; mac->ops.write_analog_reg8 = &ixgbe_write_analog_reg8_82599; mac->ops.start_hw = &ixgbe_start_hw_rev_1_82599; - mac->ops.get_san_mac_addr = &ixgbe_get_san_mac_addr_82599; - mac->ops.set_san_mac_addr = &ixgbe_set_san_mac_addr_82599; + mac->ops.get_san_mac_addr = &ixgbe_get_san_mac_addr_generic; + mac->ops.set_san_mac_addr = &ixgbe_set_san_mac_addr_generic; mac->ops.get_device_caps = &ixgbe_get_device_caps_82599; + mac->ops.get_wwn_prefix = &ixgbe_get_wwn_prefix_generic; /* RAR, Multicast, VLAN */ - mac->ops.set_vmdq = &ixgbe_set_vmdq_82599; - mac->ops.clear_vmdq = &ixgbe_clear_vmdq_82599; - mac->ops.insert_mac_addr = &ixgbe_insert_mac_addr_82599; + mac->ops.set_vmdq = &ixgbe_set_vmdq_generic; + mac->ops.clear_vmdq = &ixgbe_clear_vmdq_generic; + mac->ops.insert_mac_addr = &ixgbe_insert_mac_addr_generic; mac->rar_highwater = 1; - mac->ops.set_vfta = &ixgbe_set_vfta_82599; - mac->ops.clear_vfta = &ixgbe_clear_vfta_82599; - mac->ops.init_uta_tables = &ixgbe_init_uta_tables_82599; + mac->ops.set_vfta = &ixgbe_set_vfta_generic; + mac->ops.clear_vfta = &ixgbe_clear_vfta_generic; + mac->ops.init_uta_tables = &ixgbe_init_uta_tables_generic; mac->ops.setup_sfp = &ixgbe_setup_sfp_modules_82599; /* Link */ mac->ops.get_link_capabilities = &ixgbe_get_link_capabilities_82599; - mac->ops.check_link = &ixgbe_check_mac_link_82599; + mac->ops.check_link = &ixgbe_check_mac_link_generic; ixgbe_init_mac_link_ops_82599(hw); mac->mcft_size = 128; @@ -281,7 +244,7 @@ s32 ixgbe_init_ops_82599(struct ixgbe_hw *hw) mac->num_rar_entries = 128; mac->max_tx_queues = 128; mac->max_rx_queues = 128; - mac->max_msix_vectors = ixgbe_get_pcie_msix_count_82599(hw); + mac->max_msix_vectors = ixgbe_get_pcie_msix_count_generic(hw); return ret_val; @@ -302,6 +265,8 @@ s32 ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw, s32 status = IXGBE_SUCCESS; u32 autoc = 0; + DEBUGFUNC("ixgbe_get_link_capabilities_82599"); + /* * Determine link capabilities based on the stored value of AUTOC, * which represents EEPROM defaults. If AUTOC value has not @@ -387,6 +352,8 @@ enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw) { enum ixgbe_media_type media_type; + DEBUGFUNC("ixgbe_get_media_type_82599"); + /* Detect if there is a copper PHY attached. */ if (hw->phy.type == ixgbe_phy_cu_unknown || hw->phy.type == ixgbe_phy_tn || @@ -397,6 +364,8 @@ enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw) switch (hw->device_id) { case IXGBE_DEV_ID_82599_KX4: + case IXGBE_DEV_ID_82599_KX4_MEZZ: + case IXGBE_DEV_ID_82599_COMBO_BACKPLANE: case IXGBE_DEV_ID_82599_XAUI_LOM: /* Default device ID is mezzanine card KX/KX4 */ media_type = ixgbe_media_type_backplane; @@ -405,7 +374,7 @@ enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw) media_type = ixgbe_media_type_fiber; break; case IXGBE_DEV_ID_82599_CX4: - media_type = ixgbe_media_type_fiber; + media_type = ixgbe_media_type_cx4; break; default: media_type = ixgbe_media_type_unknown; @@ -416,19 +385,22 @@ out: } /** - * ixgbe_setup_mac_link_82599 - Setup MAC link settings + * ixgbe_start_mac_link_82599 - Setup MAC link settings * @hw: pointer to hardware structure * * Configures link settings based on values in the ixgbe_hw struct. * Restarts the link. Performs autonegotiation if needed. **/ -s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw) +s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw, + bool autoneg_wait_to_complete) { u32 autoc_reg; u32 links_reg; u32 i; s32 status = IXGBE_SUCCESS; + DEBUGFUNC("ixgbe_start_mac_link_82599"); + /* Restart link */ autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); @@ -436,7 +408,7 @@ s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw) IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); /* Only poll for autoneg to complete if specified to do so */ - if (hw->phy.autoneg_wait_to_complete) { + if (autoneg_wait_to_complete) { if ((autoc_reg & IXGBE_AUTOC_LMS_MASK) == IXGBE_AUTOC_LMS_KX4_KX_KR || (autoc_reg & IXGBE_AUTOC_LMS_MASK) == @@ -464,27 +436,7 @@ s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw) } /** - * ixgbe_setup_mac_link_multispeed_fiber - Setup MAC link settings - * @hw: pointer to hardware structure - * - * Configures link settings based on values in the ixgbe_hw struct. - * Restarts the link for multi-speed fiber at 1G speed, if link - * fails at 10G. - * Performs autonegotiation if needed. - **/ -s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw) -{ - s32 status = IXGBE_SUCCESS; - ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_82599_AUTONEG; - DEBUGFUNC("ixgbe_setup_mac_link_multispeed_fiber"); - - status = ixgbe_setup_mac_link_speed_multispeed_fiber(hw, - link_speed, TRUE, true); - return status; -} - -/** - * ixgbe_setup_mac_link_speed_multispeed_fiber - Set MAC link speed + * ixgbe_setup_mac_link_multispeed_fiber - Set MAC link speed * @hw: pointer to hardware structure * @speed: new link speed * @autoneg: TRUE if autonegotiation enabled @@ -492,7 +444,7 @@ s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw) * * Set the link speed in the AUTOC register and restarts link. **/ -s32 ixgbe_setup_mac_link_speed_multispeed_fiber(struct ixgbe_hw *hw, +s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete) { @@ -505,22 +457,15 @@ s32 ixgbe_setup_mac_link_speed_multispeed_fiber(struct ixgbe_hw *hw, bool link_up = FALSE; bool negotiation; + DEBUGFUNC("ixgbe_setup_mac_link_multispeed_fiber"); + /* Mask off requested but non-supported speeds */ status = ixgbe_get_link_capabilities(hw, &link_speed, &negotiation); if (status != IXGBE_SUCCESS) - goto out; + return status; speed &= link_speed; - /* Set autoneg_advertised value based on input link speed */ - hw->phy.autoneg_advertised = 0; - - if (speed & IXGBE_LINK_SPEED_10GB_FULL) - hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; - - if (speed & IXGBE_LINK_SPEED_1GB_FULL) - hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; - /* * When the driver changes the link speeds that it can support, * it sets autotry_restart to TRUE to indicate that we need to @@ -542,7 +487,7 @@ s32 ixgbe_setup_mac_link_speed_multispeed_fiber(struct ixgbe_hw *hw, /* If we already have link at this speed, just jump out */ status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE); if (status != IXGBE_SUCCESS) - goto out; + return status; if ((link_speed == IXGBE_LINK_SPEED_10GB_FULL) && link_up) goto out; @@ -554,11 +499,11 @@ s32 ixgbe_setup_mac_link_speed_multispeed_fiber(struct ixgbe_hw *hw, /* Allow module to change analog characteristics (1G->10G) */ msec_delay(40); - status = ixgbe_setup_mac_link_speed_82599( + status = ixgbe_setup_mac_link_82599( hw, IXGBE_LINK_SPEED_10GB_FULL, autoneg, autoneg_wait_to_complete); if (status != IXGBE_SUCCESS) - goto out; + return status; /* Flap the tx laser if it has not already been done */ if (hw->mac.autotry_restart) { @@ -575,7 +520,11 @@ s32 ixgbe_setup_mac_link_speed_multispeed_fiber(struct ixgbe_hw *hw, hw->mac.autotry_restart = FALSE; } - /* The controller may take up to 500ms at 10g to acquire link */ + /* + * Wait for the controller to acquire link. Per IEEE 802.3ap, + * Section 73.10.2, we may have to wait up to 500ms if KR is + * attempted. 82599 uses the same timing for 10g SFI. + */ for (i = 0; i < 5; i++) { /* Wait for the link partner to also set speed */ msec_delay(100); @@ -584,7 +533,7 @@ s32 ixgbe_setup_mac_link_speed_multispeed_fiber(struct ixgbe_hw *hw, status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE); if (status != IXGBE_SUCCESS) - goto out; + return status; if (link_up) goto out; @@ -599,7 +548,7 @@ s32 ixgbe_setup_mac_link_speed_multispeed_fiber(struct ixgbe_hw *hw, /* If we already have link at this speed, just jump out */ status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE); if (status != IXGBE_SUCCESS) - goto out; + return status; if ((link_speed == IXGBE_LINK_SPEED_1GB_FULL) && link_up) goto out; @@ -612,11 +561,11 @@ s32 ixgbe_setup_mac_link_speed_multispeed_fiber(struct ixgbe_hw *hw, /* Allow module to change analog characteristics (10G->1G) */ msec_delay(40); - status = ixgbe_setup_mac_link_speed_82599( + status = ixgbe_setup_mac_link_82599( hw, IXGBE_LINK_SPEED_1GB_FULL, autoneg, autoneg_wait_to_complete); if (status != IXGBE_SUCCESS) - goto out; + return status; /* Flap the tx laser if it has not already been done */ if (hw->mac.autotry_restart) { @@ -639,7 +588,7 @@ s32 ixgbe_setup_mac_link_speed_multispeed_fiber(struct ixgbe_hw *hw, /* If we have link, just jump out */ status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE); if (status != IXGBE_SUCCESS) - goto out; + return status; if (link_up) goto out; @@ -651,67 +600,134 @@ s32 ixgbe_setup_mac_link_speed_multispeed_fiber(struct ixgbe_hw *hw, * single highest speed that the user requested. */ if (speedcnt > 1) - status = ixgbe_setup_mac_link_speed_multispeed_fiber(hw, + status = ixgbe_setup_mac_link_multispeed_fiber(hw, highest_link_speed, autoneg, autoneg_wait_to_complete); out: + /* Set autoneg_advertised value based on input link speed */ + hw->phy.autoneg_advertised = 0; + + if (speed & IXGBE_LINK_SPEED_10GB_FULL) + hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; + + if (speed & IXGBE_LINK_SPEED_1GB_FULL) + hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; + return status; } /** - * ixgbe_check_mac_link_82599 - Determine link and speed status + * ixgbe_setup_mac_link_smartspeed - Set MAC link speed using SmartSpeed * @hw: pointer to hardware structure - * @speed: pointer to link speed - * @link_up: TRUE when link is up - * @link_up_wait_to_complete: bool used to wait for link up or not + * @speed: new link speed + * @autoneg: TRUE if autonegotiation enabled + * @autoneg_wait_to_complete: TRUE when waiting for completion is needed * - * Reads the links register to determine if link is up and the current speed + * Implements the Intel SmartSpeed algorithm. **/ -s32 ixgbe_check_mac_link_82599(struct ixgbe_hw *hw, ixgbe_link_speed *speed, - bool *link_up, bool link_up_wait_to_complete) +s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw, + ixgbe_link_speed speed, bool autoneg, + bool autoneg_wait_to_complete) { - u32 links_reg; - u32 i; + s32 status = IXGBE_SUCCESS; + ixgbe_link_speed link_speed; + s32 i, j; + bool link_up = FALSE; + u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); - links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); - if (link_up_wait_to_complete) { - for (i = 0; i < IXGBE_LINK_UP_TIME; i++) { - if (links_reg & IXGBE_LINKS_UP) { - *link_up = TRUE; - break; - } else { - *link_up = FALSE; - } + DEBUGFUNC("ixgbe_setup_mac_link_smartspeed"); + + /* Set autoneg_advertised value based on input link speed */ + hw->phy.autoneg_advertised = 0; + + if (speed & IXGBE_LINK_SPEED_10GB_FULL) + hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; + + if (speed & IXGBE_LINK_SPEED_1GB_FULL) + hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; + + if (speed & IXGBE_LINK_SPEED_100_FULL) + hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_100_FULL; + + /* + * Implement Intel SmartSpeed algorithm. SmartSpeed will reduce the + * autoneg advertisement if link is unable to be established at the + * highest negotiated rate. This can sometimes happen due to integrity + * issues with the physical media connection. + */ + + /* First, try to get link with full advertisement */ + hw->phy.smart_speed_active = FALSE; + for (j = 0; j < IXGBE_SMARTSPEED_MAX_RETRIES; j++) { + status = ixgbe_setup_mac_link_82599(hw, speed, autoneg, + autoneg_wait_to_complete); + if (status != IXGBE_SUCCESS) + goto out; + + /* + * Wait for the controller to acquire link. Per IEEE 802.3ap, + * Section 73.10.2, we may have to wait up to 500ms if KR is + * attempted, or 200ms if KX/KX4/BX/BX4 is attempted, per + * Table 9 in the AN MAS. + */ + for (i = 0; i < 5; i++) { msec_delay(100); - links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); + + /* If we have link, just jump out */ + status = ixgbe_check_link(hw, &link_speed, &link_up, + FALSE); + if (status != IXGBE_SUCCESS) + goto out; + + if (link_up) + goto out; } - } else { - if (links_reg & IXGBE_LINKS_UP) - *link_up = TRUE; - else - *link_up = FALSE; } - if ((links_reg & IXGBE_LINKS_SPEED_82599) == - IXGBE_LINKS_SPEED_10G_82599) - *speed = IXGBE_LINK_SPEED_10GB_FULL; - else if ((links_reg & IXGBE_LINKS_SPEED_82599) == - IXGBE_LINKS_SPEED_1G_82599) - *speed = IXGBE_LINK_SPEED_1GB_FULL; - else - *speed = IXGBE_LINK_SPEED_100_FULL; + /* + * We didn't get link. If we advertised KR plus one of KX4/KX + * (or BX4/BX), then disable KR and try again. + */ + if (((autoc_reg & IXGBE_AUTOC_KR_SUPP) == 0) || + ((autoc_reg & IXGBE_AUTOC_KX4_KX_SUPP_MASK) == 0)) + goto out; - /* if link is down, zero out the current_mode */ - if (*link_up == FALSE) { - hw->fc.current_mode = ixgbe_fc_none; - hw->fc.fc_was_autonegged = FALSE; + /* Turn SmartSpeed on to disable KR support */ + hw->phy.smart_speed_active = TRUE; + status = ixgbe_setup_mac_link_82599(hw, speed, autoneg, + autoneg_wait_to_complete); + if (status != IXGBE_SUCCESS) + goto out; + + /* + * Wait for the controller to acquire link. 600ms will allow for + * the AN link_fail_inhibit_timer as well for multiple cycles of + * parallel detect, both 10g and 1g. This allows for the maximum + * connect attempts as defined in the AN MAS table 73-7. + */ + for (i = 0; i < 6; i++) { + msec_delay(100); + + /* If we have link, just jump out */ + status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE); + if (status != IXGBE_SUCCESS) + goto out; + + if (link_up) + goto out; } - return IXGBE_SUCCESS; + /* We didn't get link. Turn SmartSpeed back off. */ + hw->phy.smart_speed_active = FALSE; + status = ixgbe_setup_mac_link_82599(hw, speed, autoneg, + autoneg_wait_to_complete); + +out: + return status; } /** - * ixgbe_setup_mac_link_speed_82599 - Set MAC link speed + * ixgbe_setup_mac_link_82599 - Set MAC link speed * @hw: pointer to hardware structure * @speed: new link speed * @autoneg: TRUE if autonegotiation enabled @@ -719,7 +735,7 @@ s32 ixgbe_check_mac_link_82599(struct ixgbe_hw *hw, ixgbe_link_speed *speed, * * Set the link speed in the AUTOC register and restarts link. **/ -s32 ixgbe_setup_mac_link_speed_82599(struct ixgbe_hw *hw, +s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete) { @@ -735,6 +751,8 @@ s32 ixgbe_setup_mac_link_speed_82599(struct ixgbe_hw *hw, u32 i; ixgbe_link_speed link_capabilities = IXGBE_LINK_SPEED_UNKNOWN; + DEBUGFUNC("ixgbe_setup_mac_link_82599"); + /* Check to see if speed passed in is supported. */ status = ixgbe_get_link_capabilities(hw, &link_capabilities, &autoneg); if (status != IXGBE_SUCCESS) @@ -761,7 +779,8 @@ s32 ixgbe_setup_mac_link_speed_82599(struct ixgbe_hw *hw, if (speed & IXGBE_LINK_SPEED_10GB_FULL) if (orig_autoc & IXGBE_AUTOC_KX4_SUPP) autoc |= IXGBE_AUTOC_KX4_SUPP; - if (orig_autoc & IXGBE_AUTOC_KR_SUPP) + if ((orig_autoc & IXGBE_AUTOC_KR_SUPP) && + (hw->phy.smart_speed_active == FALSE)) autoc |= IXGBE_AUTOC_KR_SUPP; if (speed & IXGBE_LINK_SPEED_1GB_FULL) autoc |= IXGBE_AUTOC_KX_SUPP; @@ -823,26 +842,7 @@ out: } /** - * ixgbe_setup_copper_link_82599 - Setup copper link settings - * @hw: pointer to hardware structure - * - * Restarts the link on PHY and then MAC. Performs autonegotiation if needed. - **/ -static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw) -{ - s32 status; - - /* Restart autonegotiation on PHY */ - status = hw->phy.ops.setup_link(hw); - - /* Set up MAC */ - ixgbe_setup_mac_link_82599(hw); - - return status; -} - -/** - * ixgbe_setup_copper_link_speed_82599 - Set the PHY autoneg advertised field + * ixgbe_setup_copper_link_82599 - Set the PHY autoneg advertised field * @hw: pointer to hardware structure * @speed: new link speed * @autoneg: TRUE if autonegotiation enabled @@ -850,18 +850,20 @@ static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw) * * Restarts link on PHY and MAC based on settings passed in. **/ -static s32 ixgbe_setup_copper_link_speed_82599(struct ixgbe_hw *hw, +static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete) { s32 status; + DEBUGFUNC("ixgbe_setup_copper_link_82599"); + /* Setup the PHY according to input speed */ status = hw->phy.ops.setup_link_speed(hw, speed, autoneg, autoneg_wait_to_complete); /* Set up MAC */ - ixgbe_setup_mac_link_82599(hw); + ixgbe_start_mac_link_82599(hw, autoneg_wait_to_complete); return status; } @@ -881,6 +883,8 @@ s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw) u32 autoc; u32 autoc2; + DEBUGFUNC("ixgbe_reset_hw_82599"); + /* Call adapter stop to disable tx/rx and clear interrupts */ hw->mac.ops.stop_adapter(hw); @@ -892,7 +896,6 @@ s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw) if (status == IXGBE_ERR_SFP_NOT_SUPPORTED) goto reset_hw_out; - /* Setup SFP module if there is one present. */ if (hw->phy.sfp_setup_needed) { status = hw->mac.ops.setup_sfp(hw); @@ -942,8 +945,6 @@ s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw) msec_delay(50); - - /* * Store the original AUTOC/AUTOC2 values if they have not been * stored off yet. Otherwise restore the stored original @@ -994,311 +995,15 @@ s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw) hw->mac.num_rar_entries--; } + /* Store the alternative WWNN/WWPN prefix */ + hw->mac.ops.get_wwn_prefix(hw, &hw->mac.wwnn_prefix, + &hw->mac.wwpn_prefix); + reset_hw_out: return status; } /** - * ixgbe_insert_mac_addr_82599 - Find a RAR for this mac address - * @hw: pointer to hardware structure - * @addr: Address to put into receive address register - * @vmdq: VMDq pool to assign - * - * Puts an ethernet address into a receive address register, or - * finds the rar that it is aleady in; adds to the pool list - **/ -s32 ixgbe_insert_mac_addr_82599(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) -{ - static const u32 NO_EMPTY_RAR_FOUND = 0xFFFFFFFF; - u32 first_empty_rar = NO_EMPTY_RAR_FOUND; - u32 rar; - u32 rar_low, rar_high; - u32 addr_low, addr_high; - - /* swap bytes for HW little endian */ - addr_low = addr[0] | (addr[1] << 8) - | (addr[2] << 16) - | (addr[3] << 24); - addr_high = addr[4] | (addr[5] << 8); - - /* - * Either find the mac_id in rar or find the first empty space. - * rar_highwater points to just after the highest currently used - * rar in order to shorten the search. It grows when we add a new - * rar to the top. - */ - for (rar = 0; rar < hw->mac.rar_highwater; rar++) { - rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar)); - - if (((IXGBE_RAH_AV & rar_high) == 0) - && first_empty_rar == NO_EMPTY_RAR_FOUND) { - first_empty_rar = rar; - } else if ((rar_high & 0xFFFF) == addr_high) { - rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(rar)); - if (rar_low == addr_low) - break; /* found it already in the rars */ - } - } - - if (rar < hw->mac.rar_highwater) { - /* already there so just add to the pool bits */ - ixgbe_set_vmdq(hw, rar, vmdq); - } else if (first_empty_rar != NO_EMPTY_RAR_FOUND) { - /* stick it into first empty RAR slot we found */ - rar = first_empty_rar; - ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); - } else if (rar == hw->mac.rar_highwater) { - /* add it to the top of the list and inc the highwater mark */ - ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); - hw->mac.rar_highwater++; - } else if (rar >= hw->mac.num_rar_entries) { - return IXGBE_ERR_INVALID_MAC_ADDR; - } - - /* - * If we found rar[0], make sure the default pool bit (we use pool 0) - * remains cleared to be sure default pool packets will get delivered - */ - if (rar == 0) - ixgbe_clear_vmdq(hw, rar, 0); - - return rar; -} - -/** - * ixgbe_clear_vmdq_82599 - Disassociate a VMDq pool index from a rx address - * @hw: pointer to hardware struct - * @rar: receive address register index to disassociate - * @vmdq: VMDq pool index to remove from the rar - **/ -s32 ixgbe_clear_vmdq_82599(struct ixgbe_hw *hw, u32 rar, u32 vmdq) -{ - u32 mpsar_lo, mpsar_hi; - u32 rar_entries = hw->mac.num_rar_entries; - - if (rar < rar_entries) { - mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); - mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); - - if (!mpsar_lo && !mpsar_hi) - goto done; - - if (vmdq == IXGBE_CLEAR_VMDQ_ALL) { - if (mpsar_lo) { - IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0); - mpsar_lo = 0; - } - if (mpsar_hi) { - IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0); - mpsar_hi = 0; - } - } else if (vmdq < 32) { - mpsar_lo &= ~(1 << vmdq); - IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar_lo); - } else { - mpsar_hi &= ~(1 << (vmdq - 32)); - IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar_hi); - } - - /* was that the last pool using this rar? */ - if (mpsar_lo == 0 && mpsar_hi == 0 && rar != 0) - hw->mac.ops.clear_rar(hw, rar); - } else { - DEBUGOUT1("RAR index %d is out of range.\n", rar); - } - -done: - return IXGBE_SUCCESS; -} - -/** - * ixgbe_set_vmdq_82599 - Associate a VMDq pool index with a rx address - * @hw: pointer to hardware struct - * @rar: receive address register index to associate with a VMDq index - * @vmdq: VMDq pool index - **/ -s32 ixgbe_set_vmdq_82599(struct ixgbe_hw *hw, u32 rar, u32 vmdq) -{ - u32 mpsar; - u32 rar_entries = hw->mac.num_rar_entries; - - if (rar < rar_entries) { - if (vmdq < 32) { - mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); - mpsar |= 1 << vmdq; - IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar); - } else { - mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); - mpsar |= 1 << (vmdq - 32); - IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar); - } - } else { - DEBUGOUT1("RAR index %d is out of range.\n", rar); - } - return IXGBE_SUCCESS; -} - -/** - * ixgbe_set_vfta_82599 - Set VLAN filter table - * @hw: pointer to hardware structure - * @vlan: VLAN id to write to VLAN filter - * @vind: VMDq output index that maps queue to VLAN id in VFVFB - * @vlan_on: boolean flag to turn on/off VLAN in VFVF - * - * Turn on/off specified VLAN in the VLAN filter table. - **/ -s32 ixgbe_set_vfta_82599(struct ixgbe_hw *hw, u32 vlan, u32 vind, - bool vlan_on) -{ - u32 regindex; - u32 bitindex; - u32 bits; - u32 first_empty_slot; - u32 vt; - - if (vlan > 4095) - return IXGBE_ERR_PARAM; - - /* - * this is a 2 part operation - first the VFTA, then the - * VLVF and VLVFB if VT Mode is set - */ - - /* Part 1 - * The VFTA is a bitstring made up of 128 32-bit registers - * that enable the particular VLAN id, much like the MTA: - * bits[11-5]: which register - * bits[4-0]: which bit in the register - */ - regindex = (vlan >> 5) & 0x7F; - bitindex = vlan & 0x1F; - bits = IXGBE_READ_REG(hw, IXGBE_VFTA(regindex)); - if (vlan_on) - bits |= (1 << bitindex); - else - bits &= ~(1 << bitindex); - IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), bits); - - - /* Part 2 - * If VT Mode is set - * Either vlan_on - * make sure the vlan is in VLVF - * set the vind bit in the matching VLVFB - * Or !vlan_on - * clear the pool bit and possibly the vind - */ - vt = IXGBE_READ_REG(hw, IXGBE_VT_CTL); - if (vt & IXGBE_VT_CTL_VT_ENABLE) { - /* find the vlanid or the first empty slot */ - first_empty_slot = 0; - - for (regindex = 1; regindex < IXGBE_VLVF_ENTRIES; regindex++) { - bits = IXGBE_READ_REG(hw, IXGBE_VLVF(regindex)); - if (!bits && !first_empty_slot) - first_empty_slot = regindex; - else if ((bits & 0x0FFF) == vlan) - break; - } - - if (regindex >= IXGBE_VLVF_ENTRIES) { - if (first_empty_slot) - regindex = first_empty_slot; - else { - DEBUGOUT("No space in VLVF.\n"); - goto out; - } - } - - - if (vlan_on) { - /* set the pool bit */ - if (vind < 32) { - bits = IXGBE_READ_REG(hw, - IXGBE_VLVFB(regindex*2)); - bits |= (1 << vind); - IXGBE_WRITE_REG(hw, - IXGBE_VLVFB(regindex*2), - bits); - } else { - bits = IXGBE_READ_REG(hw, - IXGBE_VLVFB((regindex*2)+1)); - bits |= (1 << vind); - IXGBE_WRITE_REG(hw, - IXGBE_VLVFB((regindex*2)+1), - bits); - } - } else { - /* clear the pool bit */ - if (vind < 32) { - bits = IXGBE_READ_REG(hw, - IXGBE_VLVFB(regindex*2)); - bits &= ~(1 << vind); - IXGBE_WRITE_REG(hw, - IXGBE_VLVFB(regindex*2), - bits); - bits |= IXGBE_READ_REG(hw, - IXGBE_VLVFB((regindex*2)+1)); - } else { - bits = IXGBE_READ_REG(hw, - IXGBE_VLVFB((regindex*2)+1)); - bits &= ~(1 << vind); - IXGBE_WRITE_REG(hw, - IXGBE_VLVFB((regindex*2)+1), - bits); - bits |= IXGBE_READ_REG(hw, - IXGBE_VLVFB(regindex*2)); - } - } - - if (bits) - IXGBE_WRITE_REG(hw, IXGBE_VLVF(regindex), - (IXGBE_VLVF_VIEN | vlan)); - else - IXGBE_WRITE_REG(hw, IXGBE_VLVF(regindex), 0); - } -out: - return IXGBE_SUCCESS; -} - -/** - * ixgbe_clear_vfta_82599 - Clear VLAN filter table - * @hw: pointer to hardware structure - * - * Clears the VLAN filer table, and the VMDq index associated with the filter - **/ -s32 ixgbe_clear_vfta_82599(struct ixgbe_hw *hw) -{ - u32 offset; - - for (offset = 0; offset < hw->mac.vft_size; offset++) - IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0); - - for (offset = 0; offset < IXGBE_VLVF_ENTRIES; offset++) { - IXGBE_WRITE_REG(hw, IXGBE_VLVF(offset), 0); - IXGBE_WRITE_REG(hw, IXGBE_VLVFB(offset*2), 0); - IXGBE_WRITE_REG(hw, IXGBE_VLVFB((offset*2)+1), 0); - } - - return IXGBE_SUCCESS; -} - -/** - * ixgbe_init_uta_tables_82599 - Initialize the Unicast Table Array - * @hw: pointer to hardware structure - **/ -s32 ixgbe_init_uta_tables_82599(struct ixgbe_hw *hw) -{ - int i; - DEBUGOUT(" Clearing UTA\n"); - - for (i = 0; i < 128; i++) - IXGBE_WRITE_REG(hw, IXGBE_UTA(i), 0); - - return IXGBE_SUCCESS; -} - -/** * ixgbe_reinit_fdir_tables_82599 - Reinitialize Flow Director tables. * @hw: pointer to hardware structure **/ @@ -1308,6 +1013,8 @@ s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw) u32 fdirctrl = IXGBE_READ_REG(hw, IXGBE_FDIRCTRL); fdirctrl &= ~IXGBE_FDIRCTRL_INIT_DONE; + DEBUGFUNC("ixgbe_reinit_fdir_tables_82599"); + /* * Before starting reinitialization process, * FDIRCMD.CMD must be zero. @@ -1384,6 +1091,8 @@ s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 pballoc) u32 pbsize; int i; + DEBUGFUNC("ixgbe_init_fdir_signature_82599"); + /* * Before enabling Flow Director, the Rx Packet Buffer size * must be reduced. The new value is the current size minus @@ -1474,6 +1183,8 @@ s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 pballoc) u32 pbsize; int i; + DEBUGFUNC("ixgbe_init_fdir_perfect_82599"); + /* * Before enabling Flow Director, the Rx Packet Buffer size * must be reduced. The new value is the current size minus @@ -1609,6 +1320,8 @@ u16 ixgbe_atr_compute_hash_82599(struct ixgbe_atr_input *atr_input, u32 key) u16 hash_result = 0; int i, j, k, h; + DEBUGFUNC("ixgbe_atr_compute_hash_82599"); + /* * Initialize the fill member to prevent warnings * on some compilers @@ -1687,6 +1400,8 @@ u16 ixgbe_atr_compute_hash_82599(struct ixgbe_atr_input *atr_input, u32 key) **/ s32 ixgbe_atr_set_vlan_id_82599(struct ixgbe_atr_input *input, u16 vlan) { + DEBUGFUNC("ixgbe_atr_set_vlan_id_82599"); + input->byte_stream[IXGBE_ATR_VLAN_OFFSET + 1] = vlan >> 8; input->byte_stream[IXGBE_ATR_VLAN_OFFSET] = vlan & 0xff; @@ -1700,6 +1415,8 @@ s32 ixgbe_atr_set_vlan_id_82599(struct ixgbe_atr_input *input, u16 vlan) **/ s32 ixgbe_atr_set_src_ipv4_82599(struct ixgbe_atr_input *input, u32 src_addr) { + DEBUGFUNC("ixgbe_atr_set_src_ipv4_82599"); + input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 3] = src_addr >> 24; input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 2] = (src_addr >> 16) & 0xff; @@ -1717,6 +1434,8 @@ s32 ixgbe_atr_set_src_ipv4_82599(struct ixgbe_atr_input *input, u32 src_addr) **/ s32 ixgbe_atr_set_dst_ipv4_82599(struct ixgbe_atr_input *input, u32 dst_addr) { + DEBUGFUNC("ixgbe_atr_set_dst_ipv4_82599"); + input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 3] = dst_addr >> 24; input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 2] = (dst_addr >> 16) & 0xff; @@ -1739,6 +1458,8 @@ s32 ixgbe_atr_set_src_ipv6_82599(struct ixgbe_atr_input *input, u32 src_addr_1, u32 src_addr_2, u32 src_addr_3, u32 src_addr_4) { + DEBUGFUNC("ixgbe_atr_set_src_ipv6_82599"); + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET] = src_addr_4 & 0xff; input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 1] = (src_addr_4 >> 8) & 0xff; @@ -1782,6 +1503,8 @@ s32 ixgbe_atr_set_dst_ipv6_82599(struct ixgbe_atr_input *input, u32 dst_addr_1, u32 dst_addr_2, u32 dst_addr_3, u32 dst_addr_4) { + DEBUGFUNC("ixgbe_atr_set_dst_ipv6_82599"); + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET] = dst_addr_4 & 0xff; input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 1] = (dst_addr_4 >> 8) & 0xff; @@ -1820,6 +1543,8 @@ s32 ixgbe_atr_set_dst_ipv6_82599(struct ixgbe_atr_input *input, **/ s32 ixgbe_atr_set_src_port_82599(struct ixgbe_atr_input *input, u16 src_port) { + DEBUGFUNC("ixgbe_atr_set_src_port_82599"); + input->byte_stream[IXGBE_ATR_SRC_PORT_OFFSET + 1] = src_port >> 8; input->byte_stream[IXGBE_ATR_SRC_PORT_OFFSET] = src_port & 0xff; @@ -1833,6 +1558,8 @@ s32 ixgbe_atr_set_src_port_82599(struct ixgbe_atr_input *input, u16 src_port) **/ s32 ixgbe_atr_set_dst_port_82599(struct ixgbe_atr_input *input, u16 dst_port) { + DEBUGFUNC("ixgbe_atr_set_dst_port_82599"); + input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET + 1] = dst_port >> 8; input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET] = dst_port & 0xff; @@ -1846,6 +1573,8 @@ s32 ixgbe_atr_set_dst_port_82599(struct ixgbe_atr_input *input, u16 dst_port) **/ s32 ixgbe_atr_set_flex_byte_82599(struct ixgbe_atr_input *input, u16 flex_byte) { + DEBUGFUNC("ixgbe_atr_set_flex_byte_82599"); + input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET + 1] = flex_byte >> 8; input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET] = flex_byte & 0xff; @@ -1859,6 +1588,8 @@ s32 ixgbe_atr_set_flex_byte_82599(struct ixgbe_atr_input *input, u16 flex_byte) **/ s32 ixgbe_atr_set_vm_pool_82599(struct ixgbe_atr_input *input, u8 vm_pool) { + DEBUGFUNC("ixgbe_atr_set_vm_pool_82599"); + input->byte_stream[IXGBE_ATR_VM_POOL_OFFSET] = vm_pool; return IXGBE_SUCCESS; @@ -1871,6 +1602,8 @@ s32 ixgbe_atr_set_vm_pool_82599(struct ixgbe_atr_input *input, u8 vm_pool) **/ s32 ixgbe_atr_set_l4type_82599(struct ixgbe_atr_input *input, u8 l4type) { + DEBUGFUNC("ixgbe_atr_set_l4type_82599"); + input->byte_stream[IXGBE_ATR_L4TYPE_OFFSET] = l4type; return IXGBE_SUCCESS; @@ -1883,6 +1616,8 @@ s32 ixgbe_atr_set_l4type_82599(struct ixgbe_atr_input *input, u8 l4type) **/ s32 ixgbe_atr_get_vlan_id_82599(struct ixgbe_atr_input *input, u16 *vlan) { + DEBUGFUNC("ixgbe_atr_get_vlan_id_82599"); + *vlan = input->byte_stream[IXGBE_ATR_VLAN_OFFSET]; *vlan |= input->byte_stream[IXGBE_ATR_VLAN_OFFSET + 1] << 8; @@ -1896,6 +1631,8 @@ s32 ixgbe_atr_get_vlan_id_82599(struct ixgbe_atr_input *input, u16 *vlan) **/ s32 ixgbe_atr_get_src_ipv4_82599(struct ixgbe_atr_input *input, u32 *src_addr) { + DEBUGFUNC("ixgbe_atr_get_src_ipv4_82599"); + *src_addr = input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET]; *src_addr |= input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 1] << 8; *src_addr |= input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 2] << 16; @@ -1911,6 +1648,8 @@ s32 ixgbe_atr_get_src_ipv4_82599(struct ixgbe_atr_input *input, u32 *src_addr) **/ s32 ixgbe_atr_get_dst_ipv4_82599(struct ixgbe_atr_input *input, u32 *dst_addr) { + DEBUGFUNC("ixgbe_atr_get_dst_ipv4_82599"); + *dst_addr = input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET]; *dst_addr |= input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 1] << 8; *dst_addr |= input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 2] << 16; @@ -1931,6 +1670,8 @@ s32 ixgbe_atr_get_src_ipv6_82599(struct ixgbe_atr_input *input, u32 *src_addr_1, u32 *src_addr_2, u32 *src_addr_3, u32 *src_addr_4) { + DEBUGFUNC("ixgbe_atr_get_src_ipv6_82599"); + *src_addr_1 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 12]; *src_addr_1 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 13] << 8; *src_addr_1 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 14] << 16; @@ -1966,6 +1707,8 @@ s32 ixgbe_atr_get_dst_ipv6_82599(struct ixgbe_atr_input *input, u32 *dst_addr_1, u32 *dst_addr_2, u32 *dst_addr_3, u32 *dst_addr_4) { + DEBUGFUNC("ixgbe_atr_get_dst_ipv6_82599"); + *dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 12]; *dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 13] << 8; *dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 14] << 16; @@ -2001,6 +1744,8 @@ s32 ixgbe_atr_get_dst_ipv6_82599(struct ixgbe_atr_input *input, **/ s32 ixgbe_atr_get_src_port_82599(struct ixgbe_atr_input *input, u16 *src_port) { + DEBUGFUNC("ixgbe_atr_get_src_port_82599"); + *src_port = input->byte_stream[IXGBE_ATR_SRC_PORT_OFFSET] << 8; *src_port |= input->byte_stream[IXGBE_ATR_SRC_PORT_OFFSET + 1]; @@ -2019,6 +1764,8 @@ s32 ixgbe_atr_get_src_port_82599(struct ixgbe_atr_input *input, u16 *src_port) **/ s32 ixgbe_atr_get_dst_port_82599(struct ixgbe_atr_input *input, u16 *dst_port) { + DEBUGFUNC("ixgbe_atr_get_dst_port_82599"); + *dst_port = input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET] << 8; *dst_port |= input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET + 1]; @@ -2032,6 +1779,8 @@ s32 ixgbe_atr_get_dst_port_82599(struct ixgbe_atr_input *input, u16 *dst_port) **/ s32 ixgbe_atr_get_flex_byte_82599(struct ixgbe_atr_input *input, u16 *flex_byte) { + DEBUGFUNC("ixgbe_atr_get_flex_byte_82599"); + *flex_byte = input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET]; *flex_byte |= input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET + 1] << 8; @@ -2045,6 +1794,8 @@ s32 ixgbe_atr_get_flex_byte_82599(struct ixgbe_atr_input *input, u16 *flex_byte) **/ s32 ixgbe_atr_get_vm_pool_82599(struct ixgbe_atr_input *input, u8 *vm_pool) { + DEBUGFUNC("ixgbe_atr_get_vm_pool_82599"); + *vm_pool = input->byte_stream[IXGBE_ATR_VM_POOL_OFFSET]; return IXGBE_SUCCESS; @@ -2057,6 +1808,8 @@ s32 ixgbe_atr_get_vm_pool_82599(struct ixgbe_atr_input *input, u8 *vm_pool) **/ s32 ixgbe_atr_get_l4type_82599(struct ixgbe_atr_input *input, u8 *l4type) { + DEBUGFUNC("ixgbe_atr_get_l4type__82599"); + *l4type = input->byte_stream[IXGBE_ATR_L4TYPE_OFFSET]; return IXGBE_SUCCESS; @@ -2078,6 +1831,8 @@ s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw, u16 bucket_hash, sig_hash; u8 l4type; + DEBUGFUNC("ixgbe_fdir_add_signature_filter_82599"); + bucket_hash = ixgbe_atr_compute_hash_82599(input, IXGBE_ATR_BUCKET_HASH_KEY); @@ -2149,6 +1904,8 @@ s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw, u16 bucket_hash; u8 l4type; + DEBUGFUNC("ixgbe_fdir_add_perfect_filter_82599"); + /* Get our input values */ ixgbe_atr_get_l4type_82599(input, &l4type); @@ -2237,6 +1994,8 @@ s32 ixgbe_read_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 *val) { u32 core_ctl; + DEBUGFUNC("ixgbe_read_analog_reg8_82599"); + IXGBE_WRITE_REG(hw, IXGBE_CORECTL, IXGBE_CORECTL_WRITE_CMD | (reg << 8)); IXGBE_WRITE_FLUSH(hw); @@ -2259,6 +2018,8 @@ s32 ixgbe_write_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 val) { u32 core_ctl; + DEBUGFUNC("ixgbe_write_analog_reg8_82599"); + core_ctl = (reg << 8) | val; IXGBE_WRITE_REG(hw, IXGBE_CORECTL, core_ctl); IXGBE_WRITE_FLUSH(hw); @@ -2277,18 +2038,35 @@ s32 ixgbe_write_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 val) **/ s32 ixgbe_start_hw_rev_1_82599(struct ixgbe_hw *hw) { - u32 q_num; + u32 i; + u32 regval; s32 ret_val = IXGBE_SUCCESS; + DEBUGFUNC("ixgbe_start_hw_rev_1__82599"); + ret_val = ixgbe_start_hw_generic(hw); /* Clear the rate limiters */ - for (q_num = 0; q_num < hw->mac.max_tx_queues; q_num++) { - IXGBE_WRITE_REG(hw, IXGBE_RTTDQSEL, q_num); + for (i = 0; i < hw->mac.max_tx_queues; i++) { + IXGBE_WRITE_REG(hw, IXGBE_RTTDQSEL, i); IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRC, 0); } IXGBE_WRITE_FLUSH(hw); + /* Disable relaxed ordering */ + for (i = 0; i < hw->mac.max_tx_queues; i++) { + regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i)); + regval &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN; + IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), regval); + } + + for (i = 0; i < hw->mac.max_rx_queues; i++) { + regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i)); + regval &= ~(IXGBE_DCA_RXCTRL_DESC_WRO_EN | + IXGBE_DCA_RXCTRL_DESC_HSRO_EN); + IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval); + } + /* We need to run link autotry after the driver loads */ hw->mac.autotry_restart = TRUE; @@ -2309,6 +2087,8 @@ s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw) { s32 status = IXGBE_ERR_PHY_ADDR_INVALID; + DEBUGFUNC("ixgbe_identify_phy_82599"); + /* Detect PHY if not unknown - returns success if already detected. */ status = ixgbe_identify_phy_generic(hw); if (status != IXGBE_SUCCESS) @@ -2343,6 +2123,8 @@ u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw) u16 ext_ability = 0; u8 comp_codes_10g = 0; + DEBUGFUNC("ixgbe_get_support_physical_layer_82599"); + hw->phy.ops.identify(hw); if (hw->phy.type == ixgbe_phy_tn || @@ -2446,6 +2228,8 @@ s32 ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, u32 regval) int i; int secrxreg; + DEBUGFUNC("ixgbe_enable_rx_dma_82599"); + /* * Workaround for 82599 silicon errata when enabling the Rx datapath. * If traffic is incoming before we enable the Rx unit, it could hang @@ -2488,119 +2272,14 @@ s32 ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, u32 regval) **/ s32 ixgbe_get_device_caps_82599(struct ixgbe_hw *hw, u16 *device_caps) { - hw->eeprom.ops.read(hw, IXGBE_DEVICE_CAPS, device_caps); - - return IXGBE_SUCCESS; -} - -/** - * ixgbe_get_san_mac_addr_offset_82599 - SAN MAC address offset for 82599 - * @hw: pointer to hardware structure - * @san_mac_offset: SAN MAC address offset - * - * This function will read the EEPROM location for the SAN MAC address - * pointer, and returns the value at that location. This is used in both - * get and set mac_addr routines. - **/ -s32 ixgbe_get_san_mac_addr_offset_82599(struct ixgbe_hw *hw, - u16 *san_mac_offset) -{ - /* - * First read the EEPROM pointer to see if the MAC addresses are - * available. - */ - hw->eeprom.ops.read(hw, IXGBE_SAN_MAC_ADDR_PTR, san_mac_offset); + DEBUGFUNC("ixgbe_get_device_caps_82599"); - return IXGBE_SUCCESS; -} - -/** - * ixgbe_get_san_mac_addr_82599 - SAN MAC address retrieval for 82599 - * @hw: pointer to hardware structure - * @san_mac_addr: SAN MAC address - * - * Reads the SAN MAC address from the EEPROM, if it's available. This is - * per-port, so set_lan_id() must be called before reading the addresses. - * set_lan_id() is called by identify_sfp(), but this cannot be relied - * upon for non-SFP connections, so we must call it here. - **/ -s32 ixgbe_get_san_mac_addr_82599(struct ixgbe_hw *hw, u8 *san_mac_addr) -{ - u16 san_mac_data, san_mac_offset; - u8 i; - - /* - * First read the EEPROM pointer to see if the MAC addresses are - * available. If they're not, no point in calling set_lan_id() here. - */ - ixgbe_get_san_mac_addr_offset_82599(hw, &san_mac_offset); - - if ((san_mac_offset == 0) || (san_mac_offset == 0xFFFF)) { - /* - * No addresses available in this EEPROM. It's not an - * error though, so just wipe the local address and return. - */ - for (i = 0; i < 6; i++) - san_mac_addr[i] = 0xFF; - - goto san_mac_addr_out; - } - - /* make sure we know which port we need to program */ - hw->mac.ops.set_lan_id(hw); - /* apply the port offset to the address offset */ - (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) : - (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET); - for (i = 0; i < 3; i++) { - hw->eeprom.ops.read(hw, san_mac_offset, &san_mac_data); - san_mac_addr[i * 2] = (u8)(san_mac_data); - san_mac_addr[i * 2 + 1] = (u8)(san_mac_data >> 8); - san_mac_offset++; - } + hw->eeprom.ops.read(hw, IXGBE_DEVICE_CAPS, device_caps); -san_mac_addr_out: return IXGBE_SUCCESS; } /** - * ixgbe_set_san_mac_addr_82599 - Write the SAN MAC address to the EEPROM - * @hw: pointer to hardware structure - * @san_mac_addr: SAN MAC address - * - * Write a SAN MAC address to the EEPROM. - **/ -s32 ixgbe_set_san_mac_addr_82599(struct ixgbe_hw *hw, u8 *san_mac_addr) -{ - s32 status = IXGBE_SUCCESS; - u16 san_mac_data, san_mac_offset; - u8 i; - - /* Look for SAN mac address pointer. If not defined, return */ - ixgbe_get_san_mac_addr_offset_82599(hw, &san_mac_offset); - - if ((san_mac_offset == 0) || (san_mac_offset == 0xFFFF)) { - status = IXGBE_ERR_NO_SAN_ADDR_PTR; - goto san_mac_addr_out; - } - - /* Make sure we know which port we need to write */ - hw->mac.ops.set_lan_id(hw); - /* Apply the port offset to the address offset */ - (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) : - (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET); - - for (i = 0; i < 3; i++) { - san_mac_data = (u16)((u16)(san_mac_addr[i * 2 + 1]) << 8); - san_mac_data |= (u16)(san_mac_addr[i * 2]); - hw->eeprom.ops.write(hw, san_mac_offset, san_mac_data); - san_mac_offset++; - } - -san_mac_addr_out: - return status; -} - -/** * ixgbe_verify_fw_version_82599 - verify fw version for 82599 * @hw: pointer to hardware structure * @@ -2616,6 +2295,8 @@ static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw) u16 fw_offset, fw_ptp_cfg_offset; u16 fw_version = 0; + DEBUGFUNC("ixgbe_verify_fw_version_82599"); + /* firmware check is only necessary for SFI devices */ if (hw->phy.media_type != ixgbe_media_type_fiber) { status = IXGBE_SUCCESS; diff --git a/sys/dev/ixgbe/ixgbe_api.c b/sys/dev/ixgbe/ixgbe_api.c index 9c3356fff591..44644574860c 100644 --- a/sys/dev/ixgbe/ixgbe_api.c +++ b/sys/dev/ixgbe/ixgbe_api.c @@ -54,6 +54,8 @@ s32 ixgbe_init_shared_code(struct ixgbe_hw *hw) { s32 status; + DEBUGFUNC("ixgbe_init_shared_code"); + /* * Set the mac type */ @@ -94,6 +96,7 @@ s32 ixgbe_set_mac_type(struct ixgbe_hw *hw) case IXGBE_DEV_ID_82598AF_SINGLE_PORT: case IXGBE_DEV_ID_82598AF_DUAL_PORT: case IXGBE_DEV_ID_82598AT: + case IXGBE_DEV_ID_82598AT2: case IXGBE_DEV_ID_82598EB_CX4: case IXGBE_DEV_ID_82598_CX4_DUAL_PORT: case IXGBE_DEV_ID_82598_DA_DUAL_PORT: @@ -103,7 +106,9 @@ s32 ixgbe_set_mac_type(struct ixgbe_hw *hw) hw->mac.type = ixgbe_mac_82598EB; break; case IXGBE_DEV_ID_82599_KX4: + case IXGBE_DEV_ID_82599_KX4_MEZZ: case IXGBE_DEV_ID_82599_XAUI_LOM: + case IXGBE_DEV_ID_82599_COMBO_BACKPLANE: case IXGBE_DEV_ID_82599_SFP: case IXGBE_DEV_ID_82599_CX4: hw->mac.type = ixgbe_mac_82599EB; @@ -244,6 +249,23 @@ s32 ixgbe_get_device_caps(struct ixgbe_hw *hw, u16 *device_caps) } /** + * ixgbe_get_wwn_prefix - Get alternative WWNN/WWPN prefix from the EEPROM + * @hw: pointer to hardware structure + * @wwnn_prefix: the alternative WWNN prefix + * @wwpn_prefix: the alternative WWPN prefix + * + * This function will read the EEPROM from the alternative SAN MAC address + * block to check the support for the alternative WWNN/WWPN prefix support. + **/ +s32 ixgbe_get_wwn_prefix(struct ixgbe_hw *hw, u16 *wwnn_prefix, + u16 *wwpn_prefix) +{ + return ixgbe_call_func(hw, hw->mac.ops.get_wwn_prefix, + (hw, wwnn_prefix, wwpn_prefix), + IXGBE_NOT_IMPLEMENTED); +} + +/** * ixgbe_get_bus_info - Set PCI bus info * @hw: pointer to hardware structure * @@ -439,19 +461,6 @@ s32 ixgbe_setup_phy_link_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed, } /** - * ixgbe_setup_link - Configure link settings - * @hw: pointer to hardware structure - * - * Configures link settings based on values in the ixgbe_hw struct. - * Restarts the link. Performs autonegotiation if needed. - **/ -s32 ixgbe_setup_link(struct ixgbe_hw *hw) -{ - return ixgbe_call_func(hw, hw->mac.ops.setup_link, (hw), - IXGBE_NOT_IMPLEMENTED); -} - -/** * ixgbe_check_link - Get link and speed status * @hw: pointer to hardware structure * @@ -466,18 +475,19 @@ s32 ixgbe_check_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed, } /** - * ixgbe_setup_link_speed - Set link speed + * ixgbe_setup_link - Set link speed * @hw: pointer to hardware structure * @speed: new link speed * @autoneg: TRUE if autonegotiation enabled * - * Set the link speed and restarts the link. + * Configures link settings. Restarts the link. + * Performs autonegotiation if needed. **/ -s32 ixgbe_setup_link_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed, +s32 ixgbe_setup_link(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete) { - return ixgbe_call_func(hw, hw->mac.ops.setup_link_speed, (hw, speed, + return ixgbe_call_func(hw, hw->mac.ops.setup_link, (hw, speed, autoneg, autoneg_wait_to_complete), IXGBE_NOT_IMPLEMENTED); } diff --git a/sys/dev/ixgbe/ixgbe_api.h b/sys/dev/ixgbe/ixgbe_api.h index 654f22f6c322..8ab78ad8720c 100644 --- a/sys/dev/ixgbe/ixgbe_api.h +++ b/sys/dev/ixgbe/ixgbe_api.h @@ -67,8 +67,7 @@ s32 ixgbe_setup_phy_link_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete); -s32 ixgbe_setup_link(struct ixgbe_hw *hw); -s32 ixgbe_setup_link_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed, +s32 ixgbe_setup_link(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete); s32 ixgbe_check_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up, bool link_up_wait_to_complete); @@ -97,6 +96,7 @@ s32 ixgbe_update_uc_addr_list(struct ixgbe_hw *hw, u8 *addr_list, u32 addr_count, ixgbe_mc_addr_itr func); s32 ixgbe_update_mc_addr_list(struct ixgbe_hw *hw, u8 *mc_addr_list, u32 mc_addr_count, ixgbe_mc_addr_itr func); +void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr_list, u32 vmdq); s32 ixgbe_enable_mc(struct ixgbe_hw *hw); s32 ixgbe_disable_mc(struct ixgbe_hw *hw); s32 ixgbe_clear_vfta(struct ixgbe_hw *hw); @@ -164,6 +164,8 @@ s32 ixgbe_set_san_mac_addr(struct ixgbe_hw *hw, u8 *san_mac_addr); s32 ixgbe_get_device_caps(struct ixgbe_hw *hw, u16 *device_caps); s32 ixgbe_acquire_swfw_semaphore(struct ixgbe_hw *hw, u16 mask); void ixgbe_release_swfw_semaphore(struct ixgbe_hw *hw, u16 mask); +s32 ixgbe_get_wwn_prefix(struct ixgbe_hw *hw, u16 *wwnn_prefix, + u16 *wwpn_prefix); #endif /* _IXGBE_API_H_ */ diff --git a/sys/dev/ixgbe/ixgbe_common.c b/sys/dev/ixgbe/ixgbe_common.c index 30c372d8a9b0..89e57d83dabb 100644 --- a/sys/dev/ixgbe/ixgbe_common.c +++ b/sys/dev/ixgbe/ixgbe_common.c @@ -35,7 +35,6 @@ #include "ixgbe_common.h" #include "ixgbe_api.h" -static s32 ixgbe_poll_eeprom_eerd_done(struct ixgbe_hw *hw); static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw); static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw); static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw); @@ -47,9 +46,11 @@ static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count); static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec); static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec); static void ixgbe_release_eeprom(struct ixgbe_hw *hw); -static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw); static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr); +static s32 ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw, + u16 *san_mac_offset); +s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan); /** * ixgbe_init_ops_generic - Inits function ptrs @@ -63,17 +64,20 @@ s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw) struct ixgbe_mac_info *mac = &hw->mac; u32 eec = IXGBE_READ_REG(hw, IXGBE_EEC); + DEBUGFUNC("ixgbe_init_ops_generic"); + /* EEPROM */ eeprom->ops.init_params = &ixgbe_init_eeprom_params_generic; /* If EEPROM is valid (bit 8 = 1), use EERD otherwise use bit bang */ if (eec & (1 << 8)) - eeprom->ops.read = &ixgbe_read_eeprom_generic; + eeprom->ops.read = &ixgbe_read_eerd_generic; else eeprom->ops.read = &ixgbe_read_eeprom_bit_bang_generic; eeprom->ops.write = &ixgbe_write_eeprom_generic; eeprom->ops.validate_checksum = &ixgbe_validate_eeprom_checksum_generic; eeprom->ops.update_checksum = &ixgbe_update_eeprom_checksum_generic; + eeprom->ops.calc_checksum = &ixgbe_calc_eeprom_checksum_generic; /* MAC */ mac->ops.init_hw = &ixgbe_init_hw_generic; @@ -117,7 +121,6 @@ s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw) /* Link */ mac->ops.get_link_capabilities = NULL; mac->ops.setup_link = NULL; - mac->ops.setup_link_speed = NULL; mac->ops.check_link = NULL; return IXGBE_SUCCESS; @@ -137,6 +140,8 @@ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw) u32 ctrl_ext; s32 ret_val = IXGBE_SUCCESS; + DEBUGFUNC("ixgbe_start_hw_generic"); + /* Set the media type */ hw->phy.media_type = hw->mac.ops.get_media_type(hw); @@ -177,6 +182,8 @@ s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw) { s32 status = IXGBE_SUCCESS; + DEBUGFUNC("ixgbe_init_hw_generic"); + /* Reset the hardware */ status = hw->mac.ops.reset_hw(hw); @@ -199,6 +206,8 @@ s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw) { u16 i = 0; + DEBUGFUNC("ixgbe_clear_hw_cntrs_generic"); + IXGBE_READ_REG(hw, IXGBE_CRCERRS); IXGBE_READ_REG(hw, IXGBE_ILLERRC); IXGBE_READ_REG(hw, IXGBE_ERRBC); @@ -324,6 +333,8 @@ s32 ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, u8 *mac_addr) u32 rar_low; u16 i; + DEBUGFUNC("ixgbe_get_mac_addr_generic"); + rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(0)); rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(0)); @@ -347,6 +358,8 @@ s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw) struct ixgbe_mac_info *mac = &hw->mac; u16 link_status; + DEBUGFUNC("ixgbe_get_bus_info_generic"); + hw->bus.type = ixgbe_bus_type_pci_express; /* Get the negotiated link width and speed from PCI config space */ @@ -399,6 +412,8 @@ void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw) struct ixgbe_bus_info *bus = &hw->bus; u32 reg; + DEBUGFUNC("ixgbe_set_lan_id_multi_port_pcie"); + reg = IXGBE_READ_REG(hw, IXGBE_STATUS); bus->func = (reg & IXGBE_STATUS_LAN_ID) >> IXGBE_STATUS_LAN_ID_SHIFT; bus->lan_id = bus->func; @@ -424,6 +439,8 @@ s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw) u32 reg_val; u16 i; + DEBUGFUNC("ixgbe_stop_adapter_generic"); + /* * Set the adapter_stopped flag so other driver functions stop touching * the hardware @@ -472,6 +489,8 @@ s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index) { u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); + DEBUGFUNC("ixgbe_led_on_generic"); + /* To turn on the LED, set mode to ON. */ led_reg &= ~IXGBE_LED_MODE_MASK(index); led_reg |= IXGBE_LED_ON << IXGBE_LED_MODE_SHIFT(index); @@ -490,6 +509,8 @@ s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index) { u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); + DEBUGFUNC("ixgbe_led_off_generic"); + /* To turn off the LED, set mode to OFF. */ led_reg &= ~IXGBE_LED_MODE_MASK(index); led_reg |= IXGBE_LED_OFF << IXGBE_LED_MODE_SHIFT(index); @@ -512,6 +533,8 @@ s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw) u32 eec; u16 eeprom_size; + DEBUGFUNC("ixgbe_init_eeprom_params_generic"); + if (eeprom->type == ixgbe_eeprom_uninitialized) { eeprom->type = ixgbe_eeprom_none; /* Set default semaphore delay to 10ms which is a well @@ -533,7 +556,7 @@ s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw) eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> IXGBE_EEC_SIZE_SHIFT); eeprom->word_size = 1 << (eeprom_size + - IXGBE_EEPROM_WORD_SIZE_SHIFT); + IXGBE_EEPROM_WORD_SIZE_BASE_SHIFT); } if (eec & IXGBE_EEC_ADDR_SIZE) @@ -562,6 +585,8 @@ s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data) s32 status; u8 write_opcode = IXGBE_EEPROM_WRITE_OPCODE_SPI; + DEBUGFUNC("ixgbe_write_eeprom_generic"); + hw->eeprom.ops.init_params(hw); if (offset >= hw->eeprom.word_size) { @@ -629,6 +654,8 @@ s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, u16 word_in; u8 read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI; + DEBUGFUNC("ixgbe_read_eeprom_bit_bang_generic"); + hw->eeprom.ops.init_params(hw); if (offset >= hw->eeprom.word_size) { @@ -675,18 +702,20 @@ out: } /** - * ixgbe_read_eeprom_generic - Read EEPROM word using EERD + * ixgbe_read_eerd_generic - Read EEPROM word using EERD * @hw: pointer to hardware structure * @offset: offset of word in the EEPROM to read * @data: word read from the EEPROM * * Reads a 16 bit word from the EEPROM using the EERD register. **/ -s32 ixgbe_read_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 *data) +s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data) { u32 eerd; s32 status; + DEBUGFUNC("ixgbe_read_eerd_generic"); + hw->eeprom.ops.init_params(hw); if (offset >= hw->eeprom.word_size) { @@ -694,15 +723,15 @@ s32 ixgbe_read_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 *data) goto out; } - eerd = (offset << IXGBE_EEPROM_READ_ADDR_SHIFT) + - IXGBE_EEPROM_READ_REG_START; + eerd = (offset << IXGBE_EEPROM_RW_ADDR_SHIFT) + + IXGBE_EEPROM_RW_REG_START; IXGBE_WRITE_REG(hw, IXGBE_EERD, eerd); - status = ixgbe_poll_eeprom_eerd_done(hw); + status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_READ); if (status == IXGBE_SUCCESS) *data = (IXGBE_READ_REG(hw, IXGBE_EERD) >> - IXGBE_EEPROM_READ_REG_DATA); + IXGBE_EEPROM_RW_REG_DATA); else DEBUGOUT("Eeprom read timed out\n"); @@ -711,20 +740,28 @@ out: } /** - * ixgbe_poll_eeprom_eerd_done - Poll EERD status + * ixgbe_poll_eerd_eewr_done - Poll EERD read or EEWR write status * @hw: pointer to hardware structure + * @ee_reg: EEPROM flag for polling * - * Polls the status bit (bit 1) of the EERD to determine when the read is done. + * Polls the status bit (bit 1) of the EERD or EEWR to determine when the + * read or write is done respectively. **/ -static s32 ixgbe_poll_eeprom_eerd_done(struct ixgbe_hw *hw) +s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg) { u32 i; u32 reg; s32 status = IXGBE_ERR_EEPROM; - for (i = 0; i < IXGBE_EERD_ATTEMPTS; i++) { - reg = IXGBE_READ_REG(hw, IXGBE_EERD); - if (reg & IXGBE_EEPROM_READ_REG_DONE) { + DEBUGFUNC("ixgbe_poll_eerd_eewr_done"); + + for (i = 0; i < IXGBE_EERD_EEWR_ATTEMPTS; i++) { + if (ee_reg == IXGBE_NVM_POLL_READ) + reg = IXGBE_READ_REG(hw, IXGBE_EERD); + else + reg = IXGBE_READ_REG(hw, IXGBE_EEWR); + + if (reg & IXGBE_EEPROM_RW_REG_DONE) { status = IXGBE_SUCCESS; break; } @@ -746,6 +783,8 @@ static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw) u32 eec; u32 i; + DEBUGFUNC("ixgbe_acquire_eeprom"); + if (ixgbe_acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) != IXGBE_SUCCESS) status = IXGBE_ERR_SWFW_SYNC; @@ -798,6 +837,8 @@ static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw) u32 i; u32 swsm; + DEBUGFUNC("ixgbe_get_eeprom_semaphore"); + /* Get SMBI software semaphore between device drivers first */ for (i = 0; i < timeout; i++) { /* @@ -860,6 +901,8 @@ static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw) { u32 swsm; + DEBUGFUNC("ixgbe_release_eeprom_semaphore"); + swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); /* Release both semaphores by writing 0 to the bits SWESMBI and SMBI */ @@ -878,6 +921,8 @@ static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw) u16 i; u8 spi_stat_reg; + DEBUGFUNC("ixgbe_ready_eeprom"); + /* * Read "Status Register" repeatedly until the LSB is cleared. The * EEPROM will signal that the command has been completed by clearing @@ -915,6 +960,8 @@ static void ixgbe_standby_eeprom(struct ixgbe_hw *hw) { u32 eec; + DEBUGFUNC("ixgbe_standby_eeprom"); + eec = IXGBE_READ_REG(hw, IXGBE_EEC); /* Toggle CS to flush commands */ @@ -941,6 +988,8 @@ static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data, u32 mask; u32 i; + DEBUGFUNC("ixgbe_shift_out_eeprom_bits"); + eec = IXGBE_READ_REG(hw, IXGBE_EEC); /* @@ -993,6 +1042,8 @@ static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count) u32 i; u16 data = 0; + DEBUGFUNC("ixgbe_shift_in_eeprom_bits"); + /* * In order to read a register from the EEPROM, we need to shift * 'count' bits in from the EEPROM. Bits are "shifted in" by raising @@ -1027,6 +1078,8 @@ static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count) **/ static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) { + DEBUGFUNC("ixgbe_raise_eeprom_clk"); + /* * Raise the clock input to the EEPROM * (setting the SK bit), then delay @@ -1044,6 +1097,8 @@ static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) **/ static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) { + DEBUGFUNC("ixgbe_lower_eeprom_clk"); + /* * Lower the clock input to the EEPROM (clearing the SK bit), then * delay @@ -1062,6 +1117,8 @@ static void ixgbe_release_eeprom(struct ixgbe_hw *hw) { u32 eec; + DEBUGFUNC("ixgbe_release_eeprom"); + eec = IXGBE_READ_REG(hw, IXGBE_EEC); eec |= IXGBE_EEC_CS; /* Pull CS high */ @@ -1083,10 +1140,10 @@ static void ixgbe_release_eeprom(struct ixgbe_hw *hw) } /** - * ixgbe_calc_eeprom_checksum - Calculates and returns the checksum + * ixgbe_calc_eeprom_checksum_generic - Calculates and returns the checksum * @hw: pointer to hardware structure **/ -static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw) +u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw) { u16 i; u16 j; @@ -1095,6 +1152,8 @@ static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw) u16 pointer = 0; u16 word = 0; + DEBUGFUNC("ixgbe_calc_eeprom_checksum_generic"); + /* Include 0x0-0x3F in the checksum */ for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) { if (hw->eeprom.ops.read(hw, i, &word) != IXGBE_SUCCESS) { @@ -1141,6 +1200,8 @@ s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, u16 checksum; u16 read_checksum = 0; + DEBUGFUNC("ixgbe_validate_eeprom_checksum_generic"); + /* * Read the first word from the EEPROM. If this times out or fails, do * not continue or we could be in for a very long wait while every @@ -1149,7 +1210,7 @@ s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, status = hw->eeprom.ops.read(hw, 0, &checksum); if (status == IXGBE_SUCCESS) { - checksum = ixgbe_calc_eeprom_checksum(hw); + checksum = hw->eeprom.ops.calc_checksum(hw); hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum); @@ -1179,6 +1240,8 @@ s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw) s32 status; u16 checksum; + DEBUGFUNC("ixgbe_update_eeprom_checksum_generic"); + /* * Read the first word from the EEPROM. If this times out or fails, do * not continue or we could be in for a very long wait while every @@ -1187,7 +1250,7 @@ s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw) status = hw->eeprom.ops.read(hw, 0, &checksum); if (status == IXGBE_SUCCESS) { - checksum = ixgbe_calc_eeprom_checksum(hw); + checksum = hw->eeprom.ops.calc_checksum(hw); status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM, checksum); } else { @@ -1207,6 +1270,8 @@ s32 ixgbe_validate_mac_addr(u8 *mac_addr) { s32 status = IXGBE_SUCCESS; + DEBUGFUNC("ixgbe_validate_mac_addr"); + /* Make sure it is not a multicast address */ if (IXGBE_IS_MULTICAST(mac_addr)) { DEBUGOUT("MAC address is multicast\n"); @@ -1240,6 +1305,8 @@ s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, u32 rar_low, rar_high; u32 rar_entries = hw->mac.num_rar_entries; + DEBUGFUNC("ixgbe_set_rar_generic"); + /* setup VMDq pool selection before this RAR gets enabled */ hw->mac.ops.set_vmdq(hw, index, vmdq); @@ -1286,6 +1353,8 @@ s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index) u32 rar_high; u32 rar_entries = hw->mac.num_rar_entries; + DEBUGFUNC("ixgbe_clear_rar_generic"); + /* Make sure we are using a valid rar index range */ if (index < rar_entries) { /* @@ -1321,6 +1390,8 @@ s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw) u32 i; u32 rar_entries = hw->mac.num_rar_entries; + DEBUGFUNC("ixgbe_init_rx_addrs_generic"); + /* * If the current mac address is valid, assume it is a software override * to the permanent address. @@ -1383,6 +1454,8 @@ void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) u32 rar_entries = hw->mac.num_rar_entries; u32 rar; + DEBUGFUNC("ixgbe_add_uc_addr"); + DEBUGOUT6(" UC Addr = %.2X %.2X %.2X %.2X %.2X %.2X\n", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); @@ -1426,6 +1499,8 @@ s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list, u32 fctrl; u32 vmdq; + DEBUGFUNC("ixgbe_update_uc_addr_list_generic"); + /* * Clear accounting of old secondary address list, * don't count RAR[0] @@ -1435,10 +1510,10 @@ s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list, hw->addr_ctrl.overflow_promisc = 0; /* Zero out the other receive addresses */ - DEBUGOUT1("Clearing RAR[1-%d]\n", hw->addr_ctrl.rar_used_count); - for (i = 1; i <= hw->addr_ctrl.rar_used_count; i++) { - IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0); - IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0); + DEBUGOUT1("Clearing RAR[1-%d]\n", uc_addr_in_use+1); + for (i = 0; i < uc_addr_in_use; i++) { + IXGBE_WRITE_REG(hw, IXGBE_RAL(1+i), 0); + IXGBE_WRITE_REG(hw, IXGBE_RAH(1+i), 0); } /* Add the new addresses */ @@ -1486,6 +1561,8 @@ static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr) { u32 vector = 0; + DEBUGFUNC("ixgbe_mta_vector"); + switch (hw->mac.mc_filter_type) { case 0: /* use bits [47:36] of the address */ vector = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4)); @@ -1524,6 +1601,8 @@ void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr) u32 vector_reg; u32 mta_reg; + DEBUGFUNC("ixgbe_set_mta"); + hw->addr_ctrl.mta_in_use++; vector = ixgbe_mta_vector(hw, mc_addr); @@ -1563,6 +1642,8 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, u32 i; u32 vmdq; + DEBUGFUNC("ixgbe_update_mc_addr_list_generic"); + /* * Set the new number of MC addresses that we are being requested to * use. @@ -1600,6 +1681,8 @@ s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw) { struct ixgbe_addr_filter_info *a = &hw->addr_ctrl; + DEBUGFUNC("ixgbe_enable_mc_generic"); + if (a->mta_in_use > 0) IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type); @@ -1617,6 +1700,8 @@ s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw) { struct ixgbe_addr_filter_info *a = &hw->addr_ctrl; + DEBUGFUNC("ixgbe_disable_mc_generic"); + if (a->mta_in_use > 0) IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type); @@ -1692,7 +1777,7 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num) break; default: DEBUGOUT("Flow control param set incorrectly\n"); - ret_val = -IXGBE_ERR_CONFIG; + ret_val = IXGBE_ERR_CONFIG; goto out; break; } @@ -1761,6 +1846,7 @@ s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw) s32 ret_val = IXGBE_SUCCESS; ixgbe_link_speed speed; u32 pcs_anadv_reg, pcs_lpab_reg, linkstat; + u32 links2, anlp1_reg, autoc_reg, links; bool link_up; DEBUGFUNC("ixgbe_fc_autoneg"); @@ -1769,27 +1855,68 @@ s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw) * AN should have completed when the cable was plugged in. * Look for reasons to bail out. Bail out if: * - FC autoneg is disabled, or if - * - we don't have multispeed fiber, or if - * - we're not running at 1G, or if - * - link is not up, or if - * - link is up but AN did not complete, or if - * - link is up and AN completed but timed out + * - link is not up. * - * Since we're being called from an LSC, link is already know to be up. + * Since we're being called from an LSC, link is already known to be up. * So use link_up_wait_to_complete=FALSE. */ hw->mac.ops.check_link(hw, &speed, &link_up, FALSE); - linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA); - if (hw->fc.disable_fc_autoneg || - !hw->phy.multispeed_fiber || - (speed != IXGBE_LINK_SPEED_1GB_FULL) || - !link_up || - ((linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) || - ((linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) { + if (hw->fc.disable_fc_autoneg || (!link_up)) { + hw->fc.fc_was_autonegged = FALSE; + hw->fc.current_mode = hw->fc.requested_mode; + goto out; + } + + /* + * On backplane, bail out if + * - backplane autoneg was not completed, or if + * - we are 82599 and link partner is not AN enabled + */ + if (hw->phy.media_type == ixgbe_media_type_backplane) { + links = IXGBE_READ_REG(hw, IXGBE_LINKS); + if ((links & IXGBE_LINKS_KX_AN_COMP) == 0) { + hw->fc.fc_was_autonegged = FALSE; + hw->fc.current_mode = hw->fc.requested_mode; + goto out; + } + + if (hw->mac.type == ixgbe_mac_82599EB) { + links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2); + if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0) { + hw->fc.fc_was_autonegged = FALSE; + hw->fc.current_mode = hw->fc.requested_mode; + goto out; + } + } + } + + /* + * On multispeed fiber at 1g, bail out if + * - link is up but AN did not complete, or if + * - link is up and AN completed but timed out + */ + if (hw->phy.multispeed_fiber && (speed == IXGBE_LINK_SPEED_1GB_FULL)) { + linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA); + if (((linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) || + ((linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) { + hw->fc.fc_was_autonegged = FALSE; + hw->fc.current_mode = hw->fc.requested_mode; + goto out; + } + } + + /* + * Bail out on + * - copper or CX4 adapters + * - fiber adapters running at 10gig + */ + if ((hw->phy.media_type == ixgbe_media_type_copper) || + (hw->phy.media_type == ixgbe_media_type_cx4) || + ((hw->phy.media_type == ixgbe_media_type_fiber) && + (speed == IXGBE_LINK_SPEED_10GB_FULL))) { hw->fc.fc_was_autonegged = FALSE; hw->fc.current_mode = hw->fc.requested_mode; - DEBUGOUT("Autoneg FC was skipped.\n"); goto out; } @@ -1797,41 +1924,85 @@ s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw) * Read the AN advertisement and LP ability registers and resolve * local flow control settings accordingly */ - pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); - pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP); - if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) && - (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE)) { + if ((speed == IXGBE_LINK_SPEED_1GB_FULL) && + (hw->phy.media_type != ixgbe_media_type_backplane)) { + pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); + pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP); + if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) && + (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE)) { + /* + * Now we need to check if the user selected Rx ONLY + * of pause frames. In this case, we had to advertise + * FULL flow control because we could not advertise RX + * ONLY. Hence, we must now check to see if we need to + * turn OFF the TRANSMISSION of PAUSE frames. + */ + if (hw->fc.requested_mode == ixgbe_fc_full) { + hw->fc.current_mode = ixgbe_fc_full; + DEBUGOUT("Flow Control = FULL.\n"); + } else { + hw->fc.current_mode = ixgbe_fc_rx_pause; + DEBUGOUT("Flow Control=RX PAUSE frames only\n"); + } + } else if (!(pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) && + (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) && + (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) && + (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) { + hw->fc.current_mode = ixgbe_fc_tx_pause; + DEBUGOUT("Flow Control = TX PAUSE frames only.\n"); + } else if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) && + (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) && + !(pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) && + (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) { + hw->fc.current_mode = ixgbe_fc_rx_pause; + DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); + } else { + hw->fc.current_mode = ixgbe_fc_none; + DEBUGOUT("Flow Control = NONE.\n"); + } + } + + if (hw->phy.media_type == ixgbe_media_type_backplane) { /* - * Now we need to check if the user selected Rx ONLY - * of pause frames. In this case, we had to advertise - * FULL flow control because we could not advertise RX - * ONLY. Hence, we must now check to see if we need to - * turn OFF the TRANSMISSION of PAUSE frames. + * Read the 10g AN autoc and LP ability registers and resolve + * local flow control settings accordingly */ - if (hw->fc.requested_mode == ixgbe_fc_full) { - hw->fc.current_mode = ixgbe_fc_full; - DEBUGOUT("Flow Control = FULL.\n"); - } else { + autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); + anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1); + + if ((autoc_reg & IXGBE_AUTOC_SYM_PAUSE) && + (anlp1_reg & IXGBE_ANLP1_SYM_PAUSE)) { + /* + * Now we need to check if the user selected Rx ONLY + * of pause frames. In this case, we had to advertise + * FULL flow control because we could not advertise RX + * ONLY. Hence, we must now check to see if we need to + * turn OFF the TRANSMISSION of PAUSE frames. + */ + if (hw->fc.requested_mode == ixgbe_fc_full) { + hw->fc.current_mode = ixgbe_fc_full; + DEBUGOUT("Flow Control = FULL.\n"); + } else { + hw->fc.current_mode = ixgbe_fc_rx_pause; + DEBUGOUT("Flow Control=RX PAUSE frames only\n"); + } + } else if (!(autoc_reg & IXGBE_AUTOC_SYM_PAUSE) && + (autoc_reg & IXGBE_AUTOC_ASM_PAUSE) && + (anlp1_reg & IXGBE_ANLP1_SYM_PAUSE) && + (anlp1_reg & IXGBE_ANLP1_ASM_PAUSE)) { + hw->fc.current_mode = ixgbe_fc_tx_pause; + DEBUGOUT("Flow Control = TX PAUSE frames only.\n"); + } else if ((autoc_reg & IXGBE_AUTOC_SYM_PAUSE) && + (autoc_reg & IXGBE_AUTOC_ASM_PAUSE) && + !(anlp1_reg & IXGBE_ANLP1_SYM_PAUSE) && + (anlp1_reg & IXGBE_ANLP1_ASM_PAUSE)) { hw->fc.current_mode = ixgbe_fc_rx_pause; DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); + } else { + hw->fc.current_mode = ixgbe_fc_none; + DEBUGOUT("Flow Control = NONE.\n"); } - } else if (!(pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) && - (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) && - (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) && - (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) { - hw->fc.current_mode = ixgbe_fc_tx_pause; - DEBUGOUT("Flow Control = TX PAUSE frames only.\n"); - } else if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) && - (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) && - !(pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) && - (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) { - hw->fc.current_mode = ixgbe_fc_rx_pause; - DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); - } else { - hw->fc.current_mode = ixgbe_fc_none; - DEBUGOUT("Flow Control = NONE.\n"); } - /* Record that current_mode is the result of a successful autoneg */ hw->fc.fc_was_autonegged = TRUE; @@ -1850,6 +2021,8 @@ s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num) s32 ret_val = IXGBE_SUCCESS; u32 reg; + DEBUGFUNC("ixgbe_setup_fc"); + /* Validate the packetbuf configuration */ if (packetbuf_num < 0 || packetbuf_num > 7) { @@ -1933,7 +2106,7 @@ s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num) break; default: DEBUGOUT("Flow control param set incorrectly\n"); - ret_val = -IXGBE_ERR_CONFIG; + ret_val = IXGBE_ERR_CONFIG; goto out; break; } @@ -1941,9 +2114,6 @@ s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num) IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg); reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL); - /* Enable and restart autoneg to inform the link partner */ - reg |= IXGBE_PCS1GLCTL_AN_ENABLE | IXGBE_PCS1GLCTL_AN_RESTART; - /* Disable AN timeout */ if (hw->fc.strict_ieee) reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN; @@ -1951,6 +2121,65 @@ s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num) IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg); DEBUGOUT1("Set up FC; PCS1GLCTL = 0x%08X\n", reg); + /* + * Set up the 10G flow control advertisement registers so the HW + * can do fc autoneg once the cable is plugged in. If we end up + * using 1g instead, this is harmless. + */ + reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); + + /* + * The possible values of fc.requested_mode are: + * 0: Flow control is completely disabled + * 1: Rx flow control is enabled (we can receive pause frames, + * but not send pause frames). + * 2: Tx flow control is enabled (we can send pause frames but + * we do not support receiving pause frames). + * 3: Both Rx and Tx flow control (symmetric) are enabled. + * other: Invalid. + */ + switch (hw->fc.requested_mode) { + case ixgbe_fc_none: + /* Flow control completely disabled by software override. */ + reg &= ~(IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE); + break; + case ixgbe_fc_rx_pause: + /* + * Rx Flow control is enabled and Tx Flow control is + * disabled by software override. Since there really + * isn't a way to advertise that we are capable of RX + * Pause ONLY, we will advertise that we support both + * symmetric and asymmetric Rx PAUSE. Later, we will + * disable the adapter's ability to send PAUSE frames. + */ + reg |= (IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE); + break; + case ixgbe_fc_tx_pause: + /* + * Tx Flow control is enabled, and Rx Flow control is + * disabled by software override. + */ + reg |= (IXGBE_AUTOC_ASM_PAUSE); + reg &= ~(IXGBE_AUTOC_SYM_PAUSE); + break; + case ixgbe_fc_full: + /* Flow control (both Rx and Tx) is enabled by SW override. */ + reg |= (IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE); + break; + default: + DEBUGOUT("Flow control param set incorrectly\n"); + ret_val = IXGBE_ERR_CONFIG; + goto out; + break; + } + /* + * AUTOC restart handles negotiation of 1G and 10G. There is + * no need to set the PCS1GCTL register. + */ + reg |= IXGBE_AUTOC_AN_RESTART; + IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg); + DEBUGOUT1("Set up FC; IXGBE_AUTOC = 0x%08X\n", reg); + out: return ret_val; } @@ -1971,6 +2200,8 @@ s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw) u32 number_of_queues; s32 status = IXGBE_ERR_MASTER_REQUESTS_PENDING; + DEBUGFUNC("ixgbe_disable_pcie_master"); + /* Disable the receive unit by stopping each queue */ number_of_queues = hw->mac.max_rx_queues; for (i = 0; i < number_of_queues; i++) { @@ -2012,13 +2243,15 @@ s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask) u32 fwmask = mask << 5; s32 timeout = 200; + DEBUGFUNC("ixgbe_acquire_swfw_sync"); + while (timeout) { /* * SW EEPROM semaphore bit is used for access to all * SW_FW_SYNC/GSSR bits (not just EEPROM) */ if (ixgbe_get_eeprom_semaphore(hw)) - return -IXGBE_ERR_SWFW_SYNC; + return IXGBE_ERR_SWFW_SYNC; gssr = IXGBE_READ_REG(hw, IXGBE_GSSR); if (!(gssr & (fwmask | swmask))) @@ -2035,7 +2268,7 @@ s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask) if (!timeout) { DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n"); - return -IXGBE_ERR_SWFW_SYNC; + return IXGBE_ERR_SWFW_SYNC; } gssr |= swmask; @@ -2058,6 +2291,8 @@ void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask) u32 gssr; u32 swmask = mask; + DEBUGFUNC("ixgbe_release_swfw_sync"); + ixgbe_get_eeprom_semaphore(hw); gssr = IXGBE_READ_REG(hw, IXGBE_GSSR); @@ -2076,6 +2311,8 @@ void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask) **/ s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval) { + DEBUGFUNC("ixgbe_enable_rx_dma_generic"); + IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, regval); return IXGBE_SUCCESS; @@ -2093,6 +2330,8 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index) u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); + DEBUGFUNC("ixgbe_blink_led_start_generic"); + /* * Link must be up to auto-blink the LEDs; * Force it if link is down. @@ -2125,6 +2364,8 @@ s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index) u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); + DEBUGFUNC("ixgbe_blink_led_stop_generic"); + autoc_reg &= ~IXGBE_AUTOC_FLU; autoc_reg |= IXGBE_AUTOC_AN_RESTART; @@ -2139,3 +2380,582 @@ s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index) return IXGBE_SUCCESS; } +/** + * ixgbe_get_san_mac_addr_offset - Get SAN MAC address offset from the EEPROM + * @hw: pointer to hardware structure + * @san_mac_offset: SAN MAC address offset + * + * This function will read the EEPROM location for the SAN MAC address + * pointer, and returns the value at that location. This is used in both + * get and set mac_addr routines. + **/ +static s32 ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw, + u16 *san_mac_offset) +{ + DEBUGFUNC("ixgbe_get_san_mac_addr_offset"); + + /* + * First read the EEPROM pointer to see if the MAC addresses are + * available. + */ + hw->eeprom.ops.read(hw, IXGBE_SAN_MAC_ADDR_PTR, san_mac_offset); + + return IXGBE_SUCCESS; +} + +/** + * ixgbe_get_san_mac_addr_generic - SAN MAC address retrieval from the EEPROM + * @hw: pointer to hardware structure + * @san_mac_addr: SAN MAC address + * + * Reads the SAN MAC address from the EEPROM, if it's available. This is + * per-port, so set_lan_id() must be called before reading the addresses. + * set_lan_id() is called by identify_sfp(), but this cannot be relied + * upon for non-SFP connections, so we must call it here. + **/ +s32 ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr) +{ + u16 san_mac_data, san_mac_offset; + u8 i; + + DEBUGFUNC("ixgbe_get_san_mac_addr_generic"); + + /* + * First read the EEPROM pointer to see if the MAC addresses are + * available. If they're not, no point in calling set_lan_id() here. + */ + ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset); + + if ((san_mac_offset == 0) || (san_mac_offset == 0xFFFF)) { + /* + * No addresses available in this EEPROM. It's not an + * error though, so just wipe the local address and return. + */ + for (i = 0; i < 6; i++) + san_mac_addr[i] = 0xFF; + + goto san_mac_addr_out; + } + + /* make sure we know which port we need to program */ + hw->mac.ops.set_lan_id(hw); + /* apply the port offset to the address offset */ + (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) : + (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET); + for (i = 0; i < 3; i++) { + hw->eeprom.ops.read(hw, san_mac_offset, &san_mac_data); + san_mac_addr[i * 2] = (u8)(san_mac_data); + san_mac_addr[i * 2 + 1] = (u8)(san_mac_data >> 8); + san_mac_offset++; + } + +san_mac_addr_out: + return IXGBE_SUCCESS; +} + +/** + * ixgbe_set_san_mac_addr_generic - Write the SAN MAC address to the EEPROM + * @hw: pointer to hardware structure + * @san_mac_addr: SAN MAC address + * + * Write a SAN MAC address to the EEPROM. + **/ +s32 ixgbe_set_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr) +{ + s32 status = IXGBE_SUCCESS; + u16 san_mac_data, san_mac_offset; + u8 i; + + DEBUGFUNC("ixgbe_set_san_mac_addr_generic"); + + /* Look for SAN mac address pointer. If not defined, return */ + ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset); + + if ((san_mac_offset == 0) || (san_mac_offset == 0xFFFF)) { + status = IXGBE_ERR_NO_SAN_ADDR_PTR; + goto san_mac_addr_out; + } + + /* Make sure we know which port we need to write */ + hw->mac.ops.set_lan_id(hw); + /* Apply the port offset to the address offset */ + (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) : + (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET); + + for (i = 0; i < 3; i++) { + san_mac_data = (u16)((u16)(san_mac_addr[i * 2 + 1]) << 8); + san_mac_data |= (u16)(san_mac_addr[i * 2]); + hw->eeprom.ops.write(hw, san_mac_offset, san_mac_data); + san_mac_offset++; + } + +san_mac_addr_out: + return status; +} + +/** + * ixgbe_get_pcie_msix_count_generic - Gets MSI-X vector count + * @hw: pointer to hardware structure + * + * Read PCIe configuration space, and get the MSI-X vector count from + * the capabilities table. + **/ +u32 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw) +{ + u32 msix_count = 64; + + DEBUGFUNC("ixgbe_get_pcie_msix_count_generic"); + if (hw->mac.msix_vectors_from_pcie) { + msix_count = IXGBE_READ_PCIE_WORD(hw, + IXGBE_PCIE_MSIX_82599_CAPS); + msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK; + + /* MSI-X count is zero-based in HW, so increment to give + * proper value */ + msix_count++; + } + + return msix_count; +} + +/** + * ixgbe_insert_mac_addr_generic - Find a RAR for this mac address + * @hw: pointer to hardware structure + * @addr: Address to put into receive address register + * @vmdq: VMDq pool to assign + * + * Puts an ethernet address into a receive address register, or + * finds the rar that it is aleady in; adds to the pool list + **/ +s32 ixgbe_insert_mac_addr_generic(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) +{ + static const u32 NO_EMPTY_RAR_FOUND = 0xFFFFFFFF; + u32 first_empty_rar = NO_EMPTY_RAR_FOUND; + u32 rar; + u32 rar_low, rar_high; + u32 addr_low, addr_high; + + DEBUGFUNC("ixgbe_insert_mac_addr_generic"); + + /* swap bytes for HW little endian */ + addr_low = addr[0] | (addr[1] << 8) + | (addr[2] << 16) + | (addr[3] << 24); + addr_high = addr[4] | (addr[5] << 8); + + /* + * Either find the mac_id in rar or find the first empty space. + * rar_highwater points to just after the highest currently used + * rar in order to shorten the search. It grows when we add a new + * rar to the top. + */ + for (rar = 0; rar < hw->mac.rar_highwater; rar++) { + rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar)); + + if (((IXGBE_RAH_AV & rar_high) == 0) + && first_empty_rar == NO_EMPTY_RAR_FOUND) { + first_empty_rar = rar; + } else if ((rar_high & 0xFFFF) == addr_high) { + rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(rar)); + if (rar_low == addr_low) + break; /* found it already in the rars */ + } + } + + if (rar < hw->mac.rar_highwater) { + /* already there so just add to the pool bits */ + ixgbe_set_vmdq(hw, rar, vmdq); + } else if (first_empty_rar != NO_EMPTY_RAR_FOUND) { + /* stick it into first empty RAR slot we found */ + rar = first_empty_rar; + ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); + } else if (rar == hw->mac.rar_highwater) { + /* add it to the top of the list and inc the highwater mark */ + ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); + hw->mac.rar_highwater++; + } else if (rar >= hw->mac.num_rar_entries) { + return IXGBE_ERR_INVALID_MAC_ADDR; + } + + /* + * If we found rar[0], make sure the default pool bit (we use pool 0) + * remains cleared to be sure default pool packets will get delivered + */ + if (rar == 0) + ixgbe_clear_vmdq(hw, rar, 0); + + return rar; +} + +/** + * ixgbe_clear_vmdq_generic - Disassociate a VMDq pool index from a rx address + * @hw: pointer to hardware struct + * @rar: receive address register index to disassociate + * @vmdq: VMDq pool index to remove from the rar + **/ +s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq) +{ + u32 mpsar_lo, mpsar_hi; + u32 rar_entries = hw->mac.num_rar_entries; + + DEBUGFUNC("ixgbe_clear_vmdq_generic"); + + if (rar < rar_entries) { + mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); + mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); + + if (!mpsar_lo && !mpsar_hi) + goto done; + + if (vmdq == IXGBE_CLEAR_VMDQ_ALL) { + if (mpsar_lo) { + IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0); + mpsar_lo = 0; + } + if (mpsar_hi) { + IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0); + mpsar_hi = 0; + } + } else if (vmdq < 32) { + mpsar_lo &= ~(1 << vmdq); + IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar_lo); + } else { + mpsar_hi &= ~(1 << (vmdq - 32)); + IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar_hi); + } + + /* was that the last pool using this rar? */ + if (mpsar_lo == 0 && mpsar_hi == 0 && rar != 0) + hw->mac.ops.clear_rar(hw, rar); + } else { + DEBUGOUT1("RAR index %d is out of range.\n", rar); + } + +done: + return IXGBE_SUCCESS; +} + +/** + * ixgbe_set_vmdq_generic - Associate a VMDq pool index with a rx address + * @hw: pointer to hardware struct + * @rar: receive address register index to associate with a VMDq index + * @vmdq: VMDq pool index + **/ +s32 ixgbe_set_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq) +{ + u32 mpsar; + u32 rar_entries = hw->mac.num_rar_entries; + + DEBUGFUNC("ixgbe_set_vmdq_generic"); + + if (rar < rar_entries) { + if (vmdq < 32) { + mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); + mpsar |= 1 << vmdq; + IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar); + } else { + mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); + mpsar |= 1 << (vmdq - 32); + IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar); + } + } else { + DEBUGOUT1("RAR index %d is out of range.\n", rar); + } + return IXGBE_SUCCESS; +} + +/** + * ixgbe_init_uta_tables_generic - Initialize the Unicast Table Array + * @hw: pointer to hardware structure + **/ +s32 ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw) +{ + int i; + + DEBUGFUNC("ixgbe_init_uta_tables_generic"); + DEBUGOUT(" Clearing UTA\n"); + + for (i = 0; i < 128; i++) + IXGBE_WRITE_REG(hw, IXGBE_UTA(i), 0); + + return IXGBE_SUCCESS; +} + +/** + * ixgbe_find_vlvf_slot - find the vlanid or the first empty slot + * @hw: pointer to hardware structure + * @vlan: VLAN id to write to VLAN filter + * + * return the VLVF index where this VLAN id should be placed + * + **/ +s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan) +{ + u32 bits = 0; + u32 first_empty_slot = 0; + s32 regindex; + + /* + * Search for the vlan id in the VLVF entries. Save off the first empty + * slot found along the way + */ + for (regindex = 1; regindex < IXGBE_VLVF_ENTRIES; regindex++) { + bits = IXGBE_READ_REG(hw, IXGBE_VLVF(regindex)); + if (!bits && !(first_empty_slot)) + first_empty_slot = regindex; + else if ((bits & 0x0FFF) == vlan) + break; + } + + /* + * If regindex is less than IXGBE_VLVF_ENTRIES, then we found the vlan + * in the VLVF. Else use the first empty VLVF register for this + * vlan id. + */ + if (regindex >= IXGBE_VLVF_ENTRIES) { + if (first_empty_slot) + regindex = first_empty_slot; + else { + DEBUGOUT("No space in VLVF.\n"); + regindex = -1; + } + } + + return regindex; +} + +/** + * ixgbe_set_vfta_generic - Set VLAN filter table + * @hw: pointer to hardware structure + * @vlan: VLAN id to write to VLAN filter + * @vind: VMDq output index that maps queue to VLAN id in VFVFB + * @vlan_on: boolean flag to turn on/off VLAN in VFVF + * + * Turn on/off specified VLAN in the VLAN filter table. + **/ +s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, + bool vlan_on) +{ + s32 regindex; + u32 bitindex; + u32 bits; + u32 vt; + + DEBUGFUNC("ixgbe_set_vfta_generic"); + + if (vlan > 4095) + return IXGBE_ERR_PARAM; + + /* + * this is a 2 part operation - first the VFTA, then the + * VLVF and VLVFB if VT Mode is set + */ + + /* Part 1 + * The VFTA is a bitstring made up of 128 32-bit registers + * that enable the particular VLAN id, much like the MTA: + * bits[11-5]: which register + * bits[4-0]: which bit in the register + */ + regindex = (vlan >> 5) & 0x7F; + bitindex = vlan & 0x1F; + bits = IXGBE_READ_REG(hw, IXGBE_VFTA(regindex)); + if (vlan_on) + bits |= (1 << bitindex); + else + bits &= ~(1 << bitindex); + IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), bits); + + + /* Part 2 + * If VT Mode is set + * Either vlan_on + * make sure the vlan is in VLVF + * set the vind bit in the matching VLVFB + * Or !vlan_on + * clear the pool bit and possibly the vind + */ + vt = IXGBE_READ_REG(hw, IXGBE_VT_CTL); + if (vt & IXGBE_VT_CTL_VT_ENABLE) { + if (vlan == 0) { + regindex = 0; + } else { + regindex = ixgbe_find_vlvf_slot(hw, vlan); + if (regindex < 0) + goto out; + } + + if (vlan_on) { + /* set the pool bit */ + if (vind < 32) { + bits = IXGBE_READ_REG(hw, + IXGBE_VLVFB(regindex*2)); + bits |= (1 << vind); + IXGBE_WRITE_REG(hw, + IXGBE_VLVFB(regindex*2), + bits); + } else { + bits = IXGBE_READ_REG(hw, + IXGBE_VLVFB((regindex*2)+1)); + bits |= (1 << vind); + IXGBE_WRITE_REG(hw, + IXGBE_VLVFB((regindex*2)+1), + bits); + } + } else { + /* clear the pool bit */ + if (vind < 32) { + bits = IXGBE_READ_REG(hw, + IXGBE_VLVFB(regindex*2)); + bits &= ~(1 << vind); + IXGBE_WRITE_REG(hw, + IXGBE_VLVFB(regindex*2), + bits); + bits |= IXGBE_READ_REG(hw, + IXGBE_VLVFB((regindex*2)+1)); + } else { + bits = IXGBE_READ_REG(hw, + IXGBE_VLVFB((regindex*2)+1)); + bits &= ~(1 << vind); + IXGBE_WRITE_REG(hw, + IXGBE_VLVFB((regindex*2)+1), + bits); + bits |= IXGBE_READ_REG(hw, + IXGBE_VLVFB(regindex*2)); + } + } + + if (bits) + IXGBE_WRITE_REG(hw, IXGBE_VLVF(regindex), + (IXGBE_VLVF_VIEN | vlan)); + else + IXGBE_WRITE_REG(hw, IXGBE_VLVF(regindex), 0); + } +out: + return IXGBE_SUCCESS; +} + +/** + * ixgbe_clear_vfta_generic - Clear VLAN filter table + * @hw: pointer to hardware structure + * + * Clears the VLAN filer table, and the VMDq index associated with the filter + **/ +s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw) +{ + u32 offset; + + DEBUGFUNC("ixgbe_clear_vfta_generic"); + + for (offset = 0; offset < hw->mac.vft_size; offset++) + IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0); + + for (offset = 0; offset < IXGBE_VLVF_ENTRIES; offset++) { + IXGBE_WRITE_REG(hw, IXGBE_VLVF(offset), 0); + IXGBE_WRITE_REG(hw, IXGBE_VLVFB(offset*2), 0); + IXGBE_WRITE_REG(hw, IXGBE_VLVFB((offset*2)+1), 0); + } + + return IXGBE_SUCCESS; +} + +/** + * ixgbe_check_mac_link_generic - Determine link and speed status + * @hw: pointer to hardware structure + * @speed: pointer to link speed + * @link_up: TRUE when link is up + * @link_up_wait_to_complete: bool used to wait for link up or not + * + * Reads the links register to determine if link is up and the current speed + **/ +s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed, + bool *link_up, bool link_up_wait_to_complete) +{ + u32 links_reg; + u32 i; + + DEBUGFUNC("ixgbe_check_mac_link_generic"); + + links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); + if (link_up_wait_to_complete) { + for (i = 0; i < IXGBE_LINK_UP_TIME; i++) { + if (links_reg & IXGBE_LINKS_UP) { + *link_up = TRUE; + break; + } else { + *link_up = FALSE; + } + msec_delay(100); + links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); + } + } else { + if (links_reg & IXGBE_LINKS_UP) + *link_up = TRUE; + else + *link_up = FALSE; + } + + if ((links_reg & IXGBE_LINKS_SPEED_82599) == + IXGBE_LINKS_SPEED_10G_82599) + *speed = IXGBE_LINK_SPEED_10GB_FULL; + else if ((links_reg & IXGBE_LINKS_SPEED_82599) == + IXGBE_LINKS_SPEED_1G_82599) + *speed = IXGBE_LINK_SPEED_1GB_FULL; + else + *speed = IXGBE_LINK_SPEED_100_FULL; + + /* if link is down, zero out the current_mode */ + if (*link_up == FALSE) { + hw->fc.current_mode = ixgbe_fc_none; + hw->fc.fc_was_autonegged = FALSE; + } + + return IXGBE_SUCCESS; +} + +/** + * ixgbe_get_wwn_prefix_generic - Get alternative WWNN/WWPN prefix from + * the EEPROM + * @hw: pointer to hardware structure + * @wwnn_prefix: the alternative WWNN prefix + * @wwpn_prefix: the alternative WWPN prefix + * + * This function will read the EEPROM from the alternative SAN MAC address + * block to check the support for the alternative WWNN/WWPN prefix support. + **/ +s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix, + u16 *wwpn_prefix) +{ + u16 offset, caps; + u16 alt_san_mac_blk_offset; + + DEBUGFUNC("ixgbe_get_wwn_prefix_generic"); + + /* clear output first */ + *wwnn_prefix = 0xFFFF; + *wwpn_prefix = 0xFFFF; + + /* check if alternative SAN MAC is supported */ + hw->eeprom.ops.read(hw, IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR, + &alt_san_mac_blk_offset); + + if ((alt_san_mac_blk_offset == 0) || + (alt_san_mac_blk_offset == 0xFFFF)) + goto wwn_prefix_out; + + /* check capability in alternative san mac address block */ + offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET; + hw->eeprom.ops.read(hw, offset, &caps); + if (!(caps & IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN)) + goto wwn_prefix_out; + + /* get the corresponding prefix for WWNN/WWPN */ + offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET; + hw->eeprom.ops.read(hw, offset, wwnn_prefix); + + offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET; + hw->eeprom.ops.read(hw, offset, wwpn_prefix); + +wwn_prefix_out: + return IXGBE_SUCCESS; +} diff --git a/sys/dev/ixgbe/ixgbe_common.h b/sys/dev/ixgbe/ixgbe_common.h index 0c535751880b..f0707e21a2e4 100644 --- a/sys/dev/ixgbe/ixgbe_common.h +++ b/sys/dev/ixgbe/ixgbe_common.h @@ -42,6 +42,8 @@ IXGBE_WRITE_REG(hw, reg + 4, (u32) (value >> 32)); \ } while (0) +u32 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw); + s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw); s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw); s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw); @@ -57,12 +59,14 @@ s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index); s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw); s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data); -s32 ixgbe_read_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 *data); +s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data); s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, u16 *data); +u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw); s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, u16 *checksum_val); s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw); +s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg); s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, u32 enable_addr); @@ -73,7 +77,6 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, ixgbe_mc_addr_itr func); s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list, u32 addr_count, ixgbe_mc_addr_itr func); -void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq); s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw); s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw); s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval); @@ -87,9 +90,25 @@ s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask); void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask); s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw); -s32 ixgbe_read_analog_reg8_generic(struct ixgbe_hw *hw, u32 reg, u8 *val); -s32 ixgbe_write_analog_reg8_generic(struct ixgbe_hw *hw, u32 reg, u8 val); s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index); s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index); +s32 ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr); +s32 ixgbe_set_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr); + +s32 ixgbe_set_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq); +s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq); +s32 ixgbe_insert_mac_addr_generic(struct ixgbe_hw *hw, u8 *addr, u32 vmdq); +s32 ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw); +s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, + u32 vind, bool vlan_on); +s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw); + +s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, + ixgbe_link_speed *speed, + bool *link_up, bool link_up_wait_to_complete); + +s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix, + u16 *wwpn_prefix); + #endif /* IXGBE_COMMON */ diff --git a/sys/dev/ixgbe/ixgbe_osdep.h b/sys/dev/ixgbe/ixgbe_osdep.h index e1bbce08602d..151e63ff1f6a 100644 --- a/sys/dev/ixgbe/ixgbe_osdep.h +++ b/sys/dev/ixgbe/ixgbe_osdep.h @@ -110,6 +110,16 @@ typedef boolean_t bool; #endif #endif +#if defined(__i386__) || defined(__amd64__) +static __inline +void prefetch(void *x) +{ + __asm volatile("prefetcht0 %0" :: "m" (*(unsigned long *)x)); +} +#else +#define prefetch(x) +#endif + struct ixgbe_osdep { bus_space_tag_t mem_bus_space_tag; diff --git a/sys/dev/ixgbe/ixgbe_phy.c b/sys/dev/ixgbe/ixgbe_phy.c index daa37d910004..9bab98d29522 100644 --- a/sys/dev/ixgbe/ixgbe_phy.c +++ b/sys/dev/ixgbe/ixgbe_phy.c @@ -59,6 +59,8 @@ s32 ixgbe_init_phy_ops_generic(struct ixgbe_hw *hw) { struct ixgbe_phy_info *phy = &hw->phy; + DEBUGFUNC("ixgbe_init_phy_ops_generic"); + /* PHY */ phy->ops.identify = &ixgbe_identify_phy_generic; phy->ops.reset = &ixgbe_reset_phy_generic; @@ -67,7 +69,7 @@ s32 ixgbe_init_phy_ops_generic(struct ixgbe_hw *hw) phy->ops.setup_link = &ixgbe_setup_phy_link_generic; phy->ops.setup_link_speed = &ixgbe_setup_phy_link_speed_generic; phy->ops.check_link = NULL; - phy->ops.get_firmware_version = NULL; + phy->ops.get_firmware_version = ixgbe_get_phy_firmware_version_generic; phy->ops.read_i2c_byte = &ixgbe_read_i2c_byte_generic; phy->ops.write_i2c_byte = &ixgbe_write_i2c_byte_generic; phy->ops.read_i2c_eeprom = &ixgbe_read_i2c_eeprom_generic; @@ -91,6 +93,8 @@ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw) u32 phy_addr; u16 ext_ability = 0; + DEBUGFUNC("ixgbe_identify_phy_generic"); + if (hw->phy.type == ixgbe_phy_unknown) { for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) { if (ixgbe_validate_phy_addr(hw, phy_addr)) { @@ -138,6 +142,8 @@ bool ixgbe_validate_phy_addr(struct ixgbe_hw *hw, u32 phy_addr) u16 phy_id = 0; bool valid = FALSE; + DEBUGFUNC("ixgbe_validate_phy_addr"); + hw->phy.addr = phy_addr; hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_HIGH, IXGBE_MDIO_PMA_PMD_DEV_TYPE, &phy_id); @@ -159,6 +165,8 @@ s32 ixgbe_get_phy_id(struct ixgbe_hw *hw) u16 phy_id_high = 0; u16 phy_id_low = 0; + DEBUGFUNC("ixgbe_get_phy_id"); + status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_HIGH, IXGBE_MDIO_PMA_PMD_DEV_TYPE, &phy_id_high); @@ -183,6 +191,8 @@ enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id) { enum ixgbe_phy_type phy_type; + DEBUGFUNC("ixgbe_get_phy_type_from_id"); + switch (phy_id) { case TN1010_PHY_ID: phy_type = ixgbe_phy_tn; @@ -215,6 +225,8 @@ s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw) u16 ctrl = 0; s32 status = IXGBE_SUCCESS; + DEBUGFUNC("ixgbe_reset_phy_generic"); + if (hw->phy.type == ixgbe_phy_unknown) status = ixgbe_identify_phy_generic(hw); @@ -262,6 +274,8 @@ s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, s32 status = IXGBE_SUCCESS; u16 gssr; + DEBUGFUNC("ixgbe_read_phy_reg_generic"); + if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1) gssr = IXGBE_GSSR_PHY1_SM; else @@ -359,6 +373,8 @@ s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, s32 status = IXGBE_SUCCESS; u16 gssr; + DEBUGFUNC("ixgbe_write_phy_reg_generic"); + if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1) gssr = IXGBE_GSSR_PHY1_SM; else @@ -437,10 +453,10 @@ s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, } /** - * ixgbe_setup_phy_link_generic - Set and restart autoneg - * @hw: pointer to hardware structure + * ixgbe_setup_phy_link_generic - Set and restart autoneg + * @hw: pointer to hardware structure * - * Restart autonegotiation and PHY and waits for completion. + * Restart autonegotiation and PHY and waits for completion. **/ s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw) { @@ -448,23 +464,59 @@ s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw) u32 time_out; u32 max_time_out = 10; u16 autoneg_reg = IXGBE_MII_AUTONEG_REG; + bool autoneg = FALSE; + ixgbe_link_speed speed; - /* - * Set advertisement settings in PHY based on autoneg_advertised - * settings. If autoneg_advertised = 0, then advertise default values - * tnx devices cannot be "forced" to a autoneg 10G and fail. But can - * for a 1G. - */ - hw->phy.ops.read_reg(hw, IXGBE_MII_SPEED_SELECTION_REG, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); + DEBUGFUNC("ixgbe_setup_phy_link_generic"); - if (hw->phy.autoneg_advertised == IXGBE_LINK_SPEED_1GB_FULL) - autoneg_reg &= 0xEFFF; /* 0 in bit 12 is 1G operation */ - else - autoneg_reg |= 0x1000; /* 1 in bit 12 is 10G/1G operation */ + ixgbe_get_copper_link_capabilities_generic(hw, &speed, &autoneg); - hw->phy.ops.write_reg(hw, IXGBE_MII_SPEED_SELECTION_REG, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg); + if (speed & IXGBE_LINK_SPEED_10GB_FULL) { + /* Set or unset auto-negotiation 10G advertisement */ + hw->phy.ops.read_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + &autoneg_reg); + + autoneg_reg &= ~IXGBE_MII_10GBASE_T_ADVERTISE; + if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) + autoneg_reg |= IXGBE_MII_10GBASE_T_ADVERTISE; + + hw->phy.ops.write_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + autoneg_reg); + } + + if (speed & IXGBE_LINK_SPEED_1GB_FULL) { + /* Set or unset auto-negotiation 1G advertisement */ + hw->phy.ops.read_reg(hw, + IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + &autoneg_reg); + + autoneg_reg &= ~IXGBE_MII_1GBASE_T_ADVERTISE; + if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) + autoneg_reg |= IXGBE_MII_1GBASE_T_ADVERTISE; + + hw->phy.ops.write_reg(hw, + IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + autoneg_reg); + } + + if (speed & IXGBE_LINK_SPEED_100_FULL) { + /* Set or unset auto-negotiation 100M advertisement */ + hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_ADVERTISE_REG, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + &autoneg_reg); + + autoneg_reg &= ~IXGBE_MII_100BASE_T_ADVERTISE; + if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL) + autoneg_reg |= IXGBE_MII_100BASE_T_ADVERTISE; + + hw->phy.ops.write_reg(hw, IXGBE_MII_AUTONEG_ADVERTISE_REG, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + autoneg_reg); + } /* Restart PHY autonegotiation and wait for completion */ hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL, @@ -489,8 +541,10 @@ s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw) } } - if (time_out == max_time_out) + if (time_out == max_time_out) { status = IXGBE_ERR_LINK_SETUP; + DEBUGOUT("ixgbe_setup_phy_link_generic: time out"); + } return status; } @@ -509,6 +563,8 @@ s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw, UNREFERENCED_PARAMETER(autoneg); UNREFERENCED_PARAMETER(autoneg_wait_to_complete); + DEBUGFUNC("ixgbe_setup_phy_link_speed_generic"); + /* * Clear autoneg_advertised and set new values based on input link * speed. @@ -545,6 +601,8 @@ s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw, s32 status = IXGBE_ERR_LINK_SETUP; u16 speed_ability; + DEBUGFUNC("ixgbe_get_copper_link_capabilities_generic"); + *speed = 0; *autoneg = TRUE; @@ -581,6 +639,8 @@ s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, ixgbe_link_speed *speed, u16 phy_speed = 0; u16 phy_data = 0; + DEBUGFUNC("ixgbe_check_phy_link_tnx"); + /* Initialize speed and link to default case */ *link_up = FALSE; *speed = IXGBE_LINK_SPEED_10GB_FULL; @@ -613,6 +673,102 @@ s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, ixgbe_link_speed *speed, } /** + * ixgbe_setup_phy_link_tnx - Set and restart autoneg + * @hw: pointer to hardware structure + * + * Restart autonegotiation and PHY and waits for completion. + **/ +s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw) +{ + s32 status = IXGBE_SUCCESS; + u32 time_out; + u32 max_time_out = 10; + u16 autoneg_reg = IXGBE_MII_AUTONEG_REG; + bool autoneg = FALSE; + ixgbe_link_speed speed; + + DEBUGFUNC("ixgbe_setup_phy_link_tnx"); + + ixgbe_get_copper_link_capabilities_generic(hw, &speed, &autoneg); + + if (speed & IXGBE_LINK_SPEED_10GB_FULL) { + /* Set or unset auto-negotiation 10G advertisement */ + hw->phy.ops.read_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + &autoneg_reg); + + autoneg_reg &= ~IXGBE_MII_10GBASE_T_ADVERTISE; + if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) + autoneg_reg |= IXGBE_MII_10GBASE_T_ADVERTISE; + + hw->phy.ops.write_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + autoneg_reg); + } + + if (speed & IXGBE_LINK_SPEED_1GB_FULL) { + /* Set or unset auto-negotiation 1G advertisement */ + hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_XNP_TX_REG, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + &autoneg_reg); + + autoneg_reg &= ~IXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX; + if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) + autoneg_reg |= IXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX; + + hw->phy.ops.write_reg(hw, IXGBE_MII_AUTONEG_XNP_TX_REG, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + autoneg_reg); + } + + if (speed & IXGBE_LINK_SPEED_100_FULL) { + /* Set or unset auto-negotiation 100M advertisement */ + hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_ADVERTISE_REG, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + &autoneg_reg); + + autoneg_reg &= ~IXGBE_MII_100BASE_T_ADVERTISE; + if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL) + autoneg_reg |= IXGBE_MII_100BASE_T_ADVERTISE; + + hw->phy.ops.write_reg(hw, IXGBE_MII_AUTONEG_ADVERTISE_REG, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + autoneg_reg); + } + + /* Restart PHY autonegotiation and wait for completion */ + hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); + + autoneg_reg |= IXGBE_MII_RESTART; + + hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg); + + /* Wait for autonegotiation to finish */ + for (time_out = 0; time_out < max_time_out; time_out++) { + usec_delay(10); + /* Restart PHY autonegotiation and wait for completion */ + status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + &autoneg_reg); + + autoneg_reg &= IXGBE_MII_AUTONEG_COMPLETE; + if (autoneg_reg == IXGBE_MII_AUTONEG_COMPLETE) { + break; + } + } + + if (time_out == max_time_out) { + status = IXGBE_ERR_LINK_SETUP; + DEBUGOUT("ixgbe_setup_phy_link_tnx: time out"); + } + + return status; +} + + +/** * ixgbe_get_phy_firmware_version_tnx - Gets the PHY Firmware Version * @hw: pointer to hardware structure * @firmware_version: pointer to the PHY Firmware Version @@ -622,6 +778,8 @@ s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw, { s32 status = IXGBE_SUCCESS; + DEBUGFUNC("ixgbe_get_phy_firmware_version_tnx"); + status = hw->phy.ops.read_reg(hw, TNX_FW_REV, IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, firmware_version); @@ -631,15 +789,17 @@ s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw, /** - * ixgbe_get_phy_firmware_version_aq - Gets the PHY Firmware Version + * ixgbe_get_phy_firmware_version_generic - Gets the PHY Firmware Version * @hw: pointer to hardware structure * @firmware_version: pointer to the PHY Firmware Version **/ -s32 ixgbe_get_phy_firmware_version_aq(struct ixgbe_hw *hw, +s32 ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw, u16 *firmware_version) { s32 status = IXGBE_SUCCESS; + DEBUGFUNC("ixgbe_get_phy_firmware_version_generic"); + status = hw->phy.ops.read_reg(hw, AQ_FW_REV, IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, firmware_version); @@ -660,6 +820,8 @@ s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw) s32 ret_val = IXGBE_SUCCESS; u32 i; + DEBUGFUNC("ixgbe_reset_phy_nl"); + hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL, IXGBE_MDIO_PHY_XS_DEV_TYPE, &phy_data); @@ -762,6 +924,8 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) u8 cable_tech = 0; u16 enforce_sfp = 0; + DEBUGFUNC("ixgbe_identify_sfp_module_generic"); + if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_fiber) { hw->phy.sfp_type = ixgbe_sfp_type_not_present; status = IXGBE_ERR_SFP_NOT_PRESENT; @@ -850,6 +1014,7 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) ((comp_codes_1g & IXGBE_SFF_1GBASELX_CAPABLE) && (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE))) hw->phy.multispeed_fiber = TRUE; + /* Determine PHY vendor */ if (hw->phy.type != ixgbe_phy_nl) { hw->phy.id = identifier; @@ -944,6 +1109,8 @@ s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw, { u16 sfp_id; + DEBUGFUNC("ixgbe_get_sfp_init_sequence_offsets"); + if (hw->phy.sfp_type == ixgbe_sfp_type_unknown) return IXGBE_ERR_SFP_NOT_SUPPORTED; @@ -1370,6 +1537,8 @@ static s32 ixgbe_clock_in_i2c_bit(struct ixgbe_hw *hw, bool *data) s32 status; u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL); + DEBUGFUNC("ixgbe_clock_in_i2c_bit"); + status = ixgbe_raise_i2c_clk(hw, &i2cctl); /* Minimum high period of clock is 4us */ @@ -1398,6 +1567,8 @@ static s32 ixgbe_clock_out_i2c_bit(struct ixgbe_hw *hw, bool data) s32 status; u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL); + DEBUGFUNC("ixgbe_clock_out_i2c_bit"); + status = ixgbe_set_i2c_data(hw, &i2cctl, data); if (status == IXGBE_SUCCESS) { status = ixgbe_raise_i2c_clk(hw, &i2cctl); @@ -1429,6 +1600,8 @@ static s32 ixgbe_raise_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl) { s32 status = IXGBE_SUCCESS; + DEBUGFUNC("ixgbe_raise_i2c_clk"); + *i2cctl |= IXGBE_I2C_CLK_OUT; IXGBE_WRITE_REG(hw, IXGBE_I2CCTL, *i2cctl); @@ -1449,6 +1622,8 @@ static s32 ixgbe_raise_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl) static void ixgbe_lower_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl) { + DEBUGFUNC("ixgbe_lower_i2c_clk"); + *i2cctl &= ~IXGBE_I2C_CLK_OUT; IXGBE_WRITE_REG(hw, IXGBE_I2CCTL, *i2cctl); @@ -1469,6 +1644,8 @@ static s32 ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data) { s32 status = IXGBE_SUCCESS; + DEBUGFUNC("ixgbe_set_i2c_data"); + if (data) *i2cctl |= IXGBE_I2C_DATA_OUT; else @@ -1500,6 +1677,8 @@ static bool ixgbe_get_i2c_data(u32 *i2cctl) { bool data; + DEBUGFUNC("ixgbe_get_i2c_data"); + if (*i2cctl & IXGBE_I2C_DATA_IN) data = 1; else diff --git a/sys/dev/ixgbe/ixgbe_phy.h b/sys/dev/ixgbe/ixgbe_phy.h index bfe73de25b12..39f3bc83f0a4 100644 --- a/sys/dev/ixgbe/ixgbe_phy.h +++ b/sys/dev/ixgbe/ixgbe_phy.h @@ -108,9 +108,10 @@ s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw, s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up); +s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw); s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw, u16 *firmware_version); -s32 ixgbe_get_phy_firmware_version_aq(struct ixgbe_hw *hw, +s32 ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw, u16 *firmware_version); s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw); diff --git a/sys/dev/ixgbe/ixgbe_type.h b/sys/dev/ixgbe/ixgbe_type.h index 50345f4c2c1a..0b1011977094 100644 --- a/sys/dev/ixgbe/ixgbe_type.h +++ b/sys/dev/ixgbe/ixgbe_type.h @@ -47,6 +47,7 @@ #define IXGBE_DEV_ID_82598AF_DUAL_PORT 0x10C6 #define IXGBE_DEV_ID_82598AF_SINGLE_PORT 0x10C7 #define IXGBE_DEV_ID_82598AT 0x10C8 +#define IXGBE_DEV_ID_82598AT2 0x150B #define IXGBE_DEV_ID_82598EB_SFP_LOM 0x10DB #define IXGBE_DEV_ID_82598EB_CX4 0x10DD #define IXGBE_DEV_ID_82598_CX4_DUAL_PORT 0x10EC @@ -54,6 +55,8 @@ #define IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM 0x10E1 #define IXGBE_DEV_ID_82598EB_XF_LR 0x10F4 #define IXGBE_DEV_ID_82599_KX4 0x10F7 +#define IXGBE_DEV_ID_82599_KX4_MEZZ 0x1514 +#define IXGBE_DEV_ID_82599_COMBO_BACKPLANE 0x10F8 #define IXGBE_DEV_ID_82599_CX4 0x10F9 #define IXGBE_DEV_ID_82599_SFP 0x10FB #define IXGBE_DEV_ID_82599_XAUI_LOM 0x10FC @@ -74,6 +77,7 @@ /* NVM Registers */ #define IXGBE_EEC 0x10010 #define IXGBE_EERD 0x10014 +#define IXGBE_EEWR 0x10018 #define IXGBE_FLA 0x1001C #define IXGBE_EEMNGCTL 0x10110 #define IXGBE_EEMNGDATA 0x10114 @@ -352,7 +356,7 @@ #define IXGBE_WUFC_FLX5 0x00200000 /* Flexible Filter 5 Enable */ #define IXGBE_WUFC_FLX_FILTERS 0x000F0000 /* Mask for 4 flex filters */ #define IXGBE_WUFC_EXT_FLX_FILTERS 0x00300000 /* Mask for Ext. flex filters */ -#define IXGBE_WUFC_ALL_FILTERS 0x003F00FF /* Mask for all 6 wakeup filters*/ +#define IXGBE_WUFC_ALL_FILTERS 0x003F00FF /* Mask for all wakeup filters */ #define IXGBE_WUFC_FLX_OFFSET 16 /* Offset to the Flexible Filters bits */ /* Wake Up Status */ @@ -703,6 +707,7 @@ #define IXGBE_MREVID 0x11064 #define IXGBE_DCA_ID 0x11070 #define IXGBE_DCA_CTRL 0x11074 +#define IXGBE_SWFW_SYNC IXGBE_GSSR /* PCI-E registers 82599-Specific */ #define IXGBE_GCR_EXT 0x11050 @@ -725,6 +730,12 @@ #define IXGBE_ECC_STATUS_82599 0x110E0 #define IXGBE_BAR_CTRL_82599 0x110F4 +/* PCI Express Control */ +#define IXGBE_GCR_CMPL_TMOUT_MASK 0x0000F000 +#define IXGBE_GCR_CMPL_TMOUT_10ms 0x00001000 +#define IXGBE_GCR_CMPL_TMOUT_RESEND 0x00010000 +#define IXGBE_GCR_CAP_VER2 0x00040000 + /* Time Sync Registers */ #define IXGBE_TSYNCRXCTL 0x05188 /* Rx Time Sync Control register - RW */ #define IXGBE_TSYNCTXCTL 0x08C00 /* Tx Time Sync Control register - RW */ @@ -848,12 +859,16 @@ #define IXGBE_MPVC 0x04318 #define IXGBE_SGMIIC 0x04314 +/* Copper Pond 2 link timeout */ +#define IXGBE_VALIDATE_LINK_READY_TIMEOUT 50 + /* Omer CORECTL */ #define IXGBE_CORECTL 0x014F00 /* BARCTRL */ -#define IXGBE_BARCTRL 0x110F4 -#define IXGBE_BARCTRL_FLSIZE 0x0700 -#define IXGBE_BARCTRL_CSRSIZE 0x2000 +#define IXGBE_BARCTRL 0x110F4 +#define IXGBE_BARCTRL_FLSIZE 0x0700 +#define IXGBE_BARCTRL_FLSIZE_SHIFT 8 +#define IXGBE_BARCTRL_CSRSIZE 0x2000 /* RSCCTL Bit Masks */ #define IXGBE_RSCCTL_RSCEN 0x01 @@ -1013,10 +1028,18 @@ /* MII clause 22/28 definitions */ #define IXGBE_MDIO_PHY_LOW_POWER_MODE 0x0800 -#define IXGBE_MII_SPEED_SELECTION_REG 0x10 -#define IXGBE_MII_RESTART 0x200 -#define IXGBE_MII_AUTONEG_COMPLETE 0x20 -#define IXGBE_MII_AUTONEG_REG 0x0 +#define IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG 0x20 /* 10G Control Reg */ +#define IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG 0xC400 /* 1G Provisioning 1 */ +#define IXGBE_MII_AUTONEG_XNP_TX_REG 0x17 /* 1G XNP Transmit */ +#define IXGBE_MII_AUTONEG_ADVERTISE_REG 0x10 /* 100M Advertisement */ +#define IXGBE_MII_10GBASE_T_ADVERTISE 0x1000 /* full duplex, bit:12*/ +#define IXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX 0x4000 /* full duplex, bit:14*/ +#define IXGBE_MII_1GBASE_T_ADVERTISE 0x8000 /* full duplex, bit:15*/ +#define IXGBE_MII_100BASE_T_ADVERTISE 0x0100 /* full duplex, bit:8 */ +#define IXGBE_MII_RESTART 0x200 +#define IXGBE_MII_AUTONEG_COMPLETE 0x20 +#define IXGBE_MII_AUTONEG_LINK_UP 0x04 +#define IXGBE_MII_AUTONEG_REG 0x0 #define IXGBE_PHY_REVISION_MASK 0xFFFFFFF0 #define IXGBE_MAX_PHY_ADDR 32 @@ -1408,6 +1431,8 @@ #define IXGBE_AUTOC_KX4_SUPP 0x80000000 #define IXGBE_AUTOC_KX_SUPP 0x40000000 #define IXGBE_AUTOC_PAUSE 0x30000000 +#define IXGBE_AUTOC_ASM_PAUSE 0x20000000 +#define IXGBE_AUTOC_SYM_PAUSE 0x10000000 #define IXGBE_AUTOC_RF 0x08000000 #define IXGBE_AUTOC_PD_TMR 0x06000000 #define IXGBE_AUTOC_AN_RX_LOOSE 0x01000000 @@ -1476,6 +1501,8 @@ #define IXGBE_LINK_UP_TIME 90 /* 9.0 Seconds */ #define IXGBE_AUTO_NEG_TIME 45 /* 4.5 Seconds */ +#define IXGBE_LINKS2_AN_SUPPORTED 0x00000040 + /* PCS1GLSTA Bit Masks */ #define IXGBE_PCS1GLSTA_LINK_OK 1 #define IXGBE_PCS1GLSTA_SYNK_OK 0x10 @@ -1496,12 +1523,18 @@ #define IXGBE_PCS1GLCTL_AN_ENABLE 0x10000 #define IXGBE_PCS1GLCTL_AN_RESTART 0x20000 +/* ANLP1 Bit Masks */ +#define IXGBE_ANLP1_PAUSE 0x0C00 +#define IXGBE_ANLP1_SYM_PAUSE 0x0400 +#define IXGBE_ANLP1_ASM_PAUSE 0x0800 + /* SW Semaphore Register bitmasks */ #define IXGBE_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */ #define IXGBE_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */ #define IXGBE_SWSM_WMNG 0x00000004 /* Wake MNG Clock */ +#define IXGBE_SWFW_REGSMP 0x80000000 /* Register Semaphore bit 31 */ -/* GSSR definitions */ +/* SW_FW_SYNC/GSSR definitions */ #define IXGBE_GSSR_EEP_SM 0x0001 #define IXGBE_GSSR_PHY0_SM 0x0002 #define IXGBE_GSSR_PHY1_SM 0x0004 @@ -1521,20 +1554,24 @@ #define IXGBE_EEC_GNT 0x00000080 /* EEPROM Access Grant */ #define IXGBE_EEC_PRES 0x00000100 /* EEPROM Present */ #define IXGBE_EEC_ARD 0x00000200 /* EEPROM Auto Read Done */ +#define IXGBE_EEC_FLUP 0x00800000 /* Flash update command */ +#define IXGBE_EEC_FLUDONE 0x04000000 /* Flash update done */ /* EEPROM Addressing bits based on type (0-small, 1-large) */ #define IXGBE_EEC_ADDR_SIZE 0x00000400 #define IXGBE_EEC_SIZE 0x00007800 /* EEPROM Size */ -#define IXGBE_EEC_SIZE_SHIFT 11 -#define IXGBE_EEPROM_WORD_SIZE_SHIFT 6 -#define IXGBE_EEPROM_OPCODE_BITS 8 +#define IXGBE_EEC_SIZE_SHIFT 11 +#define IXGBE_EEPROM_WORD_SIZE_BASE_SHIFT 6 +#define IXGBE_EEPROM_OPCODE_BITS 8 /* Checksum and EEPROM pointers */ #define IXGBE_EEPROM_CHECKSUM 0x3F #define IXGBE_EEPROM_SUM 0xBABA #define IXGBE_PCIE_ANALOG_PTR 0x03 #define IXGBE_ATLAS0_CONFIG_PTR 0x04 +#define IXGBE_PHY_PTR 0x04 #define IXGBE_ATLAS1_CONFIG_PTR 0x05 +#define IXGBE_OPTION_ROM_PTR 0x05 #define IXGBE_PCIE_GENERAL_PTR 0x06 #define IXGBE_PCIE_CONFIG0_PTR 0x07 #define IXGBE_PCIE_CONFIG1_PTR 0x08 @@ -1577,10 +1614,12 @@ #define IXGBE_EEPROM_ERASE256_OPCODE_SPI 0xDB /* EEPROM ERASE 256B */ /* EEPROM Read Register */ -#define IXGBE_EEPROM_READ_REG_DATA 16 /* data offset in EEPROM read reg */ -#define IXGBE_EEPROM_READ_REG_DONE 2 /* Offset to READ done bit */ -#define IXGBE_EEPROM_READ_REG_START 1 /* First bit to start operation */ -#define IXGBE_EEPROM_READ_ADDR_SHIFT 2 /* Shift to the address bits */ +#define IXGBE_EEPROM_RW_REG_DATA 16 /* data offset in EEPROM read reg */ +#define IXGBE_EEPROM_RW_REG_DONE 2 /* Offset to READ done bit */ +#define IXGBE_EEPROM_RW_REG_START 1 /* First bit to start operation */ +#define IXGBE_EEPROM_RW_ADDR_SHIFT 2 /* Shift to the address bits */ +#define IXGBE_NVM_POLL_WRITE 1 /* Flag for polling for write complete */ +#define IXGBE_NVM_POLL_READ 0 /* Flag for polling for read complete */ #define IXGBE_ETH_LENGTH_OF_ADDRESS 6 @@ -1588,10 +1627,12 @@ #define IXGBE_EEPROM_GRANT_ATTEMPTS 1000 /* EEPROM # attempts to gain grant */ #endif -#ifndef IXGBE_EERD_ATTEMPTS -/* Number of 5 microseconds we wait for EERD read to complete */ -#define IXGBE_EERD_ATTEMPTS 100000 -#endif +/* Number of 5 microseconds we wait for EERD read and + * EERW write to complete */ +#define IXGBE_EERD_EEWR_ATTEMPTS 100000 + +/* # attempts we wait for flush update to complete */ +#define IXGBE_FLUDONE_ATTEMPTS 20000 #define IXGBE_PCIE_CTRL2 0x5 /* PCIe Control 2 Offset */ #define IXGBE_PCIE_CTRL2_DUMMY_ENABLE 0x8 /* Dummy Function Enable */ @@ -1604,9 +1645,18 @@ #define IXGBE_DEVICE_CAPS_FCOE_OFFLOADS 0x2 #define IXGBE_FW_PASSTHROUGH_PATCH_CONFIG_PTR 0x4 #define IXGBE_FW_PATCH_VERSION_4 0x7 +#define IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR 0x27 /* Alt. SAN MAC block */ +#define IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET 0x0 /* Alt. SAN MAC capability */ +#define IXGBE_ALT_SAN_MAC_ADDR_PORT0_OFFSET 0x1 /* Alt. SAN MAC 0 offset */ +#define IXGBE_ALT_SAN_MAC_ADDR_PORT1_OFFSET 0x4 /* Alt. SAN MAC 1 offset */ +#define IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET 0x7 /* Alt. WWNN prefix offset */ +#define IXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET 0x8 /* Alt. WWPN prefix offset */ +#define IXGBE_ALT_SAN_MAC_ADDR_CAPS_SANMAC 0x0 /* Alt. SAN MAC exists */ +#define IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN 0x1 /* Alt. WWN base exists */ /* PCI Bus Info */ #define IXGBE_PCI_LINK_STATUS 0xB2 +#define IXGBE_PCI_DEVICE_CONTROL2 0xC8 #define IXGBE_PCI_LINK_WIDTH 0x3F0 #define IXGBE_PCI_LINK_WIDTH_1 0x10 #define IXGBE_PCI_LINK_WIDTH_2 0x20 @@ -1617,6 +1667,7 @@ #define IXGBE_PCI_LINK_SPEED_5000 0x2 #define IXGBE_PCI_HEADER_TYPE_REGISTER 0x0E #define IXGBE_PCI_HEADER_TYPE_MULTIFUNC 0x80 +#define IXGBE_PCI_DEVICE_CONTROL2_16ms 0x0005 /* Number of 100 microseconds we wait for PCI Express master disable */ #define IXGBE_PCI_MASTER_DISABLE_TIMEOUT 800 @@ -2210,6 +2261,7 @@ struct ixgbe_atr_input { enum ixgbe_eeprom_type { ixgbe_eeprom_uninitialized = 0, ixgbe_eeprom_spi, + ixgbe_flash, ixgbe_eeprom_none /* No NVM support */ }; @@ -2269,6 +2321,7 @@ enum ixgbe_media_type { ixgbe_media_type_fiber, ixgbe_media_type_copper, ixgbe_media_type_backplane, + ixgbe_media_type_cx4, ixgbe_media_type_virtual }; @@ -2281,6 +2334,14 @@ enum ixgbe_fc_mode { ixgbe_fc_default }; +/* Smart Speed Settings */ +#define IXGBE_SMARTSPEED_MAX_RETRIES 3 +enum ixgbe_smart_speed { + ixgbe_smart_speed_auto = 0, + ixgbe_smart_speed_on, + ixgbe_smart_speed_off +}; + /* PCI bus types */ enum ixgbe_bus_type { ixgbe_bus_type_unknown = 0, @@ -2434,6 +2495,7 @@ struct ixgbe_eeprom_operations { s32 (*write)(struct ixgbe_hw *, u16, u16); s32 (*validate_checksum)(struct ixgbe_hw *, u16 *); s32 (*update_checksum)(struct ixgbe_hw *); + u16 (*calc_checksum)(struct ixgbe_hw *); }; struct ixgbe_mac_operations { @@ -2447,6 +2509,7 @@ struct ixgbe_mac_operations { s32 (*get_san_mac_addr)(struct ixgbe_hw *, u8 *); s32 (*set_san_mac_addr)(struct ixgbe_hw *, u8 *); s32 (*get_device_caps)(struct ixgbe_hw *, u16 *); + s32 (*get_wwn_prefix)(struct ixgbe_hw *, u16 *, u16 *); s32 (*stop_adapter)(struct ixgbe_hw *); s32 (*get_bus_info)(struct ixgbe_hw *); void (*set_lan_id)(struct ixgbe_hw *); @@ -2458,9 +2521,7 @@ struct ixgbe_mac_operations { void (*release_swfw_sync)(struct ixgbe_hw *, u16); /* Link */ - s32 (*setup_link)(struct ixgbe_hw *); - s32 (*setup_link_speed)(struct ixgbe_hw *, ixgbe_link_speed, bool, - bool); + s32 (*setup_link)(struct ixgbe_hw *, ixgbe_link_speed, bool, bool); s32 (*check_link)(struct ixgbe_hw *, ixgbe_link_speed *, bool *, bool); s32 (*get_link_capabilities)(struct ixgbe_hw *, ixgbe_link_speed *, bool *); @@ -2525,6 +2586,10 @@ struct ixgbe_mac_info { u8 addr[IXGBE_ETH_LENGTH_OF_ADDRESS]; u8 perm_addr[IXGBE_ETH_LENGTH_OF_ADDRESS]; u8 san_addr[IXGBE_ETH_LENGTH_OF_ADDRESS]; + /* prefix for World Wide Node Name (WWNN) */ + u16 wwnn_prefix; + /* prefix for World Wide Port Name (WWPN) */ + u16 wwpn_prefix; s32 mc_filter_type; u32 mcft_size; u32 vft_size; @@ -2537,8 +2602,6 @@ struct ixgbe_mac_info { u32 orig_autoc; u32 orig_autoc2; bool orig_link_settings_stored; - bool autoneg; - bool autoneg_succeeded; bool autotry_restart; }; @@ -2553,7 +2616,8 @@ struct ixgbe_phy_info { enum ixgbe_media_type media_type; bool reset_disable; ixgbe_autoneg_advertised autoneg_advertised; - bool autoneg_wait_to_complete; + enum ixgbe_smart_speed smart_speed; + bool smart_speed_active; bool multispeed_fiber; }; |
