Index: sys/dev/ixgbe/if_ix.c =================================================================== --- sys/dev/ixgbe/if_ix.c +++ sys/dev/ixgbe/if_ix.c @@ -1135,10 +1135,12 @@ * ixgbe_check_wol_support * * Checks whether the adapter's ports are capable of - * Wake On LAN by reading the adapter's NVM. + * Wake On LAN by reading the adapter's NVM (X540 and newer) + * or by device ID. * - * Sets each port's hw->wol_enabled value depending - * on the value read here. + * Sets each port's hw->wol_enabled value and default + * adapter->wufc (Wake-Up Filter Control) value + * depending on the capability determined here. ************************************************************************/ static void ixgbe_check_wol_support(struct adapter *adapter) @@ -1146,18 +1148,77 @@ struct ixgbe_hw *hw = &adapter->hw; u16 dev_caps = 0; - /* Find out WoL support for port */ adapter->wol_support = hw->wol_enabled = 0; - ixgbe_get_device_caps(hw, &dev_caps); - if ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0_1) || - ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0) && - hw->bus.func == 0)) - adapter->wol_support = hw->wol_enabled = 1; - /* Save initial wake up filter configuration */ - adapter->wufc = IXGBE_READ_REG(hw, IXGBE_WUFC); + /* WoL is not supported on 82598 */ + if (hw->mac.type == ixgbe_mac_82598EB) + return; + + /* For X540 and newer, WoL capability is reported in EEPROM */ + if (hw->mac.type >= ixgbe_mac_X540) { + ixgbe_get_device_caps(hw, &dev_caps); + if ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0_1) || + ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0) && + hw->bus.func == 0)) + goto wol_capable; + return; + } + + /* For 82599, WoL capability is determined based on device IDs */ + switch (hw->device_id) { + case IXGBE_DEV_ID_82599_SFP: + switch (hw->subsystem_device_id) { + /* These subdevices support WoL only on first port */ + case IXGBE_SUBDEV_ID_82599_560FLR: + case IXGBE_SUBDEV_ID_82599_LOM_SNAP6: + case IXGBE_SUBDEV_ID_82599_SFP_WOL0: + case IXGBE_SUBDEV_ID_82599_SFP_2OCP: + if (hw->bus.func != 0) + return; + /* else: fall through */ + + /* These subdevices support WoL on all ports */ + case IXGBE_SUBDEV_ID_82599_SP_560FLR: + case IXGBE_SUBDEV_ID_82599_SFP: + case IXGBE_SUBDEV_ID_82599_RNDC: + case IXGBE_SUBDEV_ID_82599_ECNA_DP: + case IXGBE_SUBDEV_ID_82599_SFP_1OCP: + case IXGBE_SUBDEV_ID_82599_SFP_LOM_OEM1: + case IXGBE_SUBDEV_ID_82599_SFP_LOM_OEM2: + goto wol_capable; + } + break; + + case IXGBE_DEV_ID_82599EN_SFP: + /* These subdevices support WoL on all ports */ + switch (hw->subsystem_device_id) { + case IXGBE_SUBDEV_ID_82599EN_SFP_OCP1: + goto wol_capable; + } + break; + + case IXGBE_DEV_ID_82599_COMBO_BACKPLANE: + /* All except this subdevice support WoL */ + if (hw->subsystem_device_id != + IXGBE_SUBDEV_ID_82599_KX4_KR_MEZZ) + goto wol_capable; + break; + + case IXGBE_DEV_ID_82599_KX4: + /* This device supports WoL */ + goto wol_capable; + break; + + default: + break; + } return; + +wol_capable: + adapter->wol_support = hw->wol_enabled = 1; + adapter->wufc = (IXGBE_WUFC_LNKC | IXGBE_WUFC_MAG | IXGBE_WUFC_EX | + IXGBE_WUFC_MC | IXGBE_WUFC_BC); } /* ixgbe_check_wol_support */ /************************************************************************ @@ -2557,14 +2618,14 @@ "I", "DMA Coalesce"); /* for WoL-capable devices */ - if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) { + if (adapter->wol_support) { SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "wol_enable", CTLTYPE_INT | CTLFLAG_RW, adapter, 0, ixgbe_sysctl_wol_enable, "I", "Enable/Disable Wake on LAN"); SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "wufc", CTLTYPE_U32 | CTLFLAG_RW, adapter, 0, ixgbe_sysctl_wufc, - "I", "Enable/Disable Wake Up Filters"); + "I", IXGBE_SYSCTL_DESC_WUFC); } /* for X552/X557-AT devices */ @@ -2679,14 +2740,7 @@ if (!hw->wol_enabled) ixgbe_set_phy_power(hw, FALSE); - - /* Limit power management flow to X550EM baseT */ - if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T && - hw->phy.ops.enter_lplu) { - /* Turn off support for APM wakeup. (Using ACPI instead) */ - IXGBE_WRITE_REG(hw, IXGBE_GRC, - IXGBE_READ_REG(hw, IXGBE_GRC) & ~(u32)2); - + else { /* * Clear Wake Up Status register to prevent any previous wakeup * events from waking us up immediately after we suspend. @@ -2702,6 +2756,14 @@ /* Enable wakeups and power management in Wakeup Control */ IXGBE_WRITE_REG(hw, IXGBE_WUC, IXGBE_WUC_WKEN | IXGBE_WUC_PME_EN); + } + + /* Limit power management flow to X550EM baseT */ + if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T && + hw->phy.ops.enter_lplu) { + /* Turn off support for APM wakeup. (Using ACPI instead) */ + IXGBE_WRITE_REG(hw, IXGBE_GRC_BY_MAC(hw), + IXGBE_READ_REG(hw, IXGBE_GRC_BY_MAC(hw)) & ~(u32)2); /* X550EM baseT adapters need a special LPLU flow */ hw->phy.reset_disable = TRUE; @@ -3526,7 +3588,8 @@ /* Update DMA coalescing config */ ixgbe_config_dmac(adapter); /* should actually be negotiated value */ - iflib_link_state_change(ctx, LINK_STATE_UP, IF_Gbps(10)); + iflib_link_state_change(ctx, LINK_STATE_UP, + ixgbe_link_speed_to_baudrate(adapter->link_speed)); if (adapter->feat_en & IXGBE_FEATURE_SRIOV) ixgbe_ping_all_vfs(adapter); @@ -4256,11 +4319,11 @@ if (new_wufc == adapter->wufc) return (0); - if (new_wufc & 0xffffff00) + /* ARP/IPv4 Request Packet Wake Up (0x20) is not supported */ + if (new_wufc & 0xffffff20) return (EINVAL); new_wufc &= 0xff; - new_wufc |= (0xffffff & adapter->wufc); adapter->wufc = new_wufc; return (0); Index: sys/dev/ixgbe/if_ixv.c =================================================================== --- sys/dev/ixgbe/if_ixv.c +++ sys/dev/ixgbe/if_ixv.c @@ -932,7 +932,7 @@ "Full Duplex"); adapter->link_active = TRUE; iflib_link_state_change(ctx, LINK_STATE_UP, - IF_Gbps(10)); + ixgbe_link_speed_to_baudrate(adapter->link_speed)); } } else { /* Link down */ if (adapter->link_active == TRUE) { Index: sys/dev/ixgbe/ixgbe.h =================================================================== --- sys/dev/ixgbe/ixgbe.h +++ sys/dev/ixgbe/ixgbe.h @@ -545,6 +545,18 @@ "\t2 - tx pause\n" \ "\t3 - tx and rx pause" +#define IXGBE_SYSCTL_DESC_WUFC \ + "\tEnable/Disable Wake Up Filters\n" \ + "\tControl types of packets that the adapter will\n" \ + "\twake up on receipt by using these flags:\n" \ + "\t0x1 - Link Status Change\n" \ + "\t0x2 - Magic Packet\n" \ + "\t0x4 - Direct Exact\n" \ + "\t0x8 - Directed Multicast\n" \ + "\t0x10 - Broadcast\n" \ + "\t0x40 - Direct IPv4 Packet\n" \ + "\t0x80 - Direct IPv6 Packet" + /* Workaround to make 8.0 buildable */ #if __FreeBSD_version >= 800000 && __FreeBSD_version < 800504 static __inline int @@ -574,6 +586,8 @@ return (status); } +uint64_t ixgbe_link_speed_to_baudrate(ixgbe_link_speed speed); + /* Shared Prototypes */ int ixgbe_allocate_queues(struct adapter *); Index: sys/dev/ixgbe/ixgbe_osdep.c =================================================================== --- sys/dev/ixgbe/ixgbe_osdep.c +++ sys/dev/ixgbe/ixgbe_osdep.c @@ -76,3 +76,37 @@ ((struct adapter *)hw->back)->osdep.mem_bus_space_handle, reg + (offset << 2), val); } + +uint64_t +ixgbe_link_speed_to_baudrate(ixgbe_link_speed speed) +{ + uint64_t baudrate; + + switch (speed) { + case IXGBE_LINK_SPEED_10GB_FULL: + baudrate = IF_Gbps(10); + break; + case IXGBE_LINK_SPEED_5GB_FULL: + baudrate = IF_Gbps(5); + break; + case IXGBE_LINK_SPEED_2_5GB_FULL: + baudrate = IF_Mbps(2500); + break; + case IXGBE_LINK_SPEED_1GB_FULL: + baudrate = IF_Gbps(1); + break; + case IXGBE_LINK_SPEED_100_FULL: + baudrate = IF_Mbps(100); + break; + case IXGBE_LINK_SPEED_10_FULL: + baudrate = IF_Mbps(10); + break; + case IXGBE_LINK_SPEED_UNKNOWN: + default: + baudrate = 0; + break; + } + + return baudrate; +} +