Merge branch 'qed-ethtool-ops'
Yuval Mintz says: ==================== qede/qed: Implement various ethtool operations This series adds several new ethtool operations to qede: - {get, set}_channels - {get, set}_ringparam - set_phys_id - nway_reset - {get, set}_pauseparam As well as extending the qed APIs to support these commands. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
88308c01a2
@ -3993,6 +3993,8 @@ struct public_drv_mb {
|
||||
#define DRV_MSG_CODE_PHY_CORE_WRITE 0x000e0000
|
||||
#define DRV_MSG_CODE_SET_VERSION 0x000f0000
|
||||
|
||||
#define DRV_MSG_CODE_SET_LED_MODE 0x00200000
|
||||
|
||||
#define DRV_MSG_SEQ_NUMBER_MASK 0x0000ffff
|
||||
|
||||
u32 drv_mb_param;
|
||||
@ -4044,6 +4046,10 @@ struct public_drv_mb {
|
||||
#define DRV_MB_PARAM_CFG_VF_MSIX_SB_NUM_SHIFT 8
|
||||
#define DRV_MB_PARAM_CFG_VF_MSIX_SB_NUM_MASK 0x0000FF00
|
||||
|
||||
#define DRV_MB_PARAM_SET_LED_MODE_OPER 0x0
|
||||
#define DRV_MB_PARAM_SET_LED_MODE_ON 0x1
|
||||
#define DRV_MB_PARAM_SET_LED_MODE_OFF 0x2
|
||||
|
||||
u32 fw_mb_header;
|
||||
#define FW_MSG_CODE_MASK 0xffff0000
|
||||
#define FW_MSG_CODE_DRV_LOAD_ENGINE 0x10100000
|
||||
|
@ -1135,6 +1135,23 @@ static int qed_drain(struct qed_dev *cdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qed_set_led(struct qed_dev *cdev, enum qed_led_mode mode)
|
||||
{
|
||||
struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
|
||||
struct qed_ptt *ptt;
|
||||
int status = 0;
|
||||
|
||||
ptt = qed_ptt_acquire(hwfn);
|
||||
if (!ptt)
|
||||
return -EAGAIN;
|
||||
|
||||
status = qed_mcp_set_led(hwfn, ptt, mode);
|
||||
|
||||
qed_ptt_release(hwfn, ptt);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
const struct qed_common_ops qed_common_ops_pass = {
|
||||
.probe = &qed_probe,
|
||||
.remove = &qed_remove,
|
||||
@ -1155,6 +1172,7 @@ const struct qed_common_ops qed_common_ops_pass = {
|
||||
.update_msglvl = &qed_init_dp,
|
||||
.chain_alloc = &qed_chain_alloc,
|
||||
.chain_free = &qed_chain_free,
|
||||
.set_led = &qed_set_led,
|
||||
};
|
||||
|
||||
u32 qed_get_protocol_version(enum qed_protocol protocol)
|
||||
|
@ -858,3 +858,30 @@ qed_mcp_send_drv_version(struct qed_hwfn *p_hwfn,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qed_mcp_set_led(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
|
||||
enum qed_led_mode mode)
|
||||
{
|
||||
u32 resp = 0, param = 0, drv_mb_param;
|
||||
int rc;
|
||||
|
||||
switch (mode) {
|
||||
case QED_LED_MODE_ON:
|
||||
drv_mb_param = DRV_MB_PARAM_SET_LED_MODE_ON;
|
||||
break;
|
||||
case QED_LED_MODE_OFF:
|
||||
drv_mb_param = DRV_MB_PARAM_SET_LED_MODE_OFF;
|
||||
break;
|
||||
case QED_LED_MODE_RESTORE:
|
||||
drv_mb_param = DRV_MB_PARAM_SET_LED_MODE_OPER;
|
||||
break;
|
||||
default:
|
||||
DP_NOTICE(p_hwfn, "Invalid LED mode %d\n", mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_SET_LED_MODE,
|
||||
drv_mb_param, &resp, ¶m);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -224,6 +224,19 @@ qed_mcp_send_drv_version(struct qed_hwfn *p_hwfn,
|
||||
struct qed_ptt *p_ptt,
|
||||
struct qed_mcp_drv_version *p_ver);
|
||||
|
||||
/**
|
||||
* @brief Set LED status
|
||||
*
|
||||
* @param p_hwfn
|
||||
* @param p_ptt
|
||||
* @param mode - LED mode
|
||||
*
|
||||
* @return int - 0 - operation was successful.
|
||||
*/
|
||||
int qed_mcp_set_led(struct qed_hwfn *p_hwfn,
|
||||
struct qed_ptt *p_ptt,
|
||||
enum qed_led_mode mode);
|
||||
|
||||
/* Using hwfn number (and not pf_num) is required since in CMT mode,
|
||||
* same pf_num may be used by two different hwfn
|
||||
* TODO - this shouldn't really be in .h file, but until all fields
|
||||
|
@ -116,6 +116,7 @@ struct qede_dev {
|
||||
(edev)->dev_info.num_tc)
|
||||
|
||||
struct qede_fastpath *fp_array;
|
||||
u16 req_rss;
|
||||
u16 num_rss;
|
||||
u8 num_tc;
|
||||
#define QEDE_RSS_CNT(edev) ((edev)->num_rss)
|
||||
@ -269,13 +270,13 @@ int qede_change_mtu(struct net_device *dev, int new_mtu);
|
||||
void qede_fill_by_demand_stats(struct qede_dev *edev);
|
||||
|
||||
#define RX_RING_SIZE_POW 13
|
||||
#define RX_RING_SIZE BIT(RX_RING_SIZE_POW)
|
||||
#define RX_RING_SIZE ((u16)BIT(RX_RING_SIZE_POW))
|
||||
#define NUM_RX_BDS_MAX (RX_RING_SIZE - 1)
|
||||
#define NUM_RX_BDS_MIN 128
|
||||
#define NUM_RX_BDS_DEF NUM_RX_BDS_MAX
|
||||
|
||||
#define TX_RING_SIZE_POW 13
|
||||
#define TX_RING_SIZE BIT(TX_RING_SIZE_POW)
|
||||
#define TX_RING_SIZE ((u16)BIT(TX_RING_SIZE_POW))
|
||||
#define NUM_TX_BDS_MAX (TX_RING_SIZE - 1)
|
||||
#define NUM_TX_BDS_MIN 128
|
||||
#define NUM_TX_BDS_DEF NUM_TX_BDS_MAX
|
||||
|
@ -322,6 +322,30 @@ static void qede_set_msglevel(struct net_device *ndev, u32 level)
|
||||
dp_module, dp_level);
|
||||
}
|
||||
|
||||
static int qede_nway_reset(struct net_device *dev)
|
||||
{
|
||||
struct qede_dev *edev = netdev_priv(dev);
|
||||
struct qed_link_output current_link;
|
||||
struct qed_link_params link_params;
|
||||
|
||||
if (!netif_running(dev))
|
||||
return 0;
|
||||
|
||||
memset(¤t_link, 0, sizeof(current_link));
|
||||
edev->ops->common->get_link(edev->cdev, ¤t_link);
|
||||
if (!current_link.link_up)
|
||||
return 0;
|
||||
|
||||
/* Toggle the link */
|
||||
memset(&link_params, 0, sizeof(link_params));
|
||||
link_params.link_up = false;
|
||||
edev->ops->common->set_link(edev->cdev, &link_params);
|
||||
link_params.link_up = true;
|
||||
edev->ops->common->set_link(edev->cdev, &link_params);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 qede_get_link(struct net_device *dev)
|
||||
{
|
||||
struct qede_dev *edev = netdev_priv(dev);
|
||||
@ -333,6 +357,106 @@ static u32 qede_get_link(struct net_device *dev)
|
||||
return current_link.link_up;
|
||||
}
|
||||
|
||||
static void qede_get_ringparam(struct net_device *dev,
|
||||
struct ethtool_ringparam *ering)
|
||||
{
|
||||
struct qede_dev *edev = netdev_priv(dev);
|
||||
|
||||
ering->rx_max_pending = NUM_RX_BDS_MAX;
|
||||
ering->rx_pending = edev->q_num_rx_buffers;
|
||||
ering->tx_max_pending = NUM_TX_BDS_MAX;
|
||||
ering->tx_pending = edev->q_num_tx_buffers;
|
||||
}
|
||||
|
||||
static int qede_set_ringparam(struct net_device *dev,
|
||||
struct ethtool_ringparam *ering)
|
||||
{
|
||||
struct qede_dev *edev = netdev_priv(dev);
|
||||
|
||||
DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
|
||||
"Set ring params command parameters: rx_pending = %d, tx_pending = %d\n",
|
||||
ering->rx_pending, ering->tx_pending);
|
||||
|
||||
/* Validate legality of configuration */
|
||||
if (ering->rx_pending > NUM_RX_BDS_MAX ||
|
||||
ering->rx_pending < NUM_RX_BDS_MIN ||
|
||||
ering->tx_pending > NUM_TX_BDS_MAX ||
|
||||
ering->tx_pending < NUM_TX_BDS_MIN) {
|
||||
DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
|
||||
"Can only support Rx Buffer size [0%08x,...,0x%08x] and Tx Buffer size [0x%08x,...,0x%08x]\n",
|
||||
NUM_RX_BDS_MIN, NUM_RX_BDS_MAX,
|
||||
NUM_TX_BDS_MIN, NUM_TX_BDS_MAX);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Change ring size and re-load */
|
||||
edev->q_num_rx_buffers = ering->rx_pending;
|
||||
edev->q_num_tx_buffers = ering->tx_pending;
|
||||
|
||||
if (netif_running(edev->ndev))
|
||||
qede_reload(edev, NULL, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void qede_get_pauseparam(struct net_device *dev,
|
||||
struct ethtool_pauseparam *epause)
|
||||
{
|
||||
struct qede_dev *edev = netdev_priv(dev);
|
||||
struct qed_link_output current_link;
|
||||
|
||||
memset(¤t_link, 0, sizeof(current_link));
|
||||
edev->ops->common->get_link(edev->cdev, ¤t_link);
|
||||
|
||||
if (current_link.pause_config & QED_LINK_PAUSE_AUTONEG_ENABLE)
|
||||
epause->autoneg = true;
|
||||
if (current_link.pause_config & QED_LINK_PAUSE_RX_ENABLE)
|
||||
epause->rx_pause = true;
|
||||
if (current_link.pause_config & QED_LINK_PAUSE_TX_ENABLE)
|
||||
epause->tx_pause = true;
|
||||
|
||||
DP_VERBOSE(edev, QED_MSG_DEBUG,
|
||||
"ethtool_pauseparam: cmd %d autoneg %d rx_pause %d tx_pause %d\n",
|
||||
epause->cmd, epause->autoneg, epause->rx_pause,
|
||||
epause->tx_pause);
|
||||
}
|
||||
|
||||
static int qede_set_pauseparam(struct net_device *dev,
|
||||
struct ethtool_pauseparam *epause)
|
||||
{
|
||||
struct qede_dev *edev = netdev_priv(dev);
|
||||
struct qed_link_params params;
|
||||
struct qed_link_output current_link;
|
||||
|
||||
if (!edev->dev_info.common.is_mf) {
|
||||
DP_INFO(edev,
|
||||
"Pause parameters can not be updated in non-default mode\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
memset(¤t_link, 0, sizeof(current_link));
|
||||
edev->ops->common->get_link(edev->cdev, ¤t_link);
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
params.override_flags |= QED_LINK_OVERRIDE_PAUSE_CONFIG;
|
||||
if (epause->autoneg) {
|
||||
if (!(current_link.supported_caps & SUPPORTED_Autoneg)) {
|
||||
DP_INFO(edev, "autoneg not supported\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
params.pause_config |= QED_LINK_PAUSE_AUTONEG_ENABLE;
|
||||
}
|
||||
if (epause->rx_pause)
|
||||
params.pause_config |= QED_LINK_PAUSE_RX_ENABLE;
|
||||
if (epause->tx_pause)
|
||||
params.pause_config |= QED_LINK_PAUSE_TX_ENABLE;
|
||||
|
||||
params.link_up = true;
|
||||
edev->ops->common->set_link(edev->cdev, ¶ms);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void qede_update_mtu(struct qede_dev *edev, union qede_reload_args *args)
|
||||
{
|
||||
edev->ndev->mtu = args->mtu;
|
||||
@ -366,17 +490,104 @@ int qede_change_mtu(struct net_device *ndev, int new_mtu)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void qede_get_channels(struct net_device *dev,
|
||||
struct ethtool_channels *channels)
|
||||
{
|
||||
struct qede_dev *edev = netdev_priv(dev);
|
||||
|
||||
channels->max_combined = QEDE_MAX_RSS_CNT(edev);
|
||||
channels->combined_count = QEDE_RSS_CNT(edev);
|
||||
}
|
||||
|
||||
static int qede_set_channels(struct net_device *dev,
|
||||
struct ethtool_channels *channels)
|
||||
{
|
||||
struct qede_dev *edev = netdev_priv(dev);
|
||||
|
||||
DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
|
||||
"set-channels command parameters: rx = %d, tx = %d, other = %d, combined = %d\n",
|
||||
channels->rx_count, channels->tx_count,
|
||||
channels->other_count, channels->combined_count);
|
||||
|
||||
/* We don't support separate rx / tx, nor `other' channels. */
|
||||
if (channels->rx_count || channels->tx_count ||
|
||||
channels->other_count || (channels->combined_count == 0) ||
|
||||
(channels->combined_count > QEDE_MAX_RSS_CNT(edev))) {
|
||||
DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
|
||||
"command parameters not supported\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Check if there was a change in the active parameters */
|
||||
if (channels->combined_count == QEDE_RSS_CNT(edev)) {
|
||||
DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
|
||||
"No change in active parameters\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We need the number of queues to be divisible between the hwfns */
|
||||
if (channels->combined_count % edev->dev_info.common.num_hwfns) {
|
||||
DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
|
||||
"Number of channels must be divisable by %04x\n",
|
||||
edev->dev_info.common.num_hwfns);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Set number of queues and reload if necessary */
|
||||
edev->req_rss = channels->combined_count;
|
||||
if (netif_running(dev))
|
||||
qede_reload(edev, NULL, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qede_set_phys_id(struct net_device *dev,
|
||||
enum ethtool_phys_id_state state)
|
||||
{
|
||||
struct qede_dev *edev = netdev_priv(dev);
|
||||
u8 led_state = 0;
|
||||
|
||||
switch (state) {
|
||||
case ETHTOOL_ID_ACTIVE:
|
||||
return 1; /* cycle on/off once per second */
|
||||
|
||||
case ETHTOOL_ID_ON:
|
||||
led_state = QED_LED_MODE_ON;
|
||||
break;
|
||||
|
||||
case ETHTOOL_ID_OFF:
|
||||
led_state = QED_LED_MODE_OFF;
|
||||
break;
|
||||
|
||||
case ETHTOOL_ID_INACTIVE:
|
||||
led_state = QED_LED_MODE_RESTORE;
|
||||
break;
|
||||
}
|
||||
|
||||
edev->ops->common->set_led(edev->cdev, led_state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ethtool_ops qede_ethtool_ops = {
|
||||
.get_settings = qede_get_settings,
|
||||
.set_settings = qede_set_settings,
|
||||
.get_drvinfo = qede_get_drvinfo,
|
||||
.get_msglevel = qede_get_msglevel,
|
||||
.set_msglevel = qede_set_msglevel,
|
||||
.nway_reset = qede_nway_reset,
|
||||
.get_link = qede_get_link,
|
||||
.get_ringparam = qede_get_ringparam,
|
||||
.set_ringparam = qede_set_ringparam,
|
||||
.get_pauseparam = qede_get_pauseparam,
|
||||
.set_pauseparam = qede_set_pauseparam,
|
||||
.get_strings = qede_get_strings,
|
||||
.set_phys_id = qede_set_phys_id,
|
||||
.get_ethtool_stats = qede_get_ethtool_stats,
|
||||
.get_sset_count = qede_get_sset_count,
|
||||
|
||||
.get_channels = qede_get_channels,
|
||||
.set_channels = qede_set_channels,
|
||||
};
|
||||
|
||||
void qede_set_ethtool_ops(struct net_device *dev)
|
||||
|
@ -1502,8 +1502,11 @@ static int qede_set_num_queues(struct qede_dev *edev)
|
||||
u16 rss_num;
|
||||
|
||||
/* Setup queues according to possible resources*/
|
||||
rss_num = netif_get_num_default_rss_queues() *
|
||||
edev->dev_info.common.num_hwfns;
|
||||
if (edev->req_rss)
|
||||
rss_num = edev->req_rss;
|
||||
else
|
||||
rss_num = netif_get_num_default_rss_queues() *
|
||||
edev->dev_info.common.num_hwfns;
|
||||
|
||||
rss_num = min_t(u16, QEDE_MAX_RSS_CNT(edev), rss_num);
|
||||
|
||||
|
@ -25,6 +25,12 @@
|
||||
#include <linux/qed/common_hsi.h>
|
||||
#include <linux/qed/qed_chain.h>
|
||||
|
||||
enum qed_led_mode {
|
||||
QED_LED_MODE_OFF,
|
||||
QED_LED_MODE_ON,
|
||||
QED_LED_MODE_RESTORE
|
||||
};
|
||||
|
||||
#define DIRECT_REG_WR(reg_addr, val) writel((u32)val, \
|
||||
(void __iomem *)(reg_addr))
|
||||
|
||||
@ -252,6 +258,17 @@ struct qed_common_ops {
|
||||
|
||||
void (*chain_free)(struct qed_dev *cdev,
|
||||
struct qed_chain *p_chain);
|
||||
|
||||
/**
|
||||
* @brief set_led - Configure LED mode
|
||||
*
|
||||
* @param cdev
|
||||
* @param mode - LED mode
|
||||
*
|
||||
* @return 0 on success, error otherwise.
|
||||
*/
|
||||
int (*set_led)(struct qed_dev *cdev,
|
||||
enum qed_led_mode mode);
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user