Skip to content

Commit

Permalink
ice: Add stats and ethtool support
Browse files Browse the repository at this point in the history
This patch implements a watchdog task to get packet statistics from
the device.

This patch also adds support for the following ethtool operations:

ethtool devname
ethtool -s devname [msglvl N] [msglevel type on|off]
ethtool -g|--show-ring devname
ethtool -G|--set-ring devname [rx N] [tx N]
ethtool -i|--driver devname
ethtool -d|--register-dump devname [raw on|off] [hex on|off] [file name]
ethtool -k|--show-features|--show-offload devname
ethtool -K|--features|--offload devname feature on|off
ethtool -P|--show-permaddr devname
ethtool -S|--statistics devname
ethtool -a|--show-pause devname
ethtool -A|--pause devname [autoneg on|off] [rx on|off] [tx on|off]
ethtool -r|--negotiate devname

CC: Andrew Lunn <andrew@lunn.ch>
CC: Jakub Kicinski <kubakici@wp.pl>
CC: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: Anirudh Venkataramanan <anirudh.venkataramanan@intel.com>
Acked-by: Stephen Hemminger <stephen@networkplumber.org>
Tested-by: Tony Brelinski <tonyx.brelinski@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
  • Loading branch information
refactorman authored and Jeff Kirsher committed Mar 26, 2018
1 parent d76a60b commit fcea6f3
Show file tree
Hide file tree
Showing 9 changed files with 1,828 additions and 5 deletions.
3 changes: 2 additions & 1 deletion drivers/net/ethernet/intel/ice/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ ice-y := ice_main.o \
ice_nvm.o \
ice_switch.o \
ice_sched.o \
ice_txrx.o
ice_txrx.o \
ice_ethtool.o
28 changes: 27 additions & 1 deletion drivers/net/ethernet/intel/ice/ice.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/cpumask.h>
#include <linux/rtnetlink.h>
#include <linux/if_vlan.h>
#include <linux/dma-mapping.h>
#include <linux/pci.h>
#include <linux/workqueue.h>
#include <linux/aer.h>
#include <linux/interrupt.h>
#include <linux/ethtool.h>
#include <linux/timer.h>
#include <linux/delay.h>
#include <linux/bitmap.h>
Expand All @@ -34,10 +36,14 @@
#include "ice_common.h"
#include "ice_sched.h"

extern const char ice_drv_ver[];
#define ICE_BAR0 0
#define ICE_DFLT_NUM_DESC 128
#define ICE_MIN_NUM_DESC 8
#define ICE_MAX_NUM_DESC 8160
#define ICE_REQ_DESC_MULTIPLE 32
#define ICE_INT_NAME_STR_LEN (IFNAMSIZ + 16)
#define ICE_ETHTOOL_FWVER_LEN 32
#define ICE_AQ_LEN 64
#define ICE_MIN_MSIX 2
#define ICE_NO_VSI 0xffff
Expand All @@ -56,6 +62,8 @@
#define ICE_RES_MISC_VEC_ID (ICE_RES_VALID_BIT - 1)
#define ICE_INVAL_Q_INDEX 0xffff

#define ICE_VSIQF_HKEY_ARRAY_SIZE ((VSIQF_HKEY_MAX_INDEX + 1) * 4)

#define ICE_DFLT_NETIF_M (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK)

#define ICE_MAX_MTU (ICE_AQ_SET_MAC_FRAME_SIZE_MAX - \
Expand Down Expand Up @@ -102,6 +110,7 @@ enum ice_state {
__ICE_DOWN,
__ICE_PFR_REQ, /* set by driver and peers */
__ICE_ADMINQ_EVENT_PENDING,
__ICE_CFG_BUSY,
__ICE_SERVICE_SCHED,
__ICE_STATE_NBITS /* must be last */
};
Expand All @@ -118,8 +127,13 @@ struct ice_vsi {

irqreturn_t (*irq_handler)(int irq, void *data);

u64 tx_linearize;
DECLARE_BITMAP(state, __ICE_STATE_NBITS);
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
u32 tx_restart;
u32 tx_busy;
u32 rx_buf_failed;
u32 rx_page_failed;
int num_q_vectors;
int base_vector;
enum ice_vsi_type type;
Expand All @@ -141,8 +155,14 @@ struct ice_vsi {

struct ice_aqc_vsi_props info; /* VSI properties */

/* VSI stats */
struct rtnl_link_stats64 net_stats;
struct ice_eth_stats eth_stats;
struct ice_eth_stats eth_stats_prev;

bool irqs_ready;
bool current_isup; /* Sync 'link up' logging */
bool stat_offsets_loaded;

/* queue information */
u8 tx_mapping_mode; /* ICE_MAP_MODE_[CONTIG|SCATTER] */
Expand Down Expand Up @@ -205,8 +225,10 @@ struct ice_pf {
u16 q_left_rx; /* remaining num rx queues left unclaimed */
u16 next_vsi; /* Next free slot in pf->vsi[] - 0-based! */
u16 num_alloc_vsi;

struct ice_hw_port_stats stats;
struct ice_hw_port_stats stats_prev;
struct ice_hw hw;
bool stat_prev_loaded; /* has previous stats been loaded */
char int_name[ICE_INT_NAME_STR_LEN];
};

Expand Down Expand Up @@ -239,8 +261,12 @@ static inline void ice_irq_dynamic_ena(struct ice_hw *hw, struct ice_vsi *vsi,
wr32(hw, GLINT_DYN_CTL(vector), val);
}

void ice_set_ethtool_ops(struct net_device *netdev);
int ice_up(struct ice_vsi *vsi);
int ice_down(struct ice_vsi *vsi);
int ice_set_rss(struct ice_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size);
int ice_get_rss(struct ice_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size);
void ice_fill_rss_lut(u8 *lut, u16 rss_table_size, u16 rss_size);
void ice_print_link_msg(struct ice_vsi *vsi, bool isup);

#endif /* _ICE_H_ */
43 changes: 43 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,45 @@ struct ice_aqc_get_phy_caps_data {
} qual_modules[ICE_AQC_QUAL_MOD_COUNT_MAX];
};

/* Set PHY capabilities (direct 0x0601)
* NOTE: This command must be followed by setup link and restart auto-neg
*/
struct ice_aqc_set_phy_cfg {
u8 lport_num;
u8 reserved[7];
__le32 addr_high;
__le32 addr_low;
};

/* Set PHY config command data structure */
struct ice_aqc_set_phy_cfg_data {
__le64 phy_type_low; /* Use values from ICE_PHY_TYPE_LOW_* */
__le64 rsvd0;
u8 caps;
#define ICE_AQ_PHY_ENA_TX_PAUSE_ABILITY BIT(0)
#define ICE_AQ_PHY_ENA_RX_PAUSE_ABILITY BIT(1)
#define ICE_AQ_PHY_ENA_LOW_POWER BIT(2)
#define ICE_AQ_PHY_ENA_LINK BIT(3)
#define ICE_AQ_PHY_ENA_ATOMIC_LINK BIT(5)
u8 low_power_ctrl;
__le16 eee_cap; /* Value from ice_aqc_get_phy_caps */
__le16 eeer_value;
u8 link_fec_opt; /* Use defines from ice_aqc_get_phy_caps */
u8 rsvd1;
};

/* Restart AN command data structure (direct 0x0605)
* Also used for response, with only the lport_num field present.
*/
struct ice_aqc_restart_an {
u8 lport_num;
u8 reserved;
u8 cmd_flags;
#define ICE_AQC_RESTART_AN_LINK_RESTART BIT(1)
#define ICE_AQC_RESTART_AN_LINK_ENABLE BIT(2)
u8 reserved2[13];
};

/* Get link status (indirect 0x0607), also used for Link Status Event */
struct ice_aqc_get_link_status {
u8 lport_num;
Expand Down Expand Up @@ -1137,6 +1176,8 @@ struct ice_aq_desc {
struct ice_aqc_clear_pxe clear_pxe;
struct ice_aqc_list_caps get_cap;
struct ice_aqc_get_phy_caps get_phy;
struct ice_aqc_set_phy_cfg set_phy;
struct ice_aqc_restart_an restart_an;
struct ice_aqc_get_sw_cfg get_sw_conf;
struct ice_aqc_sw_rules sw_rules;
struct ice_aqc_get_topo get_topo;
Expand Down Expand Up @@ -1222,6 +1263,8 @@ enum ice_adminq_opc {

/* PHY commands */
ice_aqc_opc_get_phy_caps = 0x0600,
ice_aqc_opc_set_phy_cfg = 0x0601,
ice_aqc_opc_restart_an = 0x0605,
ice_aqc_opc_get_link_status = 0x0607,

/* NVM commands */
Expand Down
195 changes: 195 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -1261,6 +1261,201 @@ void ice_clear_pxe_mode(struct ice_hw *hw)
ice_aq_clear_pxe_mode(hw);
}

/**
* ice_aq_set_phy_cfg
* @hw: pointer to the hw struct
* @lport: logical port number
* @cfg: structure with PHY configuration data to be set
* @cd: pointer to command details structure or NULL
*
* Set the various PHY configuration parameters supported on the Port.
* One or more of the Set PHY config parameters may be ignored in an MFP
* mode as the PF may not have the privilege to set some of the PHY Config
* parameters. This status will be indicated by the command response (0x0601).
*/
static enum ice_status
ice_aq_set_phy_cfg(struct ice_hw *hw, u8 lport,
struct ice_aqc_set_phy_cfg_data *cfg, struct ice_sq_cd *cd)
{
struct ice_aqc_set_phy_cfg *cmd;
struct ice_aq_desc desc;

if (!cfg)
return ICE_ERR_PARAM;

cmd = &desc.params.set_phy;
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_phy_cfg);
cmd->lport_num = lport;

return ice_aq_send_cmd(hw, &desc, cfg, sizeof(*cfg), cd);
}

/**
* ice_update_link_info - update status of the HW network link
* @pi: port info structure of the interested logical port
*/
static enum ice_status
ice_update_link_info(struct ice_port_info *pi)
{
struct ice_aqc_get_phy_caps_data *pcaps;
struct ice_phy_info *phy_info;
enum ice_status status;
struct ice_hw *hw;

if (!pi)
return ICE_ERR_PARAM;

hw = pi->hw;

pcaps = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*pcaps), GFP_KERNEL);
if (!pcaps)
return ICE_ERR_NO_MEMORY;

phy_info = &pi->phy;
status = ice_aq_get_link_info(pi, true, NULL, NULL);
if (status)
goto out;

if (phy_info->link_info.link_info & ICE_AQ_MEDIA_AVAILABLE) {
status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_SW_CFG,
pcaps, NULL);
if (status)
goto out;

memcpy(phy_info->link_info.module_type, &pcaps->module_type,
sizeof(phy_info->link_info.module_type));
}
out:
devm_kfree(ice_hw_to_dev(hw), pcaps);
return status;
}

/**
* ice_set_fc
* @pi: port information structure
* @aq_failures: pointer to status code, specific to ice_set_fc routine
* @atomic_restart: enable automatic link update
*
* Set the requested flow control mode.
*/
enum ice_status
ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool atomic_restart)
{
struct ice_aqc_set_phy_cfg_data cfg = { 0 };
struct ice_aqc_get_phy_caps_data *pcaps;
enum ice_status status;
u8 pause_mask = 0x0;
struct ice_hw *hw;

if (!pi)
return ICE_ERR_PARAM;
hw = pi->hw;
*aq_failures = ICE_SET_FC_AQ_FAIL_NONE;

switch (pi->fc.req_mode) {
case ICE_FC_FULL:
pause_mask |= ICE_AQC_PHY_EN_TX_LINK_PAUSE;
pause_mask |= ICE_AQC_PHY_EN_RX_LINK_PAUSE;
break;
case ICE_FC_RX_PAUSE:
pause_mask |= ICE_AQC_PHY_EN_RX_LINK_PAUSE;
break;
case ICE_FC_TX_PAUSE:
pause_mask |= ICE_AQC_PHY_EN_TX_LINK_PAUSE;
break;
default:
break;
}

pcaps = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*pcaps), GFP_KERNEL);
if (!pcaps)
return ICE_ERR_NO_MEMORY;

/* Get the current phy config */
status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_SW_CFG, pcaps,
NULL);
if (status) {
*aq_failures = ICE_SET_FC_AQ_FAIL_GET;
goto out;
}

/* clear the old pause settings */
cfg.caps = pcaps->caps & ~(ICE_AQC_PHY_EN_TX_LINK_PAUSE |
ICE_AQC_PHY_EN_RX_LINK_PAUSE);
/* set the new capabilities */
cfg.caps |= pause_mask;
/* If the capabilities have changed, then set the new config */
if (cfg.caps != pcaps->caps) {
int retry_count, retry_max = 10;

/* Auto restart link so settings take effect */
if (atomic_restart)
cfg.caps |= ICE_AQ_PHY_ENA_ATOMIC_LINK;
/* Copy over all the old settings */
cfg.phy_type_low = pcaps->phy_type_low;
cfg.low_power_ctrl = pcaps->low_power_ctrl;
cfg.eee_cap = pcaps->eee_cap;
cfg.eeer_value = pcaps->eeer_value;
cfg.link_fec_opt = pcaps->link_fec_options;

status = ice_aq_set_phy_cfg(hw, pi->lport, &cfg, NULL);
if (status) {
*aq_failures = ICE_SET_FC_AQ_FAIL_SET;
goto out;
}

/* Update the link info
* It sometimes takes a really long time for link to
* come back from the atomic reset. Thus, we wait a
* little bit.
*/
for (retry_count = 0; retry_count < retry_max; retry_count++) {
status = ice_update_link_info(pi);

if (!status)
break;

mdelay(100);
}

if (status)
*aq_failures = ICE_SET_FC_AQ_FAIL_UPDATE;
}

out:
devm_kfree(ice_hw_to_dev(hw), pcaps);
return status;
}

/**
* ice_aq_set_link_restart_an
* @pi: pointer to the port information structure
* @ena_link: if true: enable link, if false: disable link
* @cd: pointer to command details structure or NULL
*
* Sets up the link and restarts the Auto-Negotiation over the link.
*/
enum ice_status
ice_aq_set_link_restart_an(struct ice_port_info *pi, bool ena_link,
struct ice_sq_cd *cd)
{
struct ice_aqc_restart_an *cmd;
struct ice_aq_desc desc;

cmd = &desc.params.restart_an;

ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_restart_an);

cmd->cmd_flags = ICE_AQC_RESTART_AN_LINK_RESTART;
cmd->lport_num = pi->lport;
if (ena_link)
cmd->cmd_flags |= ICE_AQC_RESTART_AN_LINK_ENABLE;
else
cmd->cmd_flags &= ~ICE_AQC_RESTART_AN_LINK_ENABLE;

return ice_aq_send_cmd(pi->hw, &desc, NULL, 0, cd);
}

/**
* __ice_aq_get_set_rss_lut
* @hw: pointer to the hardware structure
Expand Down
5 changes: 5 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ ice_aq_send_cmd(struct ice_hw *hw, struct ice_aq_desc *desc,
enum ice_status ice_aq_get_fw_ver(struct ice_hw *hw, struct ice_sq_cd *cd);
enum ice_status ice_clear_pf_cfg(struct ice_hw *hw);
enum ice_status
ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool atomic_restart);
enum ice_status
ice_aq_set_link_restart_an(struct ice_port_info *pi, bool ena_link,
struct ice_sq_cd *cd);
enum ice_status
ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse,
struct ice_link_status *link, struct ice_sq_cd *cd);
enum ice_status
Expand Down
Loading

0 comments on commit fcea6f3

Please sign in to comment.