diff --git a/sys/dev/ixl/i40e_common.c b/sys/dev/ixl/i40e_common.c index 826b777aba09..4f6fbab5d9d1 100644 --- a/sys/dev/ixl/i40e_common.c +++ b/sys/dev/ixl/i40e_common.c @@ -2160,6 +2160,37 @@ enum i40e_status_code i40e_aq_set_vsi_broadcast(struct i40e_hw *hw, return status; } +/** + * i40e_aq_set_vsi_vlan_promisc - control the VLAN promiscuous setting + * @hw: pointer to the hw struct + * @seid: vsi number + * @enable: set MAC L2 layer unicast promiscuous enable/disable for a given VLAN + * @cmd_details: pointer to command details structure or NULL + **/ +enum i40e_status_code i40e_aq_set_vsi_vlan_promisc(struct i40e_hw *hw, + u16 seid, bool enable, + struct i40e_asq_cmd_details *cmd_details) +{ + struct i40e_aq_desc desc; + struct i40e_aqc_set_vsi_promiscuous_modes *cmd = + (struct i40e_aqc_set_vsi_promiscuous_modes *)&desc.params.raw; + enum i40e_status_code status; + u16 flags = 0; + + i40e_fill_default_direct_cmd_desc(&desc, + i40e_aqc_opc_set_vsi_promiscuous_modes); + if (enable) + flags |= I40E_AQC_SET_VSI_PROMISC_VLAN; + + cmd->promiscuous_flags = CPU_TO_LE16(flags); + cmd->valid_flags = CPU_TO_LE16(I40E_AQC_SET_VSI_PROMISC_VLAN); + cmd->seid = CPU_TO_LE16(seid); + + status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); + + return status; +} + /** * i40e_get_vsi_params - get VSI configuration info * @hw: pointer to the hw struct @@ -2262,6 +2293,34 @@ enum i40e_status_code i40e_aq_get_switch_config(struct i40e_hw *hw, return status; } +/** + * i40e_aq_set_switch_config + * @hw: pointer to the hardware structure + * @flags: bit flag values to set + * @valid_flags: which bit flags to set + * @cmd_details: pointer to command details structure or NULL + * + * Set switch configuration bits + **/ +enum i40e_status_code i40e_aq_set_switch_config(struct i40e_hw *hw, + u16 flags, u16 valid_flags, + struct i40e_asq_cmd_details *cmd_details) +{ + struct i40e_aq_desc desc; + struct i40e_aqc_set_switch_config *scfg = + (struct i40e_aqc_set_switch_config *)&desc.params.raw; + enum i40e_status_code status; + + i40e_fill_default_direct_cmd_desc(&desc, + i40e_aqc_opc_set_switch_config); + scfg->flags = CPU_TO_LE16(flags); + scfg->valid_flags = CPU_TO_LE16(valid_flags); + + status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); + + return status; +} + /** * i40e_aq_get_firmware_version * @hw: pointer to the hw struct @@ -2437,8 +2496,8 @@ i40e_link_speed_exit: * @downlink_seid: the VSI SEID * @enabled_tc: bitmap of TCs to be enabled * @default_port: TRUE for default port VSI, FALSE for control port - * @enable_l2_filtering: TRUE to add L2 filter table rules to regular forwarding rules for cloud support * @veb_seid: pointer to where to put the resulting VEB SEID + * @enable_stats: TRUE to turn on VEB stats * @cmd_details: pointer to command details structure or NULL * * This asks the FW to add a VEB between the uplink and downlink @@ -2446,8 +2505,8 @@ i40e_link_speed_exit: **/ enum i40e_status_code i40e_aq_add_veb(struct i40e_hw *hw, u16 uplink_seid, u16 downlink_seid, u8 enabled_tc, - bool default_port, bool enable_l2_filtering, - u16 *veb_seid, + bool default_port, u16 *veb_seid, + bool enable_stats, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; @@ -2474,8 +2533,9 @@ enum i40e_status_code i40e_aq_add_veb(struct i40e_hw *hw, u16 uplink_seid, else veb_flags |= I40E_AQC_ADD_VEB_PORT_TYPE_DATA; - if (enable_l2_filtering) - veb_flags |= I40E_AQC_ADD_VEB_ENABLE_L2_FILTER; + /* reverse logic here: set the bitflag to disable the stats */ + if (!enable_stats) + veb_flags |= I40E_AQC_ADD_VEB_ENABLE_DISABLE_STATS; cmd->veb_flags = CPU_TO_LE16(veb_flags); @@ -2580,7 +2640,8 @@ enum i40e_status_code i40e_aq_add_macvlan(struct i40e_hw *hw, u16 seid, for (i = 0; i < count; i++) if (I40E_IS_MULTICAST(mv_list[i].mac_addr)) - mv_list[i].flags |= I40E_AQC_MACVLAN_ADD_USE_SHARED_MAC; + mv_list[i].flags |= + CPU_TO_LE16(I40E_AQC_MACVLAN_ADD_USE_SHARED_MAC); desc.flags |= CPU_TO_LE16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD)); if (buf_size > I40E_AQ_LARGE_BUF) @@ -2634,6 +2695,137 @@ enum i40e_status_code i40e_aq_remove_macvlan(struct i40e_hw *hw, u16 seid, return status; } +/** + * i40e_mirrorrule_op - Internal helper function to add/delete mirror rule + * @hw: pointer to the hw struct + * @opcode: AQ opcode for add or delete mirror rule + * @sw_seid: Switch SEID (to which rule refers) + * @rule_type: Rule Type (ingress/egress/VLAN) + * @id: Destination VSI SEID or Rule ID + * @count: length of the list + * @mr_list: list of mirrored VSI SEIDs or VLAN IDs + * @cmd_details: pointer to command details structure or NULL + * @rule_id: Rule ID returned from FW + * @rule_used: Number of rules used in internal switch + * @rule_free: Number of rules free in internal switch + * + * Add/Delete a mirror rule to a specific switch. Mirror rules are supported for + * VEBs/VEPA elements only + **/ +static enum i40e_status_code i40e_mirrorrule_op(struct i40e_hw *hw, + u16 opcode, u16 sw_seid, u16 rule_type, u16 id, + u16 count, __le16 *mr_list, + struct i40e_asq_cmd_details *cmd_details, + u16 *rule_id, u16 *rules_used, u16 *rules_free) +{ + struct i40e_aq_desc desc; + struct i40e_aqc_add_delete_mirror_rule *cmd = + (struct i40e_aqc_add_delete_mirror_rule *)&desc.params.raw; + struct i40e_aqc_add_delete_mirror_rule_completion *resp = + (struct i40e_aqc_add_delete_mirror_rule_completion *)&desc.params.raw; + enum i40e_status_code status; + u16 buf_size; + + buf_size = count * sizeof(*mr_list); + + /* prep the rest of the request */ + i40e_fill_default_direct_cmd_desc(&desc, opcode); + cmd->seid = CPU_TO_LE16(sw_seid); + cmd->rule_type = CPU_TO_LE16(rule_type & + I40E_AQC_MIRROR_RULE_TYPE_MASK); + cmd->num_entries = CPU_TO_LE16(count); + /* Dest VSI for add, rule_id for delete */ + cmd->destination = CPU_TO_LE16(id); + if (mr_list) { + desc.flags |= CPU_TO_LE16((u16)(I40E_AQ_FLAG_BUF | + I40E_AQ_FLAG_RD)); + if (buf_size > I40E_AQ_LARGE_BUF) + desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB); + } + + status = i40e_asq_send_command(hw, &desc, mr_list, buf_size, + cmd_details); + if (status == I40E_SUCCESS || + hw->aq.asq_last_status == I40E_AQ_RC_ENOSPC) { + if (rule_id) + *rule_id = LE16_TO_CPU(resp->rule_id); + if (rules_used) + *rules_used = LE16_TO_CPU(resp->mirror_rules_used); + if (rules_free) + *rules_free = LE16_TO_CPU(resp->mirror_rules_free); + } + return status; +} + +/** + * i40e_aq_add_mirrorrule - add a mirror rule + * @hw: pointer to the hw struct + * @sw_seid: Switch SEID (to which rule refers) + * @rule_type: Rule Type (ingress/egress/VLAN) + * @dest_vsi: SEID of VSI to which packets will be mirrored + * @count: length of the list + * @mr_list: list of mirrored VSI SEIDs or VLAN IDs + * @cmd_details: pointer to command details structure or NULL + * @rule_id: Rule ID returned from FW + * @rule_used: Number of rules used in internal switch + * @rule_free: Number of rules free in internal switch + * + * Add mirror rule. Mirror rules are supported for VEBs or VEPA elements only + **/ +enum i40e_status_code i40e_aq_add_mirrorrule(struct i40e_hw *hw, u16 sw_seid, + u16 rule_type, u16 dest_vsi, u16 count, __le16 *mr_list, + struct i40e_asq_cmd_details *cmd_details, + u16 *rule_id, u16 *rules_used, u16 *rules_free) +{ + if (!(rule_type == I40E_AQC_MIRROR_RULE_TYPE_ALL_INGRESS || + rule_type == I40E_AQC_MIRROR_RULE_TYPE_ALL_EGRESS)) { + if (count == 0 || !mr_list) + return I40E_ERR_PARAM; + } + + return i40e_mirrorrule_op(hw, i40e_aqc_opc_add_mirror_rule, sw_seid, + rule_type, dest_vsi, count, mr_list, + cmd_details, rule_id, rules_used, rules_free); +} + +/** + * i40e_aq_delete_mirrorrule - delete a mirror rule + * @hw: pointer to the hw struct + * @sw_seid: Switch SEID (to which rule refers) + * @rule_type: Rule Type (ingress/egress/VLAN) + * @count: length of the list + * @rule_id: Rule ID that is returned in the receive desc as part of + * add_mirrorrule. + * @mr_list: list of mirrored VLAN IDs to be removed + * @cmd_details: pointer to command details structure or NULL + * @rule_used: Number of rules used in internal switch + * @rule_free: Number of rules free in internal switch + * + * Delete a mirror rule. Mirror rules are supported for VEBs/VEPA elements only + **/ +enum i40e_status_code i40e_aq_delete_mirrorrule(struct i40e_hw *hw, u16 sw_seid, + u16 rule_type, u16 rule_id, u16 count, __le16 *mr_list, + struct i40e_asq_cmd_details *cmd_details, + u16 *rules_used, u16 *rules_free) +{ + /* Rule ID has to be valid except rule_type: INGRESS VLAN mirroring */ + if (rule_type != I40E_AQC_MIRROR_RULE_TYPE_VLAN) { + if (!rule_id) + return I40E_ERR_PARAM; + } else { + /* count and mr_list shall be valid for rule_type INGRESS VLAN + * mirroring. For other rule_type, count and rule_type should + * not matter. + */ + if (count == 0 || !mr_list) + return I40E_ERR_PARAM; + } + + return i40e_mirrorrule_op(hw, i40e_aqc_opc_delete_mirror_rule, sw_seid, + rule_type, rule_id, count, mr_list, + cmd_details, NULL, rules_used, rules_free); +} + /** * i40e_aq_add_vlan - Add VLAN ids to the HW filtering * @hw: pointer to the hw struct diff --git a/sys/dev/ixl/i40e_nvm.c b/sys/dev/ixl/i40e_nvm.c index 5d3f6a35ea7a..4556d1734f81 100644 --- a/sys/dev/ixl/i40e_nvm.c +++ b/sys/dev/ixl/i40e_nvm.c @@ -54,7 +54,7 @@ enum i40e_status_code i40e_read_nvm_aq(struct i40e_hw *hw, u8 module_pointer, * once per NVM initialization, e.g. inside the i40e_init_shared_code(). * Please notice that the NVM term is used here (& in all methods covered * in this file) as an equivalent of the FLASH part mapped into the SR. - * We are accessing FLASH always thru the Shadow RAM. + * We are accessing FLASH always through the Shadow RAM. **/ enum i40e_status_code i40e_init_nvm(struct i40e_hw *hw) { @@ -373,7 +373,7 @@ enum i40e_status_code i40e_read_nvm_buffer_srctl(struct i40e_hw *hw, u16 offset, DEBUGFUNC("i40e_read_nvm_buffer_srctl"); - /* Loop thru the selected region */ + /* Loop through the selected region */ for (word = 0; word < *words; word++) { index = offset + word; ret_code = i40e_read_nvm_word_srctl(hw, index, &data[word]); diff --git a/sys/dev/ixl/i40e_prototype.h b/sys/dev/ixl/i40e_prototype.h index e7e6aa22fbb7..0f2857392c0e 100644 --- a/sys/dev/ixl/i40e_prototype.h +++ b/sys/dev/ixl/i40e_prototype.h @@ -153,6 +153,9 @@ enum i40e_status_code i40e_aq_set_vsi_mc_promisc_on_vlan(struct i40e_hw *hw, enum i40e_status_code i40e_aq_set_vsi_uc_promisc_on_vlan(struct i40e_hw *hw, u16 seid, bool enable, u16 vid, struct i40e_asq_cmd_details *cmd_details); +enum i40e_status_code i40e_aq_set_vsi_vlan_promisc(struct i40e_hw *hw, + u16 seid, bool enable, + struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_get_vsi_params(struct i40e_hw *hw, struct i40e_vsi_context *vsi_ctx, struct i40e_asq_cmd_details *cmd_details); @@ -161,8 +164,8 @@ enum i40e_status_code i40e_aq_update_vsi_params(struct i40e_hw *hw, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_add_veb(struct i40e_hw *hw, u16 uplink_seid, u16 downlink_seid, u8 enabled_tc, - bool default_port, bool enable_l2_filtering, - u16 *pveb_seid, + bool default_port, u16 *pveb_seid, + bool enable_stats, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_get_veb_parameters(struct i40e_hw *hw, u16 veb_seid, u16 *switch_id, bool *floating, @@ -175,6 +178,15 @@ enum i40e_status_code i40e_aq_add_macvlan(struct i40e_hw *hw, u16 vsi_id, enum i40e_status_code i40e_aq_remove_macvlan(struct i40e_hw *hw, u16 vsi_id, struct i40e_aqc_remove_macvlan_element_data *mv_list, u16 count, struct i40e_asq_cmd_details *cmd_details); +enum i40e_status_code i40e_aq_add_mirrorrule(struct i40e_hw *hw, u16 sw_seid, + u16 rule_type, u16 dest_vsi, u16 count, __le16 *mr_list, + struct i40e_asq_cmd_details *cmd_details, + u16 *rule_id, u16 *rules_used, u16 *rules_free); +enum i40e_status_code i40e_aq_delete_mirrorrule(struct i40e_hw *hw, u16 sw_seid, + u16 rule_type, u16 rule_id, u16 count, __le16 *mr_list, + struct i40e_asq_cmd_details *cmd_details, + u16 *rules_used, u16 *rules_free); + enum i40e_status_code i40e_aq_add_vlan(struct i40e_hw *hw, u16 vsi_id, struct i40e_aqc_add_remove_vlan_element_data *v_list, u8 count, struct i40e_asq_cmd_details *cmd_details); @@ -188,6 +200,9 @@ enum i40e_status_code i40e_aq_get_switch_config(struct i40e_hw *hw, struct i40e_aqc_get_switch_config_resp *buf, u16 buf_size, u16 *start_seid, struct i40e_asq_cmd_details *cmd_details); +enum i40e_status_code i40e_aq_set_switch_config(struct i40e_hw *hw, + u16 flags, u16 valid_flags, + struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_request_resource(struct i40e_hw *hw, enum i40e_aq_resources_ids resource, enum i40e_aq_resource_access_type access, diff --git a/sys/dev/ixl/if_ixl.c b/sys/dev/ixl/if_ixl.c index 44de2ad5792b..5382ea9afeca 100644 --- a/sys/dev/ixl/if_ixl.c +++ b/sys/dev/ixl/if_ixl.c @@ -48,7 +48,7 @@ /********************************************************************* * Driver version *********************************************************************/ -char ixl_driver_version[] = "1.4.13-k"; +char ixl_driver_version[] = "1.4.17-k"; /********************************************************************* * PCI Device ID Table @@ -157,15 +157,15 @@ static void ixl_free_mac_filters(struct ixl_vsi *vsi); /* Sysctls*/ static void ixl_add_device_sysctls(struct ixl_pf *); -static int ixl_debug_info(SYSCTL_HANDLER_ARGS); -static void ixl_print_debug_info(struct ixl_pf *); - static int ixl_set_flowcntl(SYSCTL_HANDLER_ARGS); static int ixl_set_advertise(SYSCTL_HANDLER_ARGS); static int ixl_current_speed(SYSCTL_HANDLER_ARGS); static int ixl_sysctl_show_fw(SYSCTL_HANDLER_ARGS); #ifdef IXL_DEBUG_SYSCTL +static int ixl_debug_info(SYSCTL_HANDLER_ARGS); +static void ixl_print_debug_info(struct ixl_pf *); + static int ixl_sysctl_link_status(SYSCTL_HANDLER_ARGS); static int ixl_sysctl_phy_abilities(SYSCTL_HANDLER_ARGS); static int ixl_sysctl_sw_filter_list(SYSCTL_HANDLER_ARGS); @@ -359,8 +359,9 @@ ixl_probe(device_t dev) char device_name[256]; static bool lock_init = FALSE; +#if 0 INIT_DEBUGOUT("ixl_probe: begin"); - +#endif pci_vendor_id = pci_get_vendor(dev); if (pci_vendor_id != I40E_INTEL_VENDOR_ID) return (ENXIO); @@ -412,7 +413,7 @@ ixl_attach(device_t dev) { struct ixl_pf *pf; struct i40e_hw *hw; - struct ixl_vsi *vsi; + struct ixl_vsi *vsi; u16 bus; int error = 0; #ifdef PCI_IOV @@ -496,7 +497,8 @@ ixl_attach(device_t dev) error = EIO; goto err_out; } - device_printf(dev, "%s\n", ixl_fw_version_str(hw)); + ixl_print_nvm_version(pf); + if (error == I40E_ERR_FIRMWARE_API_VERSION) { device_printf(dev, "The driver for the device stopped " "because the NVM image is newer than expected.\n" @@ -631,10 +633,12 @@ ixl_attach(device_t dev) IOV_SCHEMA_HASDEFAULT, FALSE); iov_error = pci_iov_attach(dev, pf_schema, vf_schema); - if (iov_error != 0) + if (iov_error != 0) { device_printf(dev, "Failed to initialize SR-IOV (error=%d)\n", iov_error); + } else + device_printf(dev, "SR-IOV ready\n"); } #endif @@ -1085,7 +1089,6 @@ ixl_init_locked(struct ixl_pf *pf) device_printf(dev, "LLA address" "change failed!!\n"); return; - } else { } } @@ -1227,7 +1230,7 @@ ixl_reset(struct ixl_pf *pf) error = i40e_configure_lan_hmc(hw, I40E_HMC_MODEL_DIRECT_ONLY); if (error) { - device_printf(dev, "init: LAN HMC config failed; status code %d\n", error); + device_printf(dev, "init: LAN HMC config failed; status code %d\n", error); error = EIO; goto err_out; } @@ -1253,7 +1256,7 @@ ixl_reset(struct ixl_pf *pf) // XXX: (Rebuild VSIs?) - // Firmware delay workaround + /* Firmware delay workaround */ if (((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver < 33)) || (hw->aq.fw_maj_ver < 4)) { i40e_msec_delay(75); @@ -1265,20 +1268,6 @@ ixl_reset(struct ixl_pf *pf) } } - // [add_filter_to_drop_tx_flow_control_frames] - // - TODO: Implement - - // i40e_send_version - // - TODO: Properly implement - struct i40e_driver_version dv; - - dv.major_version = 1; - dv.minor_version = 1; - dv.build_version = 1; - dv.subbuild_version = 0; - // put in a driver version string that is less than 0x80 bytes long - bzero(&dv.driver_string, sizeof(dv.driver_string)); - i40e_aq_send_driver_version(hw, &dv, NULL); err_out: return (error); @@ -1598,6 +1587,9 @@ ixl_media_status(struct ifnet * ifp, struct ifmediareq * ifmr) case I40E_PHY_TYPE_1000BASE_LX: ifmr->ifm_active |= IFM_1000_LX; break; + case I40E_PHY_TYPE_1000BASE_T_OPTICAL: + ifmr->ifm_active |= IFM_OTHER; + break; /* 10 G */ case I40E_PHY_TYPE_10GBASE_SFPP_CU: ifmr->ifm_active |= IFM_10G_TWINAX; @@ -1611,6 +1603,11 @@ ixl_media_status(struct ifnet * ifp, struct ifmediareq * ifmr) case I40E_PHY_TYPE_10GBASE_T: ifmr->ifm_active |= IFM_10G_T; break; + case I40E_PHY_TYPE_XAUI: + case I40E_PHY_TYPE_XFI: + case I40E_PHY_TYPE_10GBASE_AOC: + ifmr->ifm_active |= IFM_OTHER; + break; /* 40 G */ case I40E_PHY_TYPE_40GBASE_CR4: case I40E_PHY_TYPE_40GBASE_CR4_CU: @@ -1622,10 +1619,16 @@ ixl_media_status(struct ifnet * ifp, struct ifmediareq * ifmr) case I40E_PHY_TYPE_40GBASE_LR4: ifmr->ifm_active |= IFM_40G_LR4; break; + case I40E_PHY_TYPE_XLAUI: + ifmr->ifm_active |= IFM_OTHER; + break; #ifndef IFM_ETH_XTYPE case I40E_PHY_TYPE_1000BASE_KX: ifmr->ifm_active |= IFM_1000_CX; break; + case I40E_PHY_TYPE_SGMII: + ifmr->ifm_active |= IFM_OTHER; + break; case I40E_PHY_TYPE_10GBASE_CR1_CU: case I40E_PHY_TYPE_10GBASE_CR1: ifmr->ifm_active |= IFM_10G_TWINAX; @@ -1636,14 +1639,21 @@ ixl_media_status(struct ifnet * ifp, struct ifmediareq * ifmr) case I40E_PHY_TYPE_10GBASE_KR: ifmr->ifm_active |= IFM_10G_SR; break; + case I40E_PHY_TYPE_SFI: + ifmr->ifm_active |= IFM_OTHER; + break; case I40E_PHY_TYPE_40GBASE_KR4: case I40E_PHY_TYPE_XLPPI: + case I40E_PHY_TYPE_40GBASE_AOC: ifmr->ifm_active |= IFM_40G_SR4; break; #else case I40E_PHY_TYPE_1000BASE_KX: ifmr->ifm_active |= IFM_1000_KX; break; + case I40E_PHY_TYPE_SGMII: + ifmr->ifm_active |= IFM_1000_SGMII; + break; /* ERJ: What's the difference between these? */ case I40E_PHY_TYPE_10GBASE_CR1_CU: case I40E_PHY_TYPE_10GBASE_CR1: @@ -1655,6 +1665,9 @@ ixl_media_status(struct ifnet * ifp, struct ifmediareq * ifmr) case I40E_PHY_TYPE_10GBASE_KR: ifmr->ifm_active |= IFM_10G_KR; break; + case I40E_PHY_TYPE_SFI: + ifmr->ifm_active |= IFM_10G_SFI; + break; /* Our single 20G media type */ case I40E_PHY_TYPE_20GBASE_KR2: ifmr->ifm_active |= IFM_20G_KR2; @@ -1663,9 +1676,11 @@ ixl_media_status(struct ifnet * ifp, struct ifmediareq * ifmr) ifmr->ifm_active |= IFM_40G_KR4; break; case I40E_PHY_TYPE_XLPPI: + case I40E_PHY_TYPE_40GBASE_AOC: ifmr->ifm_active |= IFM_40G_XLPPI; break; #endif + /* Unknown to driver */ default: ifmr->ifm_active |= IFM_UNKNOWN; break; @@ -2066,8 +2081,6 @@ ixl_stop_locked(struct ixl_pf *pf) /* Tell the stack that the interface is no longer active */ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - - return; } @@ -2100,7 +2113,7 @@ ixl_assign_vsi_legacy(struct ixl_pf *pf) ixl_intr, pf, &pf->tag); if (error) { pf->res = NULL; - device_printf(dev, "Failed to register legacy/msi handler"); + device_printf(dev, "Failed to register legacy/msi handler\n"); return (error); } bus_describe_intr(dev, pf->res, pf->tag, "irq0"); @@ -2261,7 +2274,7 @@ ixl_init_msix(struct ixl_pf *pf) /* Override by tuneable */ if (ixl_enable_msix == 0) - goto msi; + goto no_msix; /* ** When used in a virtualized environment @@ -2292,7 +2305,7 @@ ixl_init_msix(struct ixl_pf *pf) /* May not be enabled */ device_printf(pf->dev, "Unable to map MSIX table\n"); - goto msi; + goto no_msix; } available = pci_msix_count(dev); @@ -2300,13 +2313,13 @@ ixl_init_msix(struct ixl_pf *pf) bus_release_resource(dev, SYS_RES_MEMORY, rid, pf->msix_mem); pf->msix_mem = NULL; - goto msi; + goto no_msix; } /* Figure out a reasonable auto config value */ queues = (mp_ncpus > (available - 1)) ? (available - 1) : mp_ncpus; - /* Override with hardcoded value if it's less than autoconfig count */ + /* Override with tunable value if tunable is less than autoconfig count */ if ((ixl_max_queues != 0) && (ixl_max_queues <= queues)) queues = ixl_max_queues; else if ((ixl_max_queues != 0) && (ixl_max_queues > queues)) @@ -2363,22 +2376,20 @@ ixl_init_msix(struct ixl_pf *pf) #endif return (vectors); } -msi: - vectors = pci_msi_count(dev); +no_msix: + vectors = pci_msi_count(dev); pf->vsi.num_queues = 1; - pf->msix = 1; ixl_max_queues = 1; ixl_enable_msix = 0; - if (vectors == 1 && pci_alloc_msi(dev, &vectors) == 0) + if (vectors == 1 && pci_alloc_msi(dev, &vectors) == 0) device_printf(pf->dev, "Using an MSI interrupt\n"); else { - pf->msix = 0; + vectors = 0; device_printf(pf->dev, "Using a Legacy interrupt\n"); } return (vectors); } - /* * Plumb MSIX vectors */ @@ -2489,14 +2500,6 @@ ixl_configure_legacy(struct ixl_pf *pf) | (IXL_QUEUE_EOL << I40E_QINT_TQCTL_NEXTQ_INDX_SHIFT); wr32(hw, I40E_QINT_TQCTL(0), reg); - /* Next enable the queue pair */ - reg = rd32(hw, I40E_QTX_ENA(0)); - reg |= I40E_QTX_ENA_QENA_REQ_MASK; - wr32(hw, I40E_QTX_ENA(0), reg); - - reg = rd32(hw, I40E_QRX_ENA(0)); - reg |= I40E_QRX_ENA_QENA_REQ_MASK; - wr32(hw, I40E_QRX_ENA(0), reg); } @@ -2544,7 +2547,7 @@ ixl_allocate_pci_resources(struct ixl_pf *pf) &rid, RF_ACTIVE); if (!(pf->pci_mem)) { - device_printf(dev, "Unable to allocate bus resource: memory\n"); + device_printf(dev, "Unable to allocate bus resource: PCI memory\n"); return (ENXIO); } @@ -2834,11 +2837,6 @@ ixl_link_event(struct ixl_pf *pf, struct i40e_arq_event_info *e) struct i40e_aqc_get_link_status *status = (struct i40e_aqc_get_link_status *)&e->desc.params.raw; - /* Firmware workaround: may need to wait for link to actually come up... */ - if (!pf->link_up && (status->link_info & I40E_AQ_SIGNAL_DETECT)) { - device_printf(dev, "%s: Waiting...\n", __func__); - i40e_msec_delay(4000); - } /* Request link status from adapter */ hw->phy.get_link_info = TRUE; @@ -2946,6 +2944,7 @@ ixl_initialize_vsi(struct ixl_vsi *vsi) ctxt.info.valid_sections = I40E_AQ_VSI_PROP_QUEUE_MAP_VALID; ctxt.info.mapping_flags |= I40E_AQ_VSI_QUE_MAP_CONTIG; ctxt.info.queue_mapping[0] = 0; + /* This VSI is assigned 64 queues (we may not use all of them) */ ctxt.info.tc_mapping[0] = 0x0c00; /* Set VLAN receive stripping mode */ @@ -3784,12 +3783,20 @@ ixl_setup_vlan_filters(struct ixl_vsi *vsi) /* ** Initialize filter list and add filters that the hardware ** needs to know about. +** +** Requires VSI's filter list & seid to be set before calling. */ static void ixl_init_filters(struct ixl_vsi *vsi) { /* Add broadcast address */ ixl_add_filter(vsi, ixl_bcast_addr, IXL_VLAN_ANY); + + /* + * Prevent Tx flow control frames from being sent out by + * non-firmware transmitters. + */ + i40e_add_filter_to_drop_tx_flow_control_frames(vsi->hw, vsi->seid); } /* @@ -4580,71 +4587,6 @@ ixl_do_adminq(void *context, int pending) IXL_PF_UNLOCK(pf); } -static int -ixl_debug_info(SYSCTL_HANDLER_ARGS) -{ - struct ixl_pf *pf; - int error, input = 0; - - error = sysctl_handle_int(oidp, &input, 0, req); - - if (error || !req->newptr) - return (error); - - if (input == 1) { - pf = (struct ixl_pf *)arg1; - ixl_print_debug_info(pf); - } - - return (error); -} - -static void -ixl_print_debug_info(struct ixl_pf *pf) -{ - struct i40e_hw *hw = &pf->hw; - struct ixl_vsi *vsi = &pf->vsi; - struct ixl_queue *que = vsi->queues; - struct rx_ring *rxr = &que->rxr; - struct tx_ring *txr = &que->txr; - u32 reg; - - - printf("Queue irqs = %jx\n", (uintmax_t)que->irqs); - printf("AdminQ irqs = %jx\n", (uintmax_t)pf->admin_irq); - printf("RX next check = %x\n", rxr->next_check); - printf("RX not ready = %jx\n", (uintmax_t)rxr->not_done); - printf("RX packets = %jx\n", (uintmax_t)rxr->rx_packets); - printf("TX desc avail = %x\n", txr->avail); - - reg = rd32(hw, I40E_GLV_GORCL(0xc)); - printf("RX Bytes = %x\n", reg); - reg = rd32(hw, I40E_GLPRT_GORCL(hw->port)); - printf("Port RX Bytes = %x\n", reg); - reg = rd32(hw, I40E_GLV_RDPC(0xc)); - printf("RX discard = %x\n", reg); - reg = rd32(hw, I40E_GLPRT_RDPC(hw->port)); - printf("Port RX discard = %x\n", reg); - - reg = rd32(hw, I40E_GLV_TEPC(0xc)); - printf("TX errors = %x\n", reg); - reg = rd32(hw, I40E_GLV_GOTCL(0xc)); - printf("TX Bytes = %x\n", reg); - - reg = rd32(hw, I40E_GLPRT_RUC(hw->port)); - printf("RX undersize = %x\n", reg); - reg = rd32(hw, I40E_GLPRT_RFC(hw->port)); - printf("RX fragments = %x\n", reg); - reg = rd32(hw, I40E_GLPRT_ROC(hw->port)); - printf("RX oversize = %x\n", reg); - reg = rd32(hw, I40E_GLPRT_RLEC(hw->port)); - printf("RX length error = %x\n", reg); - reg = rd32(hw, I40E_GLPRT_MRFC(hw->port)); - printf("mac remote fault = %x\n", reg); - reg = rd32(hw, I40E_GLPRT_MLFC(hw->port)); - printf("mac local fault = %x\n", reg); -} - /** * Update VSI-specific ethernet statistics counters. **/ @@ -5047,6 +4989,8 @@ ixl_set_advertised_speeds(struct ixl_pf *pf, int speeds) config.eeer = abilities.eeer_val; config.low_power_ctrl = abilities.d3_lpan; /* Translate into aq cmd link_speed */ + if (speeds & 0x10) + config.link_speed |= I40E_LINK_SPEED_40GB; if (speeds & 0x8) config.link_speed |= I40E_LINK_SPEED_20GB; if (speeds & 0x4) @@ -5081,12 +5025,13 @@ ixl_set_advertised_speeds(struct ixl_pf *pf, int speeds) /* ** Control link advertise speed: ** Flags: -** 0x1 - advertise 100 Mb -** 0x2 - advertise 1G -** 0x4 - advertise 10G -** 0x8 - advertise 20G +** 0x1 - advertise 100 Mb +** 0x2 - advertise 1G +** 0x4 - advertise 10G +** 0x8 - advertise 20G +** 0x10 - advertise 40G ** -** Does not work on 40G devices. +** Set to 0 to disable link */ static int ixl_set_advertise(SYSCTL_HANDLER_ARGS) @@ -5097,44 +5042,50 @@ ixl_set_advertise(SYSCTL_HANDLER_ARGS) int requested_ls = 0; int error = 0; - /* - ** FW doesn't support changing advertised speed - ** for 40G devices; speed is always 40G. - */ - if (i40e_is_40G_device(hw->device_id)) - return (ENODEV); - /* Read in new mode */ requested_ls = pf->advertised_speed; error = sysctl_handle_int(oidp, &requested_ls, 0, req); if ((error) || (req->newptr == NULL)) return (error); /* Check for sane value */ - if (requested_ls < 0x1 || requested_ls > 0xE) { + if (requested_ls > 0x10) { device_printf(dev, "Invalid advertised speed; " - "valid modes are 0x1 through 0xE\n"); + "valid modes are 0x1 through 0x10\n"); return (EINVAL); } /* Then check for validity based on adapter type */ switch (hw->device_id) { case I40E_DEV_ID_10G_BASE_T: case I40E_DEV_ID_10G_BASE_T4: - if (requested_ls & 0x8) { + /* BaseT */ + if (requested_ls & ~(0x7)) { device_printf(dev, - "20Gbs speed not supported on this device.\n"); + "Only 100M/1G/10G speeds supported on this device.\n"); return (EINVAL); } break; case I40E_DEV_ID_20G_KR2: case I40E_DEV_ID_20G_KR2_A: - if (requested_ls & 0x1) { + /* 20G */ + if (requested_ls & ~(0xE)) { device_printf(dev, - "100Mbs speed not supported on this device.\n"); + "Only 1G/10G/20G speeds supported on this device.\n"); + return (EINVAL); + } + break; + case I40E_DEV_ID_KX_B: + case I40E_DEV_ID_QSFP_A: + case I40E_DEV_ID_QSFP_B: + /* 40G */ + if (requested_ls & ~(0x10)) { + device_printf(dev, + "Only 40G speeds supported on this device.\n"); return (EINVAL); } break; default: - if (requested_ls & ~0x6) { + /* 10G (1G) */ + if (requested_ls & ~(0x6)) { device_printf(dev, "Only 1/10Gbs speeds are supported on this device.\n"); return (EINVAL); @@ -5231,18 +5182,14 @@ ixl_sysctl_show_fw(SYSCTL_HANDLER_ARGS) { struct ixl_pf *pf = (struct ixl_pf *)arg1; struct i40e_hw *hw = &pf->hw; - char buf[32]; + struct sbuf *sbuf; - snprintf(buf, sizeof(buf), - "f%d.%d a%d.%d n%02x.%02x e%08x", - hw->aq.fw_maj_ver, hw->aq.fw_min_ver, - hw->aq.api_maj_ver, hw->aq.api_min_ver, - (hw->nvm.version & IXL_NVM_VERSION_HI_MASK) >> - IXL_NVM_VERSION_HI_SHIFT, - (hw->nvm.version & IXL_NVM_VERSION_LO_MASK) >> - IXL_NVM_VERSION_LO_SHIFT, - hw->nvm.eetrack); - return (sysctl_handle_string(oidp, buf, strlen(buf), req)); + sbuf = sbuf_new_for_sysctl(NULL, NULL, 128, req); + ixl_nvm_version_str(hw, sbuf); + sbuf_finish(sbuf); + sbuf_delete(sbuf); + + return 0; } static int @@ -5323,11 +5270,12 @@ ixl_sysctl_link_status(SYSCTL_HANDLER_ARGS) "AN info : %#04x\n" "Ext info : %#04x\n" "Max Frame: %d\n" - "Pacing : %#04x", + "Pacing : %#04x\n" + "CRC En? : %d", link_status.phy_type, link_status.link_speed, link_status.link_info, link_status.an_info, link_status.ext_info, link_status.max_frame_size, - link_status.pacing); + link_status.pacing, link_status.crc_enable); return (sysctl_handle_string(oidp, buf, strlen(buf), req)); } @@ -5650,6 +5598,72 @@ ixl_sysctl_switch_config(SYSCTL_HANDLER_ARGS) return (error); } + +static int +ixl_debug_info(SYSCTL_HANDLER_ARGS) +{ + struct ixl_pf *pf; + int error, input = 0; + + error = sysctl_handle_int(oidp, &input, 0, req); + + if (error || !req->newptr) + return (error); + + if (input == 1) { + pf = (struct ixl_pf *)arg1; + ixl_print_debug_info(pf); + } + + return (error); +} + +static void +ixl_print_debug_info(struct ixl_pf *pf) +{ + struct i40e_hw *hw = &pf->hw; + struct ixl_vsi *vsi = &pf->vsi; + struct ixl_queue *que = vsi->queues; + struct rx_ring *rxr = &que->rxr; + struct tx_ring *txr = &que->txr; + u32 reg; + + + printf("Queue irqs = %jx\n", (uintmax_t)que->irqs); + printf("AdminQ irqs = %jx\n", (uintmax_t)pf->admin_irq); + printf("RX next check = %x\n", rxr->next_check); + printf("RX not ready = %jx\n", (uintmax_t)rxr->not_done); + printf("RX packets = %jx\n", (uintmax_t)rxr->rx_packets); + printf("TX desc avail = %x\n", txr->avail); + + reg = rd32(hw, I40E_GLV_GORCL(0xc)); + printf("RX Bytes = %x\n", reg); + reg = rd32(hw, I40E_GLPRT_GORCL(hw->port)); + printf("Port RX Bytes = %x\n", reg); + reg = rd32(hw, I40E_GLV_RDPC(0xc)); + printf("RX discard = %x\n", reg); + reg = rd32(hw, I40E_GLPRT_RDPC(hw->port)); + printf("Port RX discard = %x\n", reg); + + reg = rd32(hw, I40E_GLV_TEPC(0xc)); + printf("TX errors = %x\n", reg); + reg = rd32(hw, I40E_GLV_GOTCL(0xc)); + printf("TX Bytes = %x\n", reg); + + reg = rd32(hw, I40E_GLPRT_RUC(hw->port)); + printf("RX undersize = %x\n", reg); + reg = rd32(hw, I40E_GLPRT_RFC(hw->port)); + printf("RX fragments = %x\n", reg); + reg = rd32(hw, I40E_GLPRT_ROC(hw->port)); + printf("RX oversize = %x\n", reg); + reg = rd32(hw, I40E_GLPRT_RLEC(hw->port)); + printf("RX length error = %x\n", reg); + reg = rd32(hw, I40E_GLPRT_MRFC(hw->port)); + printf("mac remote fault = %x\n", reg); + reg = rd32(hw, I40E_GLPRT_MLFC(hw->port)); + printf("mac local fault = %x\n", reg); +} + #endif /* IXL_DEBUG_SYSCTL */ #ifdef PCI_IOV @@ -5991,7 +6005,6 @@ ixl_vc_opcode_str(uint16_t op) static int ixl_vc_opcode_level(uint16_t opcode) { - switch (opcode) { case I40E_VIRTCHNL_OP_GET_STATS: return (10); @@ -6047,6 +6060,8 @@ ixl_vf_version_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, return; } + vf->version = ((struct i40e_virtchnl_version_info *)msg)->minor; + reply.major = I40E_VIRTCHNL_VERSION_MAJOR; reply.minor = I40E_VIRTCHNL_VERSION_MINOR; ixl_send_vf_msg(pf, vf, I40E_VIRTCHNL_OP_VERSION, I40E_SUCCESS, &reply, @@ -6075,7 +6090,11 @@ ixl_vf_get_resources_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, { struct i40e_virtchnl_vf_resource reply; - if (msg_size != 0) { + if ((vf->version == 0 && msg_size != 0) || + (vf->version == 1 && msg_size != 4)) { + device_printf(pf->dev, "Invalid GET_VF_RESOURCES message size," + " for VF version %d.%d\n", I40E_VIRTCHNL_VERSION_MAJOR, + vf->version); i40e_send_vf_nack(pf, vf, I40E_VIRTCHNL_OP_GET_VF_RESOURCES, I40E_ERR_PARAM); return; @@ -6083,7 +6102,12 @@ ixl_vf_get_resources_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, bzero(&reply, sizeof(reply)); - reply.vf_offload_flags = I40E_VIRTCHNL_VF_OFFLOAD_L2; + if (vf->version == I40E_VIRTCHNL_VERSION_MINOR_NO_VF_CAPS) + reply.vf_offload_flags = I40E_VIRTCHNL_VF_OFFLOAD_L2 | + I40E_VIRTCHNL_VF_OFFLOAD_RSS_REG | + I40E_VIRTCHNL_VF_OFFLOAD_VLAN; + else + reply.vf_offload_flags = *(u32 *)msg; reply.num_vsis = 1; reply.num_queue_pairs = vf->vsi.num_queues; @@ -6976,7 +7000,7 @@ ixl_iov_init(device_t dev, uint16_t num_vfs, const nvlist_t *params) sysctl_ctx_init(&pf->vfs[i].ctx); ret = i40e_aq_add_veb(hw, pf_vsi->uplink_seid, pf_vsi->seid, - 1, FALSE, FALSE, &pf->veb_seid, NULL); + 1, FALSE, &pf->veb_seid, FALSE, NULL); if (ret != I40E_SUCCESS) { error = ixl_adminq_err_to_errno(hw->aq.asq_last_status); device_printf(dev, "add_veb failed; code=%d error=%d", ret, @@ -7083,6 +7107,8 @@ ixl_add_vf(device_t dev, uint16_t vfnum, const nvlist_t *params) if (nvlist_get_bool(params, "allow-promisc")) vf->vf_flags |= VF_FLAG_PROMISC_CAP; + /* TODO: Get VLAN that PF has set for the VF */ + vf->vf_flags |= VF_FLAG_VLAN_CAP; ixl_reset_vf(pf, vf); diff --git a/sys/dev/ixl/if_ixlv.c b/sys/dev/ixl/if_ixlv.c index 8c4a901a663d..5519095a87c4 100644 --- a/sys/dev/ixl/if_ixlv.c +++ b/sys/dev/ixl/if_ixlv.c @@ -48,7 +48,7 @@ /********************************************************************* * Driver version *********************************************************************/ -char ixlv_driver_version[] = "1.2.6"; +char ixlv_driver_version[] = "1.2.7-k"; /********************************************************************* * PCI Device ID Table @@ -240,7 +240,9 @@ ixlv_probe(device_t dev) u16 pci_subvendor_id, pci_subdevice_id; char device_name[256]; +#if 0 INIT_DEBUGOUT("ixlv_probe: begin"); +#endif pci_vendor_id = pci_get_vendor(dev); if (pci_vendor_id != I40E_INTEL_VENDOR_ID) @@ -346,7 +348,6 @@ ixlv_attach(device_t dev) INIT_DBG_DEV(dev, "PF API version verified"); - /* TODO: Figure out why MDD events occur when this reset is removed. */ /* Need API version before sending reset message */ error = ixlv_reset(sc); if (error) { @@ -373,7 +374,6 @@ ixlv_attach(device_t dev) INIT_DBG_DEV(dev, "Offload flags: %#010x", sc->vf_res->vf_offload_flags); - // TODO: Move this into ixlv_vf_config? /* got VF config message back from PF, now we can parse it */ for (int i = 0; i < sc->vf_res->num_vsis; i++) { if (sc->vf_res->vsi_res[i].vsi_type == I40E_VSI_SRIOV) @@ -670,7 +670,7 @@ ixlv_ioctl(struct ifnet *ifp, u_long command, caddr_t data) error = EINVAL; IOCTL_DBG_IF(ifp, "mtu too large"); } else { - IOCTL_DBG_IF2(ifp, "mtu: %lu -> %d", ifp->if_mtu, ifr->ifr_mtu); + IOCTL_DBG_IF2(ifp, "mtu: %u -> %d", ifp->if_mtu, ifr->ifr_mtu); // ERJ: Interestingly enough, these types don't match ifp->if_mtu = (u_long)ifr->ifr_mtu; vsi->max_frame_size = @@ -1002,7 +1002,8 @@ ixlv_setup_vc(struct ixlv_sc *sc) continue; } - INIT_DBG_DEV(dev, "Initialized Admin Queue, attempt %d", i+1); + INIT_DBG_DEV(dev, "Initialized Admin Queue; starting" + " send_api_ver attempt %d", i+1); retry_send: /* Send VF's API version */ @@ -1121,6 +1122,9 @@ retry_config: retried++; goto retry_config; } + device_printf(dev, + "%s: ixlv_get_vf_config() timed out waiting for a response\n", + __func__); } if (error) { device_printf(dev, diff --git a/sys/dev/ixl/ixl.h b/sys/dev/ixl/ixl.h index b28c8523e934..34ff88071fcf 100644 --- a/sys/dev/ixl/ixl.h +++ b/sys/dev/ixl/ixl.h @@ -88,6 +88,7 @@ #include #include #include +#include #include #ifdef PCI_IOV @@ -100,8 +101,6 @@ #include "i40e_prototype.h" #if defined(IXL_DEBUG) || defined(IXL_DEBUG_SYSCTL) -#include - #define MAC_FORMAT "%02x:%02x:%02x:%02x:%02x:%02x" #define MAC_FORMAT_ARGS(mac_addr) \ (mac_addr)[0], (mac_addr)[1], (mac_addr)[2], (mac_addr)[3], \ @@ -336,6 +335,11 @@ #define IXL_SET_NOPROTO(vsi, count) (vsi)->noproto = (count) #endif +/* Pre-10.2 media type compatibility */ +#if __FreeBSD_version < 1002000 +#define IFM_OTHER IFM_UNKNOWN +#endif + /* ***************************************************************************** * vendor_info_array @@ -380,7 +384,6 @@ struct ixl_mac_filter { u16 flags; }; - /* * The Transmit ring control struct */ @@ -606,26 +609,6 @@ struct ixl_sysctl_info { extern int ixl_atr_rate; -/* -** ixl_fw_version_str - format the FW and NVM version strings -*/ -static inline char * -ixl_fw_version_str(struct i40e_hw *hw) -{ - static char buf[32]; - - snprintf(buf, sizeof(buf), - "f%d.%d a%d.%d n%02x.%02x e%08x", - hw->aq.fw_maj_ver, hw->aq.fw_min_ver, - hw->aq.api_maj_ver, hw->aq.api_min_ver, - (hw->nvm.version & IXL_NVM_VERSION_HI_MASK) >> - IXL_NVM_VERSION_HI_SHIFT, - (hw->nvm.version & IXL_NVM_VERSION_LO_MASK) >> - IXL_NVM_VERSION_LO_SHIFT, - hw->nvm.eetrack); - return buf; -} - /********************************************************************* * TXRX Function prototypes *********************************************************************/ diff --git a/sys/dev/ixl/ixl_pf.h b/sys/dev/ixl/ixl_pf.h index e02988422f65..65915bea1544 100644 --- a/sys/dev/ixl/ixl_pf.h +++ b/sys/dev/ixl/ixl_pf.h @@ -50,6 +50,7 @@ struct ixl_vf { uint8_t mac[ETHER_ADDR_LEN]; uint16_t vf_num; + uint32_t version; struct sysctl_ctx_list ctx; }; @@ -125,15 +126,17 @@ struct ixl_pf { ((~(I40E_AQ_EVENT_LINK_UPDOWN | I40E_AQ_EVENT_MODULE_QUAL_FAIL \ | I40E_AQ_EVENT_MEDIA_NA)) & 0x3FF) -/* Sysctl help messages; displayed with "sysctl -d" */ +/*** Sysctl help messages; displayed with "sysctl -d" ***/ + #define IXL_SYSCTL_HELP_SET_ADVERTISE \ "\nControl advertised link speed.\n" \ "Flags:\n" \ -"\t0x1 - advertise 100M\n" \ -"\t0x2 - advertise 1G\n" \ -"\t0x4 - advertise 10G\n" \ -"\t0x8 - advertise 20G\n\n" \ -"Operation not supported on 40G devices." +"\t 0x1 - advertise 100M\n" \ +"\t 0x2 - advertise 1G\n" \ +"\t 0x4 - advertise 10G\n" \ +"\t 0x8 - advertise 20G\n" \ +"\t0x10 - advertise 40G\n\n" \ +"Set to 0 to disable link." #define IXL_SYSCTL_HELP_FC \ "\nSet flow control mode using the values below.\n" \ @@ -146,6 +149,42 @@ struct ixl_pf { "\nExecutes a \"Get Link Status\" command on the Admin Queue, and displays" \ " the response." \ +/*** Functions / Macros ***/ + +/* +** Put the NVM, EEtrackID, and OEM version information into a string +*/ +static void +ixl_nvm_version_str(struct i40e_hw *hw, struct sbuf *buf) +{ + u8 oem_ver = (u8)(hw->nvm.oem_ver >> 24); + u16 oem_build = (u16)((hw->nvm.oem_ver >> 16) & 0xFFFF); + u8 oem_patch = (u8)(hw->nvm.oem_ver & 0xFF); + + sbuf_printf(buf, + "nvm %x.%02x etid %08x oem %d.%d.%d", + (hw->nvm.version & IXL_NVM_VERSION_HI_MASK) >> + IXL_NVM_VERSION_HI_SHIFT, + (hw->nvm.version & IXL_NVM_VERSION_LO_MASK) >> + IXL_NVM_VERSION_LO_SHIFT, + hw->nvm.eetrack, + oem_ver, oem_build, oem_patch); +} + +static void +ixl_print_nvm_version(struct ixl_pf *pf) +{ + struct i40e_hw *hw = &pf->hw; + device_t dev = pf->dev; + struct sbuf *sbuf; + + sbuf = sbuf_new_auto(); + ixl_nvm_version_str(hw, sbuf); + sbuf_finish(sbuf); + device_printf(dev, "%s\n", sbuf_data(sbuf)); + sbuf_delete(sbuf); +} + #define I40E_VC_DEBUG(pf, level, ...) \ do { \ if ((pf)->vc_debug_lvl >= (level)) \ diff --git a/sys/dev/ixl/ixlv.h b/sys/dev/ixl/ixlv.h index 695b1efb15da..ee4f43602829 100644 --- a/sys/dev/ixl/ixlv.h +++ b/sys/dev/ixl/ixlv.h @@ -38,7 +38,7 @@ #include "ixlv_vc_mgr.h" -#define IXLV_AQ_MAX_ERR 1000 +#define IXLV_AQ_MAX_ERR 100 #define IXLV_MAX_FILTERS 128 #define IXLV_MAX_QUEUES 16 #define IXLV_AQ_TIMEOUT (1 * hz) diff --git a/sys/dev/ixl/ixlvc.c b/sys/dev/ixl/ixlvc.c index 9333b6050d79..443c9e25b4ff 100644 --- a/sys/dev/ixl/ixlvc.c +++ b/sys/dev/ixl/ixlvc.c @@ -213,6 +213,7 @@ ixlv_verify_api_ver(struct ixlv_sc *sc) struct i40e_virtchnl_version_info *pf_vvi; struct i40e_hw *hw = &sc->hw; struct i40e_arq_event_info event; + device_t dev = sc->dev; i40e_status err; int retries = 0; @@ -242,7 +243,7 @@ ixlv_verify_api_ver(struct ixlv_sc *sc) if ((enum i40e_virtchnl_ops)le32toh(event.desc.cookie_high) != I40E_VIRTCHNL_OP_VERSION) { - DDPRINTF(sc->dev, "Received unexpected op response: %d\n", + DDPRINTF(dev, "Received unexpected op response: %d\n", le32toh(event.desc.cookie_high)); err = EIO; goto out_alloc; @@ -251,10 +252,16 @@ ixlv_verify_api_ver(struct ixlv_sc *sc) pf_vvi = (struct i40e_virtchnl_version_info *)event.msg_buf; if ((pf_vvi->major > I40E_VIRTCHNL_VERSION_MAJOR) || ((pf_vvi->major == I40E_VIRTCHNL_VERSION_MAJOR) && - (pf_vvi->minor > I40E_VIRTCHNL_VERSION_MINOR))) + (pf_vvi->minor > I40E_VIRTCHNL_VERSION_MINOR))) { + device_printf(dev, "Critical PF/VF API version mismatch!\n"); err = EIO; - else + } else sc->pf_version = pf_vvi->minor; + + /* Log PF/VF api versions */ + device_printf(dev, "PF API %d.%d / VF API %d.%d\n", + pf_vvi->major, pf_vvi->minor, + I40E_VIRTCHNL_VERSION_MAJOR, I40E_VIRTCHNL_VERSION_MINOR); out_alloc: free(event.msg_buf, M_DEVBUF); @@ -275,16 +282,15 @@ ixlv_send_vf_config_msg(struct ixlv_sc *sc) u32 caps; caps = I40E_VIRTCHNL_VF_OFFLOAD_L2 | - I40E_VIRTCHNL_VF_OFFLOAD_RSS_AQ | I40E_VIRTCHNL_VF_OFFLOAD_RSS_REG | I40E_VIRTCHNL_VF_OFFLOAD_VLAN; - if (sc->pf_version) - return ixlv_send_pf_msg(sc, I40E_VIRTCHNL_OP_GET_VF_RESOURCES, - (u8 *)&caps, sizeof(caps)); - else + if (sc->pf_version == I40E_VIRTCHNL_VERSION_MINOR_NO_VF_CAPS) return ixlv_send_pf_msg(sc, I40E_VIRTCHNL_OP_GET_VF_RESOURCES, NULL, 0); + else + return ixlv_send_pf_msg(sc, I40E_VIRTCHNL_OP_GET_VF_RESOURCES, + (u8 *)&caps, sizeof(caps)); } /*