diff options
31 files changed, 596 insertions, 236 deletions
diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 54d5fdc303ca..eea845b22089 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -661,7 +661,7 @@ struct i40e_pf { struct ptp_clock_info ptp_caps; struct sk_buff *ptp_tx_skb; unsigned long ptp_tx_start; - struct hwtstamp_config tstamp_config; + struct kernel_hwtstamp_config tstamp_config; struct timespec64 ptp_prev_hw_time; struct work_struct ptp_extts0_work; ktime_t ptp_reset_start; @@ -1303,8 +1303,11 @@ void i40e_ptp_tx_hang(struct i40e_pf *pf); void i40e_ptp_tx_hwtstamp(struct i40e_pf *pf); void i40e_ptp_rx_hwtstamp(struct i40e_pf *pf, struct sk_buff *skb, u8 index); void i40e_ptp_set_increment(struct i40e_pf *pf); -int i40e_ptp_set_ts_config(struct i40e_pf *pf, struct ifreq *ifr); -int i40e_ptp_get_ts_config(struct i40e_pf *pf, struct ifreq *ifr); +int i40e_ptp_hwtstamp_get(struct net_device *netdev, + struct kernel_hwtstamp_config *config); +int i40e_ptp_hwtstamp_set(struct net_device *netdev, + struct kernel_hwtstamp_config *config, + struct netlink_ext_ack *extack); void i40e_ptp_save_hw_time(struct i40e_pf *pf); void i40e_ptp_restore_hw_time(struct i40e_pf *pf); void i40e_ptp_init(struct i40e_pf *pf); diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 3b4f59d978a5..949b74fbb127 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -2955,27 +2955,6 @@ static int i40e_change_mtu(struct net_device *netdev, int new_mtu) } /** - * i40e_ioctl - Access the hwtstamp interface - * @netdev: network interface device structure - * @ifr: interface request data - * @cmd: ioctl command - **/ -int i40e_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - struct i40e_netdev_priv *np = netdev_priv(netdev); - struct i40e_pf *pf = np->vsi->back; - - switch (cmd) { - case SIOCGHWTSTAMP: - return i40e_ptp_get_ts_config(pf, ifr); - case SIOCSHWTSTAMP: - return i40e_ptp_set_ts_config(pf, ifr); - default: - return -EOPNOTSUPP; - } -} - -/** * i40e_vlan_stripping_enable - Turn on vlan stripping for the VSI * @vsi: the vsi being adjusted **/ @@ -13626,7 +13605,6 @@ static const struct net_device_ops i40e_netdev_ops = { .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = i40e_set_mac, .ndo_change_mtu = i40e_change_mtu, - .ndo_eth_ioctl = i40e_ioctl, .ndo_tx_timeout = i40e_tx_timeout, .ndo_vlan_rx_add_vid = i40e_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = i40e_vlan_rx_kill_vid, @@ -13654,6 +13632,8 @@ static const struct net_device_ops i40e_netdev_ops = { .ndo_xsk_wakeup = i40e_xsk_wakeup, .ndo_dfwd_add_station = i40e_fwd_add, .ndo_dfwd_del_station = i40e_fwd_del, + .ndo_hwtstamp_get = i40e_ptp_hwtstamp_get, + .ndo_hwtstamp_set = i40e_ptp_hwtstamp_set, }; /** diff --git a/drivers/net/ethernet/intel/i40e/i40e_ptp.c b/drivers/net/ethernet/intel/i40e/i40e_ptp.c index b72a4b5d76b9..1d04ea7df552 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ptp.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ptp.c @@ -912,23 +912,26 @@ void i40e_ptp_set_increment(struct i40e_pf *pf) } /** - * i40e_ptp_get_ts_config - ioctl interface to read the HW timestamping - * @pf: Board private structure - * @ifr: ioctl data + * i40e_ptp_hwtstamp_get - interface to read the HW timestamping + * @netdev: Network device structure + * @config: Timestamping configuration structure * * Obtain the current hardware timestamping settigs as requested. To do this, * keep a shadow copy of the timestamp settings rather than attempting to * deconstruct it from the registers. **/ -int i40e_ptp_get_ts_config(struct i40e_pf *pf, struct ifreq *ifr) +int i40e_ptp_hwtstamp_get(struct net_device *netdev, + struct kernel_hwtstamp_config *config) { - struct hwtstamp_config *config = &pf->tstamp_config; + struct i40e_netdev_priv *np = netdev_priv(netdev); + struct i40e_pf *pf = np->vsi->back; if (!test_bit(I40E_FLAG_PTP_ENA, pf->flags)) return -EOPNOTSUPP; - return copy_to_user(ifr->ifr_data, config, sizeof(*config)) ? - -EFAULT : 0; + *config = pf->tstamp_config; + + return 0; } /** @@ -1167,7 +1170,7 @@ int i40e_ptp_alloc_pins(struct i40e_pf *pf) * more broad if the specific filter is not directly supported. **/ static int i40e_ptp_set_timestamp_mode(struct i40e_pf *pf, - struct hwtstamp_config *config) + struct kernel_hwtstamp_config *config) { struct i40e_hw *hw = &pf->hw; u32 tsyntype, regval; @@ -1290,9 +1293,10 @@ static int i40e_ptp_set_timestamp_mode(struct i40e_pf *pf, } /** - * i40e_ptp_set_ts_config - ioctl interface to control the HW timestamping - * @pf: Board private structure - * @ifr: ioctl data + * i40e_ptp_hwtstamp_set - interface to control the HW timestamping + * @netdev: Network device structure + * @config: Timestamping configuration structure + * @extack: Netlink extended ack structure for error reporting * * Respond to the user filter requests and make the appropriate hardware * changes here. The XL710 cannot support splitting of the Tx/Rx timestamping @@ -1303,26 +1307,25 @@ static int i40e_ptp_set_timestamp_mode(struct i40e_pf *pf, * as the user receives the timestamps they care about and the user is notified * the filter has been broadened. **/ -int i40e_ptp_set_ts_config(struct i40e_pf *pf, struct ifreq *ifr) +int i40e_ptp_hwtstamp_set(struct net_device *netdev, + struct kernel_hwtstamp_config *config, + struct netlink_ext_ack *extack) { - struct hwtstamp_config config; + struct i40e_netdev_priv *np = netdev_priv(netdev); + struct i40e_pf *pf = np->vsi->back; int err; if (!test_bit(I40E_FLAG_PTP_ENA, pf->flags)) return -EOPNOTSUPP; - if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) - return -EFAULT; - - err = i40e_ptp_set_timestamp_mode(pf, &config); + err = i40e_ptp_set_timestamp_mode(pf, config); if (err) return err; /* save these settings for future reference */ - pf->tstamp_config = config; + pf->tstamp_config = *config; - return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? - -EFAULT : 0; + return 0; } /** diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index f8ef80069e3d..af68869693ed 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -7902,27 +7902,6 @@ int ice_change_mtu(struct net_device *netdev, int new_mtu) } /** - * ice_eth_ioctl - Access the hwtstamp interface - * @netdev: network interface device structure - * @ifr: interface request data - * @cmd: ioctl command - */ -static int ice_eth_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - struct ice_netdev_priv *np = netdev_priv(netdev); - struct ice_pf *pf = np->vsi->back; - - switch (cmd) { - case SIOCGHWTSTAMP: - return ice_ptp_get_ts_config(pf, ifr); - case SIOCSHWTSTAMP: - return ice_ptp_set_ts_config(pf, ifr); - default: - return -EOPNOTSUPP; - } -} - -/** * ice_aq_str - convert AQ err code to a string * @aq_err: the AQ error code to convert */ @@ -9761,7 +9740,6 @@ static const struct net_device_ops ice_netdev_ops = { .ndo_change_mtu = ice_change_mtu, .ndo_get_stats64 = ice_get_stats64, .ndo_set_tx_maxrate = ice_set_tx_maxrate, - .ndo_eth_ioctl = ice_eth_ioctl, .ndo_set_vf_spoofchk = ice_set_vf_spoofchk, .ndo_set_vf_mac = ice_set_vf_mac, .ndo_get_vf_config = ice_get_vf_cfg, @@ -9785,4 +9763,6 @@ static const struct net_device_ops ice_netdev_ops = { .ndo_bpf = ice_xdp, .ndo_xdp_xmit = ice_xdp_xmit, .ndo_xsk_wakeup = ice_xsk_wakeup, + .ndo_hwtstamp_get = ice_ptp_hwtstamp_get, + .ndo_hwtstamp_set = ice_ptp_hwtstamp_set, }; diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c index e7005d757477..e358eb1d719f 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp.c +++ b/drivers/net/ethernet/intel/ice/ice_ptp.c @@ -2197,23 +2197,24 @@ static int ice_ptp_getcrosststamp(struct ptp_clock_info *info, } /** - * ice_ptp_get_ts_config - ioctl interface to read the timestamping config - * @pf: Board private structure - * @ifr: ioctl data + * ice_ptp_hwtstamp_get - interface to read the timestamping config + * @netdev: Pointer to network interface device structure + * @config: Timestamping configuration structure * * Copy the timestamping config to user buffer */ -int ice_ptp_get_ts_config(struct ice_pf *pf, struct ifreq *ifr) +int ice_ptp_hwtstamp_get(struct net_device *netdev, + struct kernel_hwtstamp_config *config) { - struct hwtstamp_config *config; + struct ice_netdev_priv *np = netdev_priv(netdev); + struct ice_pf *pf = np->vsi->back; if (pf->ptp.state != ICE_PTP_READY) return -EIO; - config = &pf->ptp.tstamp_config; + *config = pf->ptp.tstamp_config; - return copy_to_user(ifr->ifr_data, config, sizeof(*config)) ? - -EFAULT : 0; + return 0; } /** @@ -2221,8 +2222,8 @@ int ice_ptp_get_ts_config(struct ice_pf *pf, struct ifreq *ifr) * @pf: Board private structure * @config: hwtstamp settings requested or saved */ -static int -ice_ptp_set_timestamp_mode(struct ice_pf *pf, struct hwtstamp_config *config) +static int ice_ptp_set_timestamp_mode(struct ice_pf *pf, + struct kernel_hwtstamp_config *config) { switch (config->tx_type) { case HWTSTAMP_TX_OFF: @@ -2266,32 +2267,32 @@ ice_ptp_set_timestamp_mode(struct ice_pf *pf, struct hwtstamp_config *config) } /** - * ice_ptp_set_ts_config - ioctl interface to control the timestamping - * @pf: Board private structure - * @ifr: ioctl data + * ice_ptp_hwtstamp_set - interface to control the timestamping + * @netdev: Pointer to network interface device structure + * @config: Timestamping configuration structure + * @extack: Netlink extended ack structure for error reporting * * Get the user config and store it */ -int ice_ptp_set_ts_config(struct ice_pf *pf, struct ifreq *ifr) +int ice_ptp_hwtstamp_set(struct net_device *netdev, + struct kernel_hwtstamp_config *config, + struct netlink_ext_ack *extack) { - struct hwtstamp_config config; + struct ice_netdev_priv *np = netdev_priv(netdev); + struct ice_pf *pf = np->vsi->back; int err; if (pf->ptp.state != ICE_PTP_READY) return -EAGAIN; - if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) - return -EFAULT; - - err = ice_ptp_set_timestamp_mode(pf, &config); + err = ice_ptp_set_timestamp_mode(pf, config); if (err) return err; /* Return the actual configuration set */ - config = pf->ptp.tstamp_config; + *config = pf->ptp.tstamp_config; - return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? - -EFAULT : 0; + return 0; } /** diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h index c8dac5a5bcd9..137f2070a2d9 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp.h +++ b/drivers/net/ethernet/intel/ice/ice_ptp.h @@ -259,7 +259,7 @@ struct ice_ptp { struct ptp_extts_request extts_rqs[GLTSYN_EVNT_H_IDX_MAX]; struct ptp_clock_info info; struct ptp_clock *clock; - struct hwtstamp_config tstamp_config; + struct kernel_hwtstamp_config tstamp_config; u64 reset_time; u32 tx_hwtstamp_skipped; u32 tx_hwtstamp_timeouts; @@ -291,8 +291,11 @@ struct ice_ptp { #if IS_ENABLED(CONFIG_PTP_1588_CLOCK) int ice_ptp_clock_index(struct ice_pf *pf); struct ice_pf; -int ice_ptp_set_ts_config(struct ice_pf *pf, struct ifreq *ifr); -int ice_ptp_get_ts_config(struct ice_pf *pf, struct ifreq *ifr); +int ice_ptp_hwtstamp_get(struct net_device *netdev, + struct kernel_hwtstamp_config *config); +int ice_ptp_hwtstamp_set(struct net_device *netdev, + struct kernel_hwtstamp_config *config, + struct netlink_ext_ack *extack); void ice_ptp_restore_timestamp_mode(struct ice_pf *pf); void ice_ptp_extts_event(struct ice_pf *pf); @@ -313,12 +316,16 @@ void ice_ptp_init(struct ice_pf *pf); void ice_ptp_release(struct ice_pf *pf); void ice_ptp_link_change(struct ice_pf *pf, bool linkup); #else /* IS_ENABLED(CONFIG_PTP_1588_CLOCK) */ -static inline int ice_ptp_set_ts_config(struct ice_pf *pf, struct ifreq *ifr) + +static inline int ice_ptp_hwtstamp_get(struct net_device *netdev, + struct kernel_hwtstamp_config *config) { return -EOPNOTSUPP; } -static inline int ice_ptp_get_ts_config(struct ice_pf *pf, struct ifreq *ifr) +static inline int ice_ptp_hwtstamp_set(struct net_device *netdev, + struct kernel_hwtstamp_config *config, + struct netlink_ext_ack *extack) { return -EOPNOTSUPP; } diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h index f34ead8243e9..c3f4f7cd264e 100644 --- a/drivers/net/ethernet/intel/igb/igb.h +++ b/drivers/net/ethernet/intel/igb/igb.h @@ -626,7 +626,7 @@ struct igb_adapter { struct delayed_work ptp_overflow_work; struct work_struct ptp_tx_work; struct sk_buff *ptp_tx_skb; - struct hwtstamp_config tstamp_config; + struct kernel_hwtstamp_config tstamp_config; unsigned long ptp_tx_start; unsigned long last_rx_ptp_check; unsigned long last_rx_timestamp; @@ -771,8 +771,11 @@ void igb_ptp_tx_hang(struct igb_adapter *adapter); void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector, struct sk_buff *skb); int igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va, ktime_t *timestamp); -int igb_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr); -int igb_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr); +int igb_ptp_hwtstamp_get(struct net_device *netdev, + struct kernel_hwtstamp_config *config); +int igb_ptp_hwtstamp_set(struct net_device *netdev, + struct kernel_hwtstamp_config *config, + struct netlink_ext_ack *extack); void igb_set_flag_queue_pairs(struct igb_adapter *, const u32); unsigned int igb_get_max_rss_queues(struct igb_adapter *); #ifdef CONFIG_IGB_HWMON diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index b76a154e635e..a9a7a94ae61e 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -3062,6 +3062,8 @@ static const struct net_device_ops igb_netdev_ops = { .ndo_bpf = igb_xdp, .ndo_xdp_xmit = igb_xdp_xmit, .ndo_xsk_wakeup = igb_xsk_wakeup, + .ndo_hwtstamp_get = igb_ptp_hwtstamp_get, + .ndo_hwtstamp_set = igb_ptp_hwtstamp_set, }; /** @@ -9317,10 +9319,6 @@ static int igb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) case SIOCGMIIREG: case SIOCSMIIREG: return igb_mii_ioctl(netdev, ifr, cmd); - case SIOCGHWTSTAMP: - return igb_ptp_get_ts_config(netdev, ifr); - case SIOCSHWTSTAMP: - return igb_ptp_set_ts_config(netdev, ifr); default: return -EOPNOTSUPP; } diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c index 793c96016288..05d30aba66db 100644 --- a/drivers/net/ethernet/intel/igb/igb_ptp.c +++ b/drivers/net/ethernet/intel/igb/igb_ptp.c @@ -1094,21 +1094,22 @@ void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector, struct sk_buff *skb) } /** - * igb_ptp_get_ts_config - get hardware time stamping config + * igb_ptp_hwtstamp_get - get hardware time stamping config * @netdev: netdev struct - * @ifr: interface struct + * @config: timestamping configuration structure * * Get the hwtstamp_config settings to return to the user. Rather than attempt * to deconstruct the settings from the registers, just return a shadow copy * of the last known settings. **/ -int igb_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr) +int igb_ptp_hwtstamp_get(struct net_device *netdev, + struct kernel_hwtstamp_config *config) { struct igb_adapter *adapter = netdev_priv(netdev); - struct hwtstamp_config *config = &adapter->tstamp_config; - return copy_to_user(ifr->ifr_data, config, sizeof(*config)) ? - -EFAULT : 0; + *config = adapter->tstamp_config; + + return 0; } /** @@ -1129,7 +1130,7 @@ int igb_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr) * level 2 or 4". */ static int igb_ptp_set_timestamp_mode(struct igb_adapter *adapter, - struct hwtstamp_config *config) + struct kernel_hwtstamp_config *config) { struct e1000_hw *hw = &adapter->hw; u32 tsync_tx_ctl = E1000_TSYNCTXCTL_ENABLED; @@ -1275,30 +1276,26 @@ static int igb_ptp_set_timestamp_mode(struct igb_adapter *adapter, } /** - * igb_ptp_set_ts_config - set hardware time stamping config + * igb_ptp_hwtstamp_set - set hardware time stamping config * @netdev: netdev struct - * @ifr: interface struct - * + * @config: timestamping configuration structure + * @extack: netlink extended ack structure for error reporting **/ -int igb_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr) +int igb_ptp_hwtstamp_set(struct net_device *netdev, + struct kernel_hwtstamp_config *config, + struct netlink_ext_ack *extack) { struct igb_adapter *adapter = netdev_priv(netdev); - struct hwtstamp_config config; int err; - if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) - return -EFAULT; - - err = igb_ptp_set_timestamp_mode(adapter, &config); + err = igb_ptp_set_timestamp_mode(adapter, config); if (err) return err; /* save these settings for future reference */ - memcpy(&adapter->tstamp_config, &config, - sizeof(adapter->tstamp_config)); + adapter->tstamp_config = *config; - return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? - -EFAULT : 0; + return 0; } /** diff --git a/drivers/net/ethernet/intel/igbvf/ethtool.c b/drivers/net/ethernet/intel/igbvf/ethtool.c index 83b97989a6bd..773895c663fd 100644 --- a/drivers/net/ethernet/intel/igbvf/ethtool.c +++ b/drivers/net/ethernet/intel/igbvf/ethtool.c @@ -33,6 +33,7 @@ static const struct igbvf_stats igbvf_gstrings_stats[] = { { "lbrx_bytes", IGBVF_STAT(stats.gorlbc, stats.base_gorlbc) }, { "lbrx_packets", IGBVF_STAT(stats.gprlbc, stats.base_gprlbc) }, { "tx_restart_queue", IGBVF_STAT(restart_queue, zero_base) }, + { "tx_timeout_count", IGBVF_STAT(tx_timeout_count, zero_base) }, { "rx_long_byte_count", IGBVF_STAT(stats.gorc, stats.base_gorc) }, { "rx_csum_offload_good", IGBVF_STAT(hw_csum_good, zero_base) }, { "rx_csum_offload_errors", IGBVF_STAT(hw_csum_err, zero_base) }, diff --git a/drivers/net/ethernet/intel/igbvf/igbvf.h b/drivers/net/ethernet/intel/igbvf/igbvf.h index ca6e44245a7b..ba9c3fee6da7 100644 --- a/drivers/net/ethernet/intel/igbvf/igbvf.h +++ b/drivers/net/ethernet/intel/igbvf/igbvf.h @@ -238,8 +238,6 @@ struct igbvf_adapter { int int_mode; u32 eims_enable_mask; u32 eims_other; - u32 int_counter0; - u32 int_counter1; u32 eeprom_wol; u32 wol; diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c index e55dd9345833..aed9162afd38 100644 --- a/drivers/net/ethernet/intel/igbvf/netdev.c +++ b/drivers/net/ethernet/intel/igbvf/netdev.c @@ -855,8 +855,6 @@ static irqreturn_t igbvf_msix_other(int irq, void *data) struct igbvf_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - adapter->int_counter1++; - hw->mac.get_link_status = 1; if (!test_bit(__IGBVF_DOWN, &adapter->state)) mod_timer(&adapter->watchdog_timer, jiffies + 1); @@ -899,8 +897,6 @@ static irqreturn_t igbvf_intr_msix_rx(int irq, void *data) struct net_device *netdev = data; struct igbvf_adapter *adapter = netdev_priv(netdev); - adapter->int_counter0++; - /* Write the ITR value calculated at the end of the * previous interrupt. */ diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h index 1525ae25fd3e..97b1a2c820ee 100644 --- a/drivers/net/ethernet/intel/igc/igc.h +++ b/drivers/net/ethernet/intel/igc/igc.h @@ -315,7 +315,7 @@ struct igc_adapter { */ spinlock_t ptp_tx_lock; struct igc_tx_timestamp_request tx_tstamp[IGC_MAX_TX_TSTAMP_REGS]; - struct hwtstamp_config tstamp_config; + struct kernel_hwtstamp_config tstamp_config; unsigned int ptp_flags; /* System time value lock */ spinlock_t tmreg_lock; @@ -773,8 +773,11 @@ void igc_ptp_reset(struct igc_adapter *adapter); void igc_ptp_suspend(struct igc_adapter *adapter); void igc_ptp_stop(struct igc_adapter *adapter); ktime_t igc_ptp_rx_pktstamp(struct igc_adapter *adapter, __le32 *buf); -int igc_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr); -int igc_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr); +int igc_ptp_hwtstamp_get(struct net_device *netdev, + struct kernel_hwtstamp_config *config); +int igc_ptp_hwtstamp_set(struct net_device *netdev, + struct kernel_hwtstamp_config *config, + struct netlink_ext_ack *extack); void igc_ptp_tx_hang(struct igc_adapter *adapter); void igc_ptp_read(struct igc_adapter *adapter, struct timespec64 *ts); void igc_ptp_tx_tstamp_event(struct igc_adapter *adapter); diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index 4f6632cb9497..32ea4fdd3e2b 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -6303,24 +6303,6 @@ int igc_close(struct net_device *netdev) return 0; } -/** - * igc_ioctl - Access the hwtstamp interface - * @netdev: network interface device structure - * @ifr: interface request data - * @cmd: ioctl command - **/ -static int igc_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - switch (cmd) { - case SIOCGHWTSTAMP: - return igc_ptp_get_ts_config(netdev, ifr); - case SIOCSHWTSTAMP: - return igc_ptp_set_ts_config(netdev, ifr); - default: - return -EOPNOTSUPP; - } -} - static int igc_save_launchtime_params(struct igc_adapter *adapter, int queue, bool enable) { @@ -6971,12 +6953,13 @@ static const struct net_device_ops igc_netdev_ops = { .ndo_fix_features = igc_fix_features, .ndo_set_features = igc_set_features, .ndo_features_check = igc_features_check, - .ndo_eth_ioctl = igc_ioctl, .ndo_setup_tc = igc_setup_tc, .ndo_bpf = igc_bpf, .ndo_xdp_xmit = igc_xdp_xmit, .ndo_xsk_wakeup = igc_xsk_wakeup, .ndo_get_tstamp = igc_get_tstamp, + .ndo_hwtstamp_get = igc_ptp_hwtstamp_get, + .ndo_hwtstamp_set = igc_ptp_hwtstamp_set, }; u32 igc_rd32(struct igc_hw *hw, u32 reg) diff --git a/drivers/net/ethernet/intel/igc/igc_ptp.c b/drivers/net/ethernet/intel/igc/igc_ptp.c index f4f5c28615d3..b7b46d863bee 100644 --- a/drivers/net/ethernet/intel/igc/igc_ptp.c +++ b/drivers/net/ethernet/intel/igc/igc_ptp.c @@ -626,7 +626,7 @@ static void igc_ptp_enable_tx_timestamp(struct igc_adapter *adapter) * Return: 0 in case of success, negative errno code otherwise. */ static int igc_ptp_set_timestamp_mode(struct igc_adapter *adapter, - struct hwtstamp_config *config) + struct kernel_hwtstamp_config *config) { switch (config->tx_type) { case HWTSTAMP_TX_OFF: @@ -853,48 +853,46 @@ void igc_ptp_tx_tstamp_event(struct igc_adapter *adapter) } /** - * igc_ptp_set_ts_config - set hardware time stamping config + * igc_ptp_hwtstamp_set - set hardware time stamping config * @netdev: network interface device structure - * @ifr: interface request data + * @config: timestamping configuration structure + * @extack: netlink extended ack structure for error reporting * **/ -int igc_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr) +int igc_ptp_hwtstamp_set(struct net_device *netdev, + struct kernel_hwtstamp_config *config, + struct netlink_ext_ack *extack) { struct igc_adapter *adapter = netdev_priv(netdev); - struct hwtstamp_config config; int err; - if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) - return -EFAULT; - - err = igc_ptp_set_timestamp_mode(adapter, &config); + err = igc_ptp_set_timestamp_mode(adapter, config); if (err) return err; /* save these settings for future reference */ - memcpy(&adapter->tstamp_config, &config, - sizeof(adapter->tstamp_config)); + adapter->tstamp_config = *config; - return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? - -EFAULT : 0; + return 0; } /** - * igc_ptp_get_ts_config - get hardware time stamping config + * igc_ptp_hwtstamp_get - get hardware time stamping config * @netdev: network interface device structure - * @ifr: interface request data + * @config: timestamping configuration structure * * Get the hwtstamp_config settings to return to the user. Rather than attempt * to deconstruct the settings from the registers, just return a shadow copy * of the last known settings. **/ -int igc_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr) +int igc_ptp_hwtstamp_get(struct net_device *netdev, + struct kernel_hwtstamp_config *config) { struct igc_adapter *adapter = netdev_priv(netdev); - struct hwtstamp_config *config = &adapter->tstamp_config; - return copy_to_user(ifr->ifr_data, config, sizeof(*config)) ? - -EFAULT : 0; + *config = adapter->tstamp_config; + + return 0; } /* The two conditions below must be met for cross timestamping via diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index c6772cd2d802..05b36ac3ac29 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -429,6 +429,10 @@ enum ixgbe_ring_f_enum { #define IXGBE_BAD_L2A_QUEUE 3 #define IXGBE_MAX_MACVLANS 63 +#define IXGBE_MAX_TX_QUEUES 128 +#define IXGBE_MAX_TX_DESCRIPTORS 40 +#define IXGBE_MAX_TX_VF_HANGS 4 + DECLARE_STATIC_KEY_FALSE(ixgbe_xdp_locking_key); struct ixgbe_ring_feature { @@ -785,7 +789,7 @@ struct ixgbe_adapter { struct ptp_clock_info ptp_caps; struct work_struct ptp_tx_work; struct sk_buff *ptp_tx_skb; - struct hwtstamp_config tstamp_config; + struct kernel_hwtstamp_config tstamp_config; unsigned long ptp_tx_start; unsigned long last_overflow_check; unsigned long last_rx_ptp_check; @@ -810,6 +814,7 @@ struct ixgbe_adapter { u32 timer_event_accumulator; u32 vferr_refcount; struct ixgbe_mac_addr *mac_table; + u8 tx_hang_count[IXGBE_MAX_TX_QUEUES]; struct kobject *info_kobj; u16 lse_mask; #ifdef CONFIG_IXGBE_HWMON @@ -1080,8 +1085,11 @@ static inline void ixgbe_ptp_rx_hwtstamp(struct ixgbe_ring *rx_ring, rx_ring->last_rx_timestamp = jiffies; } -int ixgbe_ptp_set_ts_config(struct ixgbe_adapter *adapter, struct ifreq *ifr); -int ixgbe_ptp_get_ts_config(struct ixgbe_adapter *adapter, struct ifreq *ifr); +int ixgbe_ptp_hwtstamp_get(struct net_device *netdev, + struct kernel_hwtstamp_config *config); +int ixgbe_ptp_hwtstamp_set(struct net_device *netdev, + struct kernel_hwtstamp_config *config, + struct netlink_ext_ack *extack); void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter); void ixgbe_ptp_reset(struct ixgbe_adapter *adapter); void ixgbe_ptp_check_pps_event(struct ixgbe_adapter *adapter); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c index 444da982593f..406c15f58034 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c @@ -45,7 +45,7 @@ static void ixgbe_set_pcie_completion_timeout(struct ixgbe_hw *hw) goto out; /* - * if capababilities version is type 1 we can write the + * if capabilities version is type 1 we can write the * timeout of 10ms to 250ms through the GCR register */ if (!(gcr & IXGBE_GCR_CAP_VER2)) { @@ -751,7 +751,7 @@ mac_reset_top: /* * Store the original AUTOC value if it has not been * stored off yet. Otherwise restore the stored original - * AUTOC value since the reset operation sets back to deaults. + * AUTOC value since the reset operation sets back to defaults. */ autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); if (hw->mac.orig_link_settings_stored == false) { diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index 5784d5d1896e..4ff19426ab74 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -244,7 +244,7 @@ int ixgbe_setup_fc_generic(struct ixgbe_hw *hw) */ if (hw->phy.media_type == ixgbe_media_type_backplane) { /* Need the SW/FW semaphore around AUTOC writes if 82599 and - * LESM is on, likewise reset_pipeline requries the lock as + * LESM is on, likewise reset_pipeline requires the lock as * it also writes AUTOC. */ ret_val = hw->mac.ops.prot_autoc_write(hw, reg_bp, locked); @@ -301,7 +301,7 @@ int ixgbe_start_hw_generic(struct ixgbe_hw *hw) return ret_val; } - /* Cashe bit indicating need for crosstalk fix */ + /* Cache bit indicating need for crosstalk fix */ switch (hw->mac.type) { case ixgbe_mac_82599EB: case ixgbe_mac_X550EM_x: diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c index 71ea25de1bac..87b03c1992a8 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c @@ -3965,6 +3965,10 @@ static const struct ixgbe_mac_operations mac_ops_e610 = { .prot_autoc_write = prot_autoc_write_generic, .setup_fc = ixgbe_setup_fc_e610, .fc_autoneg = ixgbe_fc_autoneg_e610, + .enable_mdd = ixgbe_enable_mdd_x550, + .disable_mdd = ixgbe_disable_mdd_x550, + .restore_mdd_vf = ixgbe_restore_mdd_vf_x550, + .handle_mdd = ixgbe_handle_mdd_x550, }; static const struct ixgbe_phy_operations phy_ops_e610 = { diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c index 7dcf6ecd157b..011fda9c6193 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c @@ -744,7 +744,7 @@ void ixgbe_free_fcoe_ddp_resources(struct ixgbe_adapter *adapter) * ixgbe_setup_fcoe_ddp_resources - setup all fcoe ddp context resources * @adapter: ixgbe adapter * - * Sets up ddp context resouces + * Sets up ddp context resources * * Returns : 0 indicates success or -EINVAL on failure */ diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c index 336d47ffb95a..170a29d162c6 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c @@ -891,7 +891,7 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter, q_vector->rx.itr = IXGBE_ITR_ADAPTIVE_MAX_USECS | IXGBE_ITR_ADAPTIVE_LATENCY; - /* intialize ITR */ + /* initialize ITR */ if (txr_count && !rxr_count) { /* tx only vector */ if (adapter->tx_itr_setting == 1) @@ -1293,7 +1293,8 @@ void ixgbe_tx_ctxtdesc(struct ixgbe_ring *tx_ring, u32 vlan_macip_lens, tx_ring->next_to_use = (i < tx_ring->count) ? i : 0; /* set bits to identify this as an advanced context descriptor */ - type_tucmd |= IXGBE_TXD_CMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT; + type_tucmd |= IXGBE_TXD_CMD_DEXT | + FIELD_PREP(IXGBE_ADVTXD_DTYP_MASK, IXGBE_ADVTXD_DTYP_CTXT); context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens); context_desc->fceof_saidx = cpu_to_le32(fceof_saidx); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 6eccfba51fac..6122a0abb41f 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -9,6 +9,7 @@ #include <linux/string.h> #include <linux/in.h> #include <linux/interrupt.h> +#include <linux/iopoll.h> #include <linux/ip.h> #include <linux/tcp.h> #include <linux/sctp.h> @@ -1040,6 +1041,48 @@ static u64 ixgbe_get_tx_pending(struct ixgbe_ring *ring) return ((head <= tail) ? tail : tail + ring->count) - head; } +/** + * ixgbe_get_vf_idx - provide VF index number based on queue index + * @adapter: pointer to the adapter struct + * @queue: Tx queue identifier + * @vf: output VF index + * + * Provide VF index number associated to the input queue. + * + * Returns: 0 if VF provided or error number. + */ +static int ixgbe_get_vf_idx(struct ixgbe_adapter *adapter, u16 queue, u16 *vf) +{ + struct ixgbe_hw *hw = &adapter->hw; + u8 queue_count; + u32 reg; + + if (queue >= adapter->num_tx_queues) + return -EINVAL; + + /* Determine number of queues by checking + * number of virtual functions + */ + reg = IXGBE_READ_REG(hw, IXGBE_GCR_EXT); + switch (reg & IXGBE_GCR_EXT_VT_MODE_MASK) { + case IXGBE_GCR_EXT_VT_MODE_64: + queue_count = IXGBE_64VFS_QUEUES; + break; + case IXGBE_GCR_EXT_VT_MODE_32: + queue_count = IXGBE_32VFS_QUEUES; + break; + case IXGBE_GCR_EXT_VT_MODE_16: + queue_count = IXGBE_16VFS_QUEUES; + break; + default: + return -EINVAL; + } + + *vf = queue / queue_count; + + return 0; +} + static bool ixgbe_check_tx_hang(struct ixgbe_ring *tx_ring) { u32 tx_done = ixgbe_get_tx_completed(tx_ring); @@ -1159,6 +1202,150 @@ void ixgbe_update_rx_ring_stats(struct ixgbe_ring *rx_ring, } /** + * ixgbe_pf_handle_tx_hang - handle Tx hang on PF + * @tx_ring: tx ring number + * @next: next ring + * + * Prints a message containing details about the tx hang. + */ +static void ixgbe_pf_handle_tx_hang(struct ixgbe_ring *tx_ring, + unsigned int next) +{ + struct ixgbe_adapter *adapter = netdev_priv(tx_ring->netdev); + struct ixgbe_hw *hw = &adapter->hw; + + e_err(drv, "Detected Tx Unit Hang%s\n" + " Tx Queue <%d>\n" + " TDH, TDT <%x>, <%x>\n" + " next_to_use <%x>\n" + " next_to_clean <%x>\n" + "tx_buffer_info[next_to_clean]\n" + " time_stamp <%lx>\n" + " jiffies <%lx>\n", + ring_is_xdp(tx_ring) ? " (XDP)" : "", + tx_ring->queue_index, + IXGBE_READ_REG(hw, IXGBE_TDH(tx_ring->reg_idx)), + IXGBE_READ_REG(hw, IXGBE_TDT(tx_ring->reg_idx)), + tx_ring->next_to_use, next, + tx_ring->tx_buffer_info[next].time_stamp, jiffies); + + if (!ring_is_xdp(tx_ring)) + netif_stop_subqueue(tx_ring->netdev, + tx_ring->queue_index); +} + +/** + * ixgbe_vf_handle_tx_hang - handle Tx hang on VF + * @adapter: structure containing ring specific data + * @vf: VF index + * + * Print a message containing details about malicious driver detection. + * Set malicious VF link down if the detection happened several times. + */ +static void ixgbe_vf_handle_tx_hang(struct ixgbe_adapter *adapter, u16 vf) +{ + struct ixgbe_hw *hw = &adapter->hw; + + if (adapter->hw.mac.type != ixgbe_mac_e610) + return; + + e_warn(drv, + "Malicious Driver Detection tx hang detected on PF %d VF %d MAC: %pM", + hw->bus.func, vf, adapter->vfinfo[vf].vf_mac_addresses); + + adapter->tx_hang_count[vf]++; + if (adapter->tx_hang_count[vf] == IXGBE_MAX_TX_VF_HANGS) { + ixgbe_set_vf_link_state(adapter, vf, + IFLA_VF_LINK_STATE_DISABLE); + adapter->tx_hang_count[vf] = 0; + } +} + +static u32 ixgbe_poll_tx_icache(struct ixgbe_hw *hw, u16 queue, u16 idx) +{ + IXGBE_WRITE_REG(hw, IXGBE_TXDESCIC, queue * idx); + return IXGBE_READ_REG(hw, IXGBE_TXDESCIC); +} + +/** + * ixgbe_check_illegal_queue - search for queue with illegal packet + * @adapter: structure containing ring specific data + * @queue: queue index + * + * Check if tx descriptor connected with input queue + * contains illegal packet. + * + * Returns: true if queue contain illegal packet. + */ +static bool ixgbe_check_illegal_queue(struct ixgbe_adapter *adapter, + u16 queue) +{ + u32 hdr_len_reg, mss_len_reg, type_reg; + struct ixgbe_hw *hw = &adapter->hw; + u32 mss_len, header_len, reg; + + for (u16 i = 0; i < IXGBE_MAX_TX_DESCRIPTORS; i++) { + /* HW will clear bit IXGBE_TXDESCIC_READY when address + * is written to address field. HW will set this bit + * when iCache read is done, and data is ready at TIC_DWx. + * Set descriptor address. + */ + read_poll_timeout(ixgbe_poll_tx_icache, reg, + !(reg & IXGBE_TXDESCIC_READY), 0, 0, false, + hw, queue, i); + + /* read tx descriptor access registers */ + hdr_len_reg = IXGBE_READ_REG(hw, IXGBE_TIC_DW2(IXGBE_VLAN_MACIP_LENS_REG)); + type_reg = IXGBE_READ_REG(hw, IXGBE_TIC_DW2(IXGBE_TYPE_TUCMD_MLHL)); + mss_len_reg = IXGBE_READ_REG(hw, IXGBE_TIC_DW2(IXGBE_MSS_L4LEN_IDX)); + + /* check if Advanced Context Descriptor */ + if (FIELD_GET(IXGBE_ADVTXD_DTYP_MASK, type_reg) != + IXGBE_ADVTXD_DTYP_CTXT) + continue; + + /* check for illegal MSS and Header length */ + mss_len = FIELD_GET(IXGBE_ADVTXD_MSS_MASK, mss_len_reg); + header_len = FIELD_GET(IXGBE_ADVTXD_HEADER_LEN_MASK, + hdr_len_reg); + if ((mss_len + header_len) > SZ_16K) { + e_warn(probe, "mss len + header len too long\n"); + return true; + } + } + + return false; +} + +/** + * ixgbe_handle_mdd_event - handle mdd event + * @adapter: structure containing ring specific data + * @tx_ring: tx descriptor ring to handle + * + * Reset VF driver if malicious vf detected or + * illegal packet in an any queue detected. + */ +static void ixgbe_handle_mdd_event(struct ixgbe_adapter *adapter, + struct ixgbe_ring *tx_ring) +{ + u16 vf, q; + + if (adapter->vfinfo && ixgbe_check_mdd_event(adapter)) { + /* vf mdd info and malicious vf detected */ + if (!ixgbe_get_vf_idx(adapter, tx_ring->queue_index, &vf)) + ixgbe_vf_handle_tx_hang(adapter, vf); + } else { + /* malicious vf not detected */ + for (q = 0; q < IXGBE_MAX_TX_QUEUES; q++) { + if (ixgbe_check_illegal_queue(adapter, q) && + !ixgbe_get_vf_idx(adapter, q, &vf)) + /* illegal queue detected */ + ixgbe_vf_handle_tx_hang(adapter, vf); + } + } +} + +/** * ixgbe_clean_tx_irq - Reclaim resources after transmit completes * @q_vector: structure containing interrupt and ring information * @tx_ring: tx ring to clean @@ -1265,26 +1452,10 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, adapter->tx_ipsec += total_ipsec; if (check_for_tx_hang(tx_ring) && ixgbe_check_tx_hang(tx_ring)) { - /* schedule immediate reset if we believe we hung */ - struct ixgbe_hw *hw = &adapter->hw; - e_err(drv, "Detected Tx Unit Hang %s\n" - " Tx Queue <%d>\n" - " TDH, TDT <%x>, <%x>\n" - " next_to_use <%x>\n" - " next_to_clean <%x>\n" - "tx_buffer_info[next_to_clean]\n" - " time_stamp <%lx>\n" - " jiffies <%lx>\n", - ring_is_xdp(tx_ring) ? "(XDP)" : "", - tx_ring->queue_index, - IXGBE_READ_REG(hw, IXGBE_TDH(tx_ring->reg_idx)), - IXGBE_READ_REG(hw, IXGBE_TDT(tx_ring->reg_idx)), - tx_ring->next_to_use, i, - tx_ring->tx_buffer_info[i].time_stamp, jiffies); - - if (!ring_is_xdp(tx_ring)) - netif_stop_subqueue(tx_ring->netdev, - tx_ring->queue_index); + if (adapter->hw.mac.type == ixgbe_mac_e610) + ixgbe_handle_mdd_event(adapter, tx_ring); + + ixgbe_pf_handle_tx_hang(tx_ring, i); e_info(probe, "tx hang %d detected on queue %d, resetting adapter\n", @@ -2200,7 +2371,7 @@ static struct sk_buff *ixgbe_build_skb(struct ixgbe_ring *rx_ring, struct sk_buff *skb; /* Prefetch first cache line of first page. If xdp->data_meta - * is unused, this points extactly as xdp->data, otherwise we + * is unused, this points exactly as xdp->data, otherwise we * likely have a consumer accessing first few bytes of meta * data, and then actual data. */ @@ -2323,7 +2494,7 @@ static void ixgbe_rx_buffer_flip(struct ixgbe_ring *rx_ring, * This function provides a "bounce buffer" approach to Rx interrupt * processing. The advantage to this is that on systems that have * expensive overhead for IOMMU access this provides a means of avoiding - * it by maintaining the mapping of the page to the syste. + * it by maintaining the mapping of the page to the system. * * Returns amount of work completed **/ @@ -3933,8 +4104,12 @@ void ixgbe_set_rx_drop_en(struct ixgbe_adapter *adapter) static void ixgbe_set_rx_drop_en(struct ixgbe_adapter *adapter) #endif { - int i; bool pfc_en = adapter->dcb_cfg.pfc_mode_enable; + struct ixgbe_hw *hw = &adapter->hw; + int i; + + if (hw->mac.ops.disable_mdd) + hw->mac.ops.disable_mdd(hw); if (adapter->ixgbe_ieee_pfc) pfc_en |= !!(adapter->ixgbe_ieee_pfc->pfc_en); @@ -3956,6 +4131,9 @@ static void ixgbe_set_rx_drop_en(struct ixgbe_adapter *adapter) for (i = 0; i < adapter->num_rx_queues; i++) ixgbe_disable_rx_drop(adapter, adapter->rx_ring[i]); } + + if (hw->mac.ops.enable_mdd) + hw->mac.ops.enable_mdd(hw); } #define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT 2 @@ -4885,7 +5063,7 @@ static void ixgbe_scrub_vfta(struct ixgbe_adapter *adapter, u32 vfta_offset) /* pull VLAN ID from VLVF */ vid = vlvf & VLAN_VID_MASK; - /* only concern outselves with a certain range */ + /* only concern ourselves with a certain range */ if (vid < vid_start || vid >= vid_end) continue; @@ -7964,6 +8142,9 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter) netif_carrier_on(netdev); ixgbe_check_vf_rate_limit(adapter); + if (adapter->num_vfs && hw->mac.ops.enable_mdd) + hw->mac.ops.enable_mdd(hw); + /* enable transmits */ netif_tx_wake_all_queues(adapter->netdev); @@ -9441,10 +9622,6 @@ static int ixgbe_ioctl(struct net_device *netdev, struct ifreq *req, int cmd) struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev); switch (cmd) { - case SIOCSHWTSTAMP: - return ixgbe_ptp_set_ts_config(adapter, req); - case SIOCGHWTSTAMP: - return ixgbe_ptp_get_ts_config(adapter, req); case SIOCGMIIPHY: if (!adapter->hw.phy.ops.read_reg) return -EOPNOTSUPP; @@ -10908,6 +11085,8 @@ static const struct net_device_ops ixgbe_netdev_ops = { .ndo_bpf = ixgbe_xdp, .ndo_xdp_xmit = ixgbe_xdp_xmit, .ndo_xsk_wakeup = ixgbe_xsk_wakeup, + .ndo_hwtstamp_get = ixgbe_ptp_hwtstamp_get, + .ndo_hwtstamp_set = ixgbe_ptp_hwtstamp_set, }; static void ixgbe_disable_txr_hw(struct ixgbe_adapter *adapter, @@ -11110,7 +11289,7 @@ void ixgbe_txrx_ring_enable(struct ixgbe_adapter *adapter, int ring) * ixgbe_enumerate_functions - Get the number of ports this device has * @adapter: adapter structure * - * This function enumerates the phsyical functions co-located on a single slot, + * This function enumerates the physical functions co-located on a single slot, * in order to determine how many ports a device has. This is most useful in * determining the required GT/s of PCIe bandwidth necessary for optimal * performance. diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h index bf65e82b4c61..4af149b63a39 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h @@ -34,7 +34,7 @@ #define IXGBE_VT_MSGTYPE_CTS 0x20000000 /* Indicates that VF is still clear to send requests */ #define IXGBE_VT_MSGINFO_SHIFT 16 -/* bits 23:16 are used for exra info for certain messages */ +/* bits 23:16 are used for extra info for certain messages */ #define IXGBE_VT_MSGINFO_MASK (0xFF << IXGBE_VT_MSGINFO_SHIFT) /* definitions to support mailbox API version negotiation */ diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c index 2d54828bdfbb..2449e4cf2679 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c @@ -1323,7 +1323,7 @@ int ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, ixgbe_link_speed *speed, * @hw: pointer to hardware structure * * Restart autonegotiation and PHY and waits for completion. - * This function always returns success, this is nessary since + * This function always returns success, this is necessary since * it is called via a function pointer that could call other * functions that could return an error. **/ diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c index eef25e11d938..40be99def2ee 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c @@ -936,20 +936,22 @@ void ixgbe_ptp_rx_rgtstamp(struct ixgbe_q_vector *q_vector, } /** - * ixgbe_ptp_get_ts_config - get current hardware timestamping configuration - * @adapter: pointer to adapter structure - * @ifr: ioctl data + * ixgbe_ptp_hwtstamp_get - get current hardware timestamping configuration + * @netdev: pointer to net device structure + * @config: timestamping configuration structure * * This function returns the current timestamping settings. Rather than * attempt to deconstruct registers to fill in the values, simply keep a copy * of the old settings around, and return a copy when requested. */ -int ixgbe_ptp_get_ts_config(struct ixgbe_adapter *adapter, struct ifreq *ifr) +int ixgbe_ptp_hwtstamp_get(struct net_device *netdev, + struct kernel_hwtstamp_config *config) { - struct hwtstamp_config *config = &adapter->tstamp_config; + struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev); - return copy_to_user(ifr->ifr_data, config, - sizeof(*config)) ? -EFAULT : 0; + *config = adapter->tstamp_config; + + return 0; } /** @@ -978,7 +980,7 @@ int ixgbe_ptp_get_ts_config(struct ixgbe_adapter *adapter, struct ifreq *ifr) * mode, if required to support the specifically requested mode. */ static int ixgbe_ptp_set_timestamp_mode(struct ixgbe_adapter *adapter, - struct hwtstamp_config *config) + struct kernel_hwtstamp_config *config) { struct ixgbe_hw *hw = &adapter->hw; u32 tsync_tx_ctl = IXGBE_TSYNCTXCTL_ENABLED; @@ -1129,31 +1131,29 @@ static int ixgbe_ptp_set_timestamp_mode(struct ixgbe_adapter *adapter, } /** - * ixgbe_ptp_set_ts_config - user entry point for timestamp mode - * @adapter: pointer to adapter struct - * @ifr: ioctl data + * ixgbe_ptp_hwtstamp_set - user entry point for timestamp mode + * @netdev: pointer to net device structure + * @config: timestamping configuration structure + * @extack: netlink extended ack structure for error reporting * * Set hardware to requested mode. If unsupported, return an error with no * changes. Otherwise, store the mode for future reference. */ -int ixgbe_ptp_set_ts_config(struct ixgbe_adapter *adapter, struct ifreq *ifr) +int ixgbe_ptp_hwtstamp_set(struct net_device *netdev, + struct kernel_hwtstamp_config *config, + struct netlink_ext_ack *extack) { - struct hwtstamp_config config; + struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev); int err; - if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) - return -EFAULT; - - err = ixgbe_ptp_set_timestamp_mode(adapter, &config); + err = ixgbe_ptp_set_timestamp_mode(adapter, config); if (err) return err; /* save these settings for future reference */ - memcpy(&adapter->tstamp_config, &config, - sizeof(adapter->tstamp_config)); + adapter->tstamp_config = *config; - return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? - -EFAULT : 0; + return 0; } static void ixgbe_ptp_link_speed_adjust(struct ixgbe_adapter *adapter, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c index 0dbbd2befd4d..32ac1e020d91 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c @@ -207,6 +207,7 @@ void ixgbe_enable_sriov(struct ixgbe_adapter *adapter, unsigned int max_vfs) int ixgbe_disable_sriov(struct ixgbe_adapter *adapter) { unsigned int num_vfs = adapter->num_vfs, vf; + struct ixgbe_hw *hw = &adapter->hw; unsigned long flags; int rss; @@ -237,6 +238,9 @@ int ixgbe_disable_sriov(struct ixgbe_adapter *adapter) if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)) return 0; + if (hw->mac.ops.disable_mdd) + hw->mac.ops.disable_mdd(hw); + #ifdef CONFIG_PCI_IOV /* * If our VFs are assigned we cannot shut down SR-IOV @@ -702,7 +706,7 @@ static inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf) u32 reg_val; u32 queue; - /* remove VLAN filters beloning to this VF */ + /* remove VLAN filters belonging to this VF */ ixgbe_clear_vf_vlans(adapter, vf); /* add back PF assigned VLAN or VLAN 0 */ @@ -1353,12 +1357,59 @@ static void ixgbe_rcv_ack_from_vf(struct ixgbe_adapter *adapter, u32 vf) ixgbe_write_mbx(hw, &msg, 1, vf); } +/** + * ixgbe_check_mdd_event - check for MDD event on all VFs + * @adapter: pointer to ixgbe adapter + * + * Return: true if there is a VF on which MDD event occurred, false otherwise. + */ +bool ixgbe_check_mdd_event(struct ixgbe_adapter *adapter) +{ + struct ixgbe_hw *hw = &adapter->hw; + DECLARE_BITMAP(vf_bitmap, 64); + bool ret = false; + int i; + + if (!hw->mac.ops.handle_mdd) + return false; + + /* Did we have a malicious event */ + bitmap_zero(vf_bitmap, 64); + hw->mac.ops.handle_mdd(hw, vf_bitmap); + + /* Log any blocked queues and release lock */ + for_each_set_bit(i, vf_bitmap, 64) { + dev_warn(&adapter->pdev->dev, + "Malicious event on VF %d tx:%x rx:%x\n", i, + IXGBE_READ_REG(hw, IXGBE_LVMMC_TX), + IXGBE_READ_REG(hw, IXGBE_LVMMC_RX)); + + if (hw->mac.ops.restore_mdd_vf) { + u32 ping; + + hw->mac.ops.restore_mdd_vf(hw, i); + + /* get the VF to rebuild its queues */ + adapter->vfinfo[i].clear_to_send = 0; + ping = IXGBE_PF_CONTROL_MSG | + IXGBE_VT_MSGTYPE_CTS; + ixgbe_write_mbx(hw, &ping, 1, i); + } + + ret = true; + } + + return ret; +} + void ixgbe_msg_task(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; unsigned long flags; u32 vf; + ixgbe_check_mdd_event(adapter); + spin_lock_irqsave(&adapter->vfs_lock, flags); for (vf = 0; vf < adapter->num_vfs; vf++) { /* process any reset requests */ diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h index 0690ecb8dfa3..bc4cab976bf9 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h @@ -15,6 +15,7 @@ #ifdef CONFIG_PCI_IOV void ixgbe_restore_vf_multicasts(struct ixgbe_adapter *adapter); #endif +bool ixgbe_check_mdd_event(struct ixgbe_adapter *adapter); void ixgbe_msg_task(struct ixgbe_adapter *adapter); int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask); void ixgbe_ping_all_vfs(struct ixgbe_adapter *adapter); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index 892fa6c1f879..36577091cd9e 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -238,7 +238,7 @@ struct ixgbe_thermal_sensor_data { #define NVM_VER_INVALID 0xFFFF #define NVM_ETK_VALID 0x8000 #define NVM_INVALID_PTR 0xFFFF -#define NVM_VER_SIZE 32 /* version sting size */ +#define NVM_VER_SIZE 32 /* version string size */ struct ixgbe_nvm_version { u32 etk_id; @@ -402,6 +402,8 @@ struct ixgbe_nvm_version { #define IXGBE_MRCTL(_i) (0x0F600 + ((_i) * 4)) #define IXGBE_VMRVLAN(_i) (0x0F610 + ((_i) * 4)) #define IXGBE_VMRVM(_i) (0x0F630 + ((_i) * 4)) +#define IXGBE_LVMMC_RX 0x2FA8 +#define IXGBE_LVMMC_TX 0x8108 #define IXGBE_WQBR_RX(_i) (0x2FB0 + ((_i) * 4)) /* 4 total */ #define IXGBE_WQBR_TX(_i) (0x8130 + ((_i) * 4)) /* 4 total */ #define IXGBE_L34T_IMIR(_i) (0x0E800 + ((_i) * 4)) /*128 of these (0-127)*/ @@ -1042,6 +1044,7 @@ struct ixgbe_nvm_version { #define IXGBE_GCR_EXT_VT_MODE_16 0x00000001 #define IXGBE_GCR_EXT_VT_MODE_32 0x00000002 #define IXGBE_GCR_EXT_VT_MODE_64 0x00000003 +#define IXGBE_GCR_EXT_VT_MODE_MASK 0x00000003 #define IXGBE_GCR_EXT_SRIOV (IXGBE_GCR_EXT_MSIX_EN | \ IXGBE_GCR_EXT_VT_MODE_64) @@ -2021,7 +2024,7 @@ enum { /* 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_EERD_MAX_ADDR 0x00003FFF /* EERD alows 14 bits for addr. */ +#define IXGBE_EERD_MAX_ADDR 0x00003FFF /* EERD allows 14 bits for addr. */ #define IXGBE_EEC_SIZE_SHIFT 11 #define IXGBE_EEPROM_WORD_SIZE_SHIFT 6 @@ -2746,6 +2749,28 @@ enum ixgbe_fdir_pballoc_type { #define FW_PHY_INFO_ID_HI_MASK 0xFFFF0000u #define FW_PHY_INFO_ID_LO_MASK 0x0000FFFFu +/* There are only 3 options for VFs creation on this device: + * 16 VFs pool with 8 queues each + * 32 VFs pool with 4 queues each + * 64 VFs pool with 2 queues each + * + * That means reading some VF registers that map VF to queue depending on + * chosen option. Define values that help dealing with each scenario. + */ +/* Number of queues based on VFs pool */ +#define IXGBE_16VFS_QUEUES 8 +#define IXGBE_32VFS_QUEUES 4 +#define IXGBE_64VFS_QUEUES 2 +/* Mask for getting queues bits based on VFs pool */ +#define IXGBE_16VFS_BITMASK GENMASK(IXGBE_16VFS_QUEUES - 1, 0) +#define IXGBE_32VFS_BITMASK GENMASK(IXGBE_32VFS_QUEUES - 1, 0) +#define IXGBE_64VFS_BITMASK GENMASK(IXGBE_64VFS_QUEUES - 1, 0) +/* Convert queue index to register number. + * We have 4 registers with 32 queues in each. + */ +#define IXGBE_QUEUES_PER_REG 32 +#define IXGBE_QUEUES_REG_AMOUNT 4 + /* Host Interface Command Structures */ struct ixgbe_hic_hdr { u8 cmd; @@ -2911,6 +2936,13 @@ struct ixgbe_adv_tx_context_desc { __le32 mss_l4len_idx; }; +enum { + IXGBE_VLAN_MACIP_LENS_REG = 0, + IXGBE_FCEOF_SAIDX_REG = 1, + IXGBE_TYPE_TUCMD_MLHL = 2, + IXGBE_MSS_L4LEN_IDX = 3, +}; + /* Adv Transmit Descriptor Config Masks */ #define IXGBE_ADVTXD_DTALEN_MASK 0x0000FFFF /* Data buf length(bytes) */ #define IXGBE_ADVTXD_MAC_LINKSEC 0x00040000 /* Insert LinkSec */ @@ -2918,7 +2950,7 @@ struct ixgbe_adv_tx_context_desc { #define IXGBE_ADVTXD_IPSEC_SA_INDEX_MASK 0x000003FF /* IPSec SA index */ #define IXGBE_ADVTXD_IPSEC_ESP_LEN_MASK 0x000001FF /* IPSec ESP length */ #define IXGBE_ADVTXD_DTYP_MASK 0x00F00000 /* DTYP mask */ -#define IXGBE_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Desc */ +#define IXGBE_ADVTXD_DTYP_CTXT 0x2 /* Advanced Context Desc */ #define IXGBE_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */ #define IXGBE_ADVTXD_DCMD_EOP IXGBE_TXD_CMD_EOP /* End of Packet */ #define IXGBE_ADVTXD_DCMD_IFCS IXGBE_TXD_CMD_IFCS /* Insert FCS */ @@ -2967,6 +2999,8 @@ struct ixgbe_adv_tx_context_desc { #define IXGBE_ADVTXD_FCOEF_EOF_MASK (3u << 10) /* FC EOF index */ #define IXGBE_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */ #define IXGBE_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */ +#define IXGBE_ADVTXD_MSS_MASK GENMASK(31, IXGBE_ADVTXD_MSS_SHIFT) +#define IXGBE_ADVTXD_HEADER_LEN_MASK GENMASK(8, 0) /* Autonegotiation advertised speeds */ typedef u32 ixgbe_autoneg_advertised; @@ -3539,6 +3573,12 @@ struct ixgbe_mac_operations { int (*dmac_config_tcs)(struct ixgbe_hw *hw); int (*read_iosf_sb_reg)(struct ixgbe_hw *, u32, u32, u32 *); int (*write_iosf_sb_reg)(struct ixgbe_hw *, u32, u32, u32); + + /* MDD events */ + void (*enable_mdd)(struct ixgbe_hw *hw); + void (*disable_mdd)(struct ixgbe_hw *hw); + void (*restore_mdd_vf)(struct ixgbe_hw *hw, u32 vf); + void (*handle_mdd)(struct ixgbe_hw *hw, unsigned long *vf_bitmap); }; struct ixgbe_phy_operations { diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c index f1ab95aa8c83..c2353aed0120 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c @@ -47,7 +47,7 @@ int ixgbe_get_invariants_X540(struct ixgbe_hw *hw) } /** - * ixgbe_setup_mac_link_X540 - Set the auto advertised capabilitires + * ixgbe_setup_mac_link_X540 - Set the auto advertised capabilities * @hw: pointer to hardware structure * @speed: new link speed * @autoneg_wait_to_complete: true when waiting for completion is needed diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index 7461367a1868..bfa647086c70 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -3316,7 +3316,7 @@ static enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw) return media_type; } -/** ixgbe_init_ext_t_x550em - Start (unstall) the external Base T PHY. +/** ixgbe_init_ext_t_x550em - Start (uninstall) the external Base T PHY. ** @hw: pointer to hardware structure **/ static int ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw) @@ -3800,6 +3800,122 @@ static int ixgbe_write_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, return status; } +static void ixgbe_set_mdd_x550(struct ixgbe_hw *hw, bool ena) +{ + u32 reg_dma, reg_rdr; + + reg_dma = IXGBE_READ_REG(hw, IXGBE_DMATXCTL); + reg_rdr = IXGBE_READ_REG(hw, IXGBE_RDRXCTL); + + if (ena) { + reg_dma |= (IXGBE_DMATXCTL_MDP_EN | IXGBE_DMATXCTL_MBINTEN); + reg_rdr |= (IXGBE_RDRXCTL_MDP_EN | IXGBE_RDRXCTL_MBINTEN); + } else { + reg_dma &= ~(IXGBE_DMATXCTL_MDP_EN | IXGBE_DMATXCTL_MBINTEN); + reg_rdr &= ~(IXGBE_RDRXCTL_MDP_EN | IXGBE_RDRXCTL_MBINTEN); + } + + IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, reg_dma); + IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, reg_rdr); +} + +/** + * ixgbe_enable_mdd_x550 - enable malicious driver detection + * @hw: pointer to hardware structure + */ +void ixgbe_enable_mdd_x550(struct ixgbe_hw *hw) +{ + ixgbe_set_mdd_x550(hw, true); +} + +/** + * ixgbe_disable_mdd_x550 - disable malicious driver detection + * @hw: pointer to hardware structure + */ +void ixgbe_disable_mdd_x550(struct ixgbe_hw *hw) +{ + ixgbe_set_mdd_x550(hw, false); +} + +/** + * ixgbe_restore_mdd_vf_x550 - restore VF that was disabled during MDD event + * @hw: pointer to hardware structure + * @vf: vf index + */ +void ixgbe_restore_mdd_vf_x550(struct ixgbe_hw *hw, u32 vf) +{ + u32 idx, reg, val, num_qs, start_q, bitmask; + + /* Map VF to queues */ + reg = IXGBE_READ_REG(hw, IXGBE_MRQC); + switch (reg & IXGBE_MRQC_MRQE_MASK) { + case IXGBE_MRQC_VMDQRT8TCEN: + num_qs = IXGBE_16VFS_QUEUES; + bitmask = IXGBE_16VFS_BITMASK; + break; + case IXGBE_MRQC_VMDQRSS32EN: + case IXGBE_MRQC_VMDQRT4TCEN: + num_qs = IXGBE_32VFS_QUEUES; + bitmask = IXGBE_32VFS_BITMASK; + break; + default: + num_qs = IXGBE_64VFS_QUEUES; + bitmask = IXGBE_64VFS_BITMASK; + break; + } + start_q = vf * num_qs; + + /* Release vf's queues by clearing WQBR_TX and WQBR_RX (RW1C) */ + idx = start_q / IXGBE_QUEUES_PER_REG; + val = bitmask << (start_q % IXGBE_QUEUES_PER_REG); + IXGBE_WRITE_REG(hw, IXGBE_WQBR_TX(idx), val); + IXGBE_WRITE_REG(hw, IXGBE_WQBR_RX(idx), val); +} + +/** + * ixgbe_handle_mdd_x550 - handle malicious driver detection event + * @hw: pointer to hardware structure + * @vf_bitmap: output vf bitmap of malicious vfs + */ +void ixgbe_handle_mdd_x550(struct ixgbe_hw *hw, unsigned long *vf_bitmap) +{ + u32 i, j, reg, q, div, vf; + unsigned long wqbr; + + /* figure out pool size for mapping to vf's */ + reg = IXGBE_READ_REG(hw, IXGBE_MRQC); + switch (reg & IXGBE_MRQC_MRQE_MASK) { + case IXGBE_MRQC_VMDQRT8TCEN: + div = IXGBE_16VFS_QUEUES; + break; + case IXGBE_MRQC_VMDQRSS32EN: + case IXGBE_MRQC_VMDQRT4TCEN: + div = IXGBE_32VFS_QUEUES; + break; + default: + div = IXGBE_64VFS_QUEUES; + break; + } + + /* Read WQBR_TX and WQBR_RX and check for malicious queues */ + for (i = 0; i < IXGBE_QUEUES_REG_AMOUNT; i++) { + wqbr = IXGBE_READ_REG(hw, IXGBE_WQBR_TX(i)) | + IXGBE_READ_REG(hw, IXGBE_WQBR_RX(i)); + if (!wqbr) + continue; + + /* Get malicious queue */ + for_each_set_bit(j, (unsigned long *)&wqbr, + IXGBE_QUEUES_PER_REG) { + /* Get queue from bitmask */ + q = j + (i * IXGBE_QUEUES_PER_REG); + /* Map queue to vf */ + vf = q / div; + set_bit(vf, vf_bitmap); + } + } +} + #define X550_COMMON_MAC \ .init_hw = &ixgbe_init_hw_generic, \ .start_hw = &ixgbe_start_hw_X540, \ @@ -3863,6 +3979,10 @@ static const struct ixgbe_mac_operations mac_ops_X550 = { .prot_autoc_write = prot_autoc_write_generic, .setup_fc = ixgbe_setup_fc_generic, .fc_autoneg = ixgbe_fc_autoneg, + .enable_mdd = ixgbe_enable_mdd_x550, + .disable_mdd = ixgbe_disable_mdd_x550, + .restore_mdd_vf = ixgbe_restore_mdd_vf_x550, + .handle_mdd = ixgbe_handle_mdd_x550, }; static const struct ixgbe_mac_operations mac_ops_X550EM_x = { diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.h index 3e4092f8da3e..2a11147fb1bc 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.h @@ -17,4 +17,9 @@ void ixgbe_set_source_address_pruning_x550(struct ixgbe_hw *hw, void ixgbe_set_ethertype_anti_spoofing_x550(struct ixgbe_hw *hw, bool enable, int vf); +void ixgbe_enable_mdd_x550(struct ixgbe_hw *hw); +void ixgbe_disable_mdd_x550(struct ixgbe_hw *hw); +void ixgbe_restore_mdd_vf_x550(struct ixgbe_hw *hw, u32 vf); +void ixgbe_handle_mdd_x550(struct ixgbe_hw *hw, unsigned long *vf_bitmap); + #endif /* _IXGBE_X550_H_ */ |
