Add get/set implenentation for ethtool's module management signal API. Examples: ethtool --get-module-mgmt-signal eth16 type reset reset: low
ethtool --get-module-mgmt-signal eth16 type int reset: low ethtool --get-module-mgmt-signal eth16 type present reset: high sudo ethtool --set-module-mgmt-signal eth16 type reset value high ethtool --get-module-mgmt-signal eth16 type reset reset: high sudo ethtool --set-module-mgmt-signal eth16 type reset value low ethtool --get-module-mgmt-signal eth16 type reset reset: low Ice driver gets link event notification when module gets restarted. There is 'ice_handle_link_event' which handles the notification and updates link status information. Signed-off-by: Marek Pazdan <[email protected]> --- drivers/net/ethernet/intel/ice/ice.h | 6 ++ drivers/net/ethernet/intel/ice/ice_common.c | 21 +++++ drivers/net/ethernet/intel/ice/ice_common.h | 1 + drivers/net/ethernet/intel/ice/ice_ethtool.c | 94 ++++++++++++++++++++ drivers/net/ethernet/intel/ice/ice_main.c | 1 + drivers/net/ethernet/intel/ice/ice_type.h | 2 +- 6 files changed, 124 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index fd083647c14a..3b95a69140e8 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -195,6 +195,12 @@ #define ice_pf_src_tmr_owned(pf) ((pf)->hw.func_caps.ts_func_info.src_tmr_owned) +enum ice_mgmt_pin { + ICE_MGMT_PIN_RESET = 0, + ICE_MGMT_PIN_INT, + ICE_MGMT_PIN_PRESENT +}; + enum ice_feature { ICE_F_DSCP, ICE_F_PHY_RCLK, diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index 59df31c2c83f..2d643a7cc90f 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -6096,3 +6096,24 @@ u32 ice_get_link_speed(u16 index) return ice_aq_to_link_speed[index]; } + +/** + * ice_set_has_gpios - Sets availability of SDP GPIO pins. + * @hw: pointer to the HW structure + * + * This function sets availability of GPIO software defined pins + * (SDP) which are connected to transceiver slots and are used + * for transceiver control. + */ +bool ice_set_has_gpios(struct ice_hw *hw) +{ + if (hw->vendor_id != PCI_VENDOR_ID_INTEL) + return false; + + switch (hw->device_id) { + case ICE_DEV_ID_E810C_QSFP: + return true; + default: + return false; + } +} diff --git a/drivers/net/ethernet/intel/ice/ice_common.h b/drivers/net/ethernet/intel/ice/ice_common.h index 9b00aa0ddf10..b64629b1d60d 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.h +++ b/drivers/net/ethernet/intel/ice/ice_common.h @@ -304,4 +304,5 @@ ice_aq_write_i2c(struct ice_hw *hw, struct ice_aqc_link_topo_addr topo_addr, int ice_get_pca9575_handle(struct ice_hw *hw, u16 *pca9575_handle); int ice_read_pca9575_reg(struct ice_hw *hw, u8 offset, u8 *data); bool ice_fw_supports_report_dflt_cfg(struct ice_hw *hw); +bool ice_set_has_gpios(struct ice_hw *hw); #endif /* _ICE_COMMON_H_ */ diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index 7c2dc347e4e5..bf6a803729d4 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c @@ -3848,6 +3848,96 @@ ice_get_channels(struct net_device *dev, struct ethtool_channels *ch) ch->max_other = ch->other_count; } +/** + * ice_get_module_mgmt_signal - get module management signal status + * @dev: network interface device structure + * @params: ethtool module management signal params + * @extack: extended ACK from the Netlink message + * + * Returns -EIO if AQ command for GPIO get failed, otherwise + * returns 0 and current status of requested signal in params. + */ +static int +ice_get_module_mgmt_signal(struct net_device *dev, + struct ethtool_module_mgmt_params *params, + struct netlink_ext_ack *extack) +{ + struct ice_netdev_priv *np = netdev_priv(dev); + struct ice_pf *pf = np->vsi->back; + struct ice_hw *hw = &pf->hw; + u16 gpio_handle = 0; /* SOC/on-chip GPIO */ + bool value; + int ret = 0; + + if (hw->has_module_mgmt_gpio) { + switch (params->type) { + case ETHTOOL_MODULE_MGMT_RESET: + ret = ice_aq_get_gpio(hw, gpio_handle, + ICE_MGMT_PIN_RESET, &value, NULL); + break; + case ETHTOOL_MODULE_MGMT_INT: + ret = ice_aq_get_gpio(hw, gpio_handle, + ICE_MGMT_PIN_INT, &value, NULL); + break; + case ETHTOOL_MODULE_MGMT_PRESENT: + ret = ice_aq_get_gpio(hw, gpio_handle, + ICE_MGMT_PIN_PRESENT, &value, NULL); + break; + default: + dev_dbg(ice_pf_to_dev(pf), "Incorrect management signal requested: %d\n", + params->type); + return -EINVAL; + } + } else { + return -EOPNOTSUPP; + } + + if (ret == 0) { + params->value = value ? ETHTOOL_MODULE_MGMT_SIGNAL_HIGH : + ETHTOOL_MODULE_MGMT_SIGNAL_LOW; + } + return ret; +} + +/** + * ice_set_module_mgmt_signal - set module management signal config + * @dev: network interface device structure + * @params: ethtool module management signal params + * @extack: extended ACK from the Netlink message + * + * Returns -EIO if AQ command for GPIO set failed, otherwise + * returns 0. + */ +static int +ice_set_module_mgmt_signal(struct net_device *dev, + const struct ethtool_module_mgmt_params *params, + struct netlink_ext_ack *extack) +{ + struct ice_netdev_priv *np = netdev_priv(dev); + struct ice_pf *pf = np->vsi->back; + struct ice_hw *hw = &pf->hw; + u16 gpio_handle = 0; /* SOC/on-chip GPIO */ + bool value = params->value == ETHTOOL_MODULE_MGMT_SIGNAL_HIGH ? true : false; + int ret = 0; + + if (hw->has_module_mgmt_gpio) { + switch (params->type) { + case ETHTOOL_MODULE_MGMT_RESET: + ret = ice_aq_set_gpio(hw, gpio_handle, + ICE_MGMT_PIN_RESET, value, NULL); + break; + default: + dev_dbg(ice_pf_to_dev(pf), "Incorrect management signal requested: %d\n", + params->type); + return -EINVAL; + } + } else { + return -EOPNOTSUPP; + } + + return ret; +} + /** * ice_get_valid_rss_size - return valid number of RSS queues * @hw: pointer to the HW structure @@ -4815,6 +4905,8 @@ static const struct ethtool_ops ice_ethtool_ops = { .set_fecparam = ice_set_fecparam, .get_module_info = ice_get_module_info, .get_module_eeprom = ice_get_module_eeprom, + .get_module_mgmt_signal = ice_get_module_mgmt_signal, + .set_module_mgmt_signal = ice_set_module_mgmt_signal, }; static const struct ethtool_ops ice_ethtool_safe_mode_ops = { @@ -4837,6 +4929,8 @@ static const struct ethtool_ops ice_ethtool_safe_mode_ops = { .set_ringparam = ice_set_ringparam, .nway_reset = ice_nway_reset, .get_channels = ice_get_channels, + .get_module_mgmt_signal = ice_get_module_mgmt_signal, + .set_module_mgmt_signal = ice_set_module_mgmt_signal, }; /** diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index d390157b59fe..02b9809561e1 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -5294,6 +5294,7 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent) hw->port_info = NULL; hw->vendor_id = pdev->vendor; hw->device_id = pdev->device; + hw->has_module_mgmt_gpio = ice_set_has_gpios(hw); pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id); hw->subsystem_vendor_id = pdev->subsystem_vendor; hw->subsystem_device_id = pdev->subsystem_device; diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h index 0aab21113cc4..e88075ae4c8a 100644 --- a/drivers/net/ethernet/intel/ice/ice_type.h +++ b/drivers/net/ethernet/intel/ice/ice_type.h @@ -895,7 +895,7 @@ struct ice_hw { u32 psm_clk_freq; u64 debug_mask; /* bitmap for debug mask */ enum ice_mac_type mac_type; - + bool has_module_mgmt_gpio; /* has GPIO for module management */ u16 fd_ctr_base; /* FD counter base index */ /* pci info */ -- 2.45.2
