Skip to content

Commit

Permalink
Merge branch 'bnxt_en-next'
Browse files Browse the repository at this point in the history
Michael Chan says:

====================
bnxt_en: Updates for net-next.

Update to latest firmware interface, add EEE feature, unsupported SFP+
module warning, and ethtool -s improvements.

v2: Removed the GEEPROM patch and added more comments to the get_eee patch.
====================
  • Loading branch information
David S. Miller committed Apr 5, 2016
2 parents 04c85bf + 29c262f commit f1cc809
Show file tree
Hide file tree
Showing 9 changed files with 803 additions and 95 deletions.
259 changes: 237 additions & 22 deletions drivers/net/ethernet/broadcom/bnxt/bnxt.c

Large diffs are not rendered by default.

17 changes: 12 additions & 5 deletions drivers/net/ethernet/broadcom/bnxt/bnxt.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* Broadcom NetXtreme-C/E network driver.
*
* Copyright (c) 2014-2015 Broadcom Corporation
* Copyright (c) 2014-2016 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand All @@ -11,7 +11,7 @@
#define BNXT_H

#define DRV_MODULE_NAME "bnxt_en"
#define DRV_MODULE_VERSION "1.0.0"
#define DRV_MODULE_VERSION "1.2.0"

#define DRV_VER_MAJ 1
#define DRV_VER_MIN 0
Expand Down Expand Up @@ -788,7 +788,7 @@ struct bnxt_link_info {
#define BNXT_LINK_AUTO_ALLSPDS PORT_PHY_QCFG_RESP_AUTO_MODE_ALL_SPEEDS
#define BNXT_LINK_AUTO_ONESPD PORT_PHY_QCFG_RESP_AUTO_MODE_ONE_SPEED
#define BNXT_LINK_AUTO_ONEORBELOW PORT_PHY_QCFG_RESP_AUTO_MODE_ONE_OR_BELOW
#define BNXT_LINK_AUTO_MSK PORT_PHY_QCFG_RESP_AUTO_MODE_MASK
#define BNXT_LINK_AUTO_MSK PORT_PHY_QCFG_RESP_AUTO_MODE_SPEED_MASK
#define PHY_VER_LEN 3
u8 phy_ver[PHY_VER_LEN];
u16 link_speed;
Expand All @@ -813,7 +813,6 @@ struct bnxt_link_info {
#define BNXT_LINK_SPEED_MSK_40GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_40GB
#define BNXT_LINK_SPEED_MSK_50GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_50GB
u16 lp_auto_link_speeds;
u16 auto_link_speed;
u16 force_link_speed;
u32 preemphasis;

Expand All @@ -826,6 +825,8 @@ struct bnxt_link_info {
u16 req_link_speed;
u32 advertising;
bool force_link_chng;

u8 last_port_module_event;
/* a copy of phy_qcfg output used to report link
* info to VF
*/
Expand Down Expand Up @@ -875,6 +876,7 @@ struct bnxt {
#define BNXT_FLAG_RFS 0x100
#define BNXT_FLAG_SHARED_RINGS 0x200
#define BNXT_FLAG_PORT_STATS 0x400
#define BNXT_FLAG_EEE_CAP 0x1000

#define BNXT_FLAG_ALL_CONFIG_FEATS (BNXT_FLAG_TPA | \
BNXT_FLAG_RFS | \
Expand Down Expand Up @@ -940,6 +942,7 @@ struct bnxt {

u32 msg_enable;

u32 hwrm_spec_code;
u16 hwrm_cmd_seq;
u32 hwrm_intr_seq_id;
void *hwrm_cmd_resp_addr;
Expand Down Expand Up @@ -991,6 +994,7 @@ struct bnxt {
#define BNXT_RST_RING_SP_EVENT 7
#define BNXT_HWRM_PF_UNLOAD_SP_EVENT 8
#define BNXT_PERIODIC_STATS_SP_EVENT 9
#define BNXT_HWRM_PORT_MODULE_SP_EVENT 10

struct bnxt_pf_info pf;
#ifdef CONFIG_BNXT_SRIOV
Expand All @@ -1011,6 +1015,9 @@ struct bnxt {
int ntp_fltr_count;

struct bnxt_link_info link_info;
struct ethtool_eee eee;
u32 lpi_tmr_lo;
u32 lpi_tmr_hi;
};

#ifdef CONFIG_NET_RX_BUSY_POLL
Expand Down Expand Up @@ -1108,7 +1115,7 @@ int hwrm_send_message_silent(struct bnxt *, void *, u32, int);
int bnxt_hwrm_set_coal(struct bnxt *);
int bnxt_hwrm_func_qcaps(struct bnxt *);
int bnxt_hwrm_set_pause(struct bnxt *);
int bnxt_hwrm_set_link_setting(struct bnxt *, bool);
int bnxt_hwrm_set_link_setting(struct bnxt *, bool, bool);
int bnxt_open_nic(struct bnxt *, bool, bool);
int bnxt_close_nic(struct bnxt *, bool, bool);
int bnxt_get_max_rings(struct bnxt *, int *, int *, bool);
Expand Down
165 changes: 136 additions & 29 deletions drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* Broadcom NetXtreme-C/E network driver.
*
* Copyright (c) 2014-2015 Broadcom Corporation
* Copyright (c) 2014-2016 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -597,7 +597,7 @@ static void bnxt_get_drvinfo(struct net_device *dev,
kfree(pkglog);
}

static u32 _bnxt_fw_to_ethtool_adv_spds(u16 fw_speeds, u8 fw_pause)
u32 _bnxt_fw_to_ethtool_adv_spds(u16 fw_speeds, u8 fw_pause)
{
u32 speed_mask = 0;

Expand Down Expand Up @@ -698,10 +698,23 @@ static int bnxt_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
if (link_info->phy_link_status == BNXT_LINK_LINK)
cmd->lp_advertising =
bnxt_fw_to_ethtool_lp_adv(link_info);
ethtool_speed = bnxt_fw_to_ethtool_speed(link_info->link_speed);
if (!netif_carrier_ok(dev))
cmd->duplex = DUPLEX_UNKNOWN;
else if (link_info->duplex & BNXT_LINK_DUPLEX_FULL)
cmd->duplex = DUPLEX_FULL;
else
cmd->duplex = DUPLEX_HALF;
} else {
cmd->autoneg = AUTONEG_DISABLE;
cmd->advertising = 0;
ethtool_speed =
bnxt_fw_to_ethtool_speed(link_info->req_link_speed);
cmd->duplex = DUPLEX_HALF;
if (link_info->req_duplex == BNXT_LINK_DUPLEX_FULL)
cmd->duplex = DUPLEX_FULL;
}
ethtool_cmd_speed_set(cmd, ethtool_speed);

cmd->port = PORT_NONE;
if (link_info->media_type == PORT_PHY_QCFG_RESP_MEDIA_TYPE_TP) {
Expand All @@ -719,16 +732,8 @@ static int bnxt_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
cmd->port = PORT_FIBRE;
}

if (link_info->phy_link_status == BNXT_LINK_LINK) {
if (link_info->duplex & BNXT_LINK_DUPLEX_FULL)
cmd->duplex = DUPLEX_FULL;
} else {
cmd->duplex = DUPLEX_UNKNOWN;
}
ethtool_speed = bnxt_fw_to_ethtool_speed(link_info->link_speed);
ethtool_cmd_speed_set(cmd, ethtool_speed);
if (link_info->transceiver ==
PORT_PHY_QCFG_RESP_TRANSCEIVER_TYPE_XCVR_INTERNAL)
PORT_PHY_QCFG_RESP_XCVR_PKG_TYPE_XCVR_INTERNAL)
cmd->transceiver = XCVR_INTERNAL;
else
cmd->transceiver = XCVR_EXTERNAL;
Expand All @@ -739,31 +744,52 @@ static int bnxt_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)

static u32 bnxt_get_fw_speed(struct net_device *dev, u16 ethtool_speed)
{
struct bnxt *bp = netdev_priv(dev);
struct bnxt_link_info *link_info = &bp->link_info;
u16 support_spds = link_info->support_speeds;
u32 fw_speed = 0;

switch (ethtool_speed) {
case SPEED_100:
return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_100MB;
if (support_spds & BNXT_LINK_SPEED_MSK_100MB)
fw_speed = PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_100MB;
break;
case SPEED_1000:
return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_1GB;
if (support_spds & BNXT_LINK_SPEED_MSK_1GB)
fw_speed = PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_1GB;
break;
case SPEED_2500:
return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_2_5GB;
if (support_spds & BNXT_LINK_SPEED_MSK_2_5GB)
fw_speed = PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_2_5GB;
break;
case SPEED_10000:
return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_10GB;
if (support_spds & BNXT_LINK_SPEED_MSK_10GB)
fw_speed = PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_10GB;
break;
case SPEED_20000:
return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_20GB;
if (support_spds & BNXT_LINK_SPEED_MSK_20GB)
fw_speed = PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_20GB;
break;
case SPEED_25000:
return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_25GB;
if (support_spds & BNXT_LINK_SPEED_MSK_25GB)
fw_speed = PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_25GB;
break;
case SPEED_40000:
return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_40GB;
if (support_spds & BNXT_LINK_SPEED_MSK_40GB)
fw_speed = PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_40GB;
break;
case SPEED_50000:
return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_50GB;
if (support_spds & BNXT_LINK_SPEED_MSK_50GB)
fw_speed = PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_50GB;
break;
default:
netdev_err(dev, "unsupported speed!\n");
break;
}
return 0;
return fw_speed;
}

static u16 bnxt_get_fw_auto_link_speeds(u32 advertising)
u16 bnxt_get_fw_auto_link_speeds(u32 advertising)
{
u16 fw_speed_mask = 0;

Expand Down Expand Up @@ -823,6 +849,8 @@ static int bnxt_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
*/
set_pause = true;
} else {
u16 fw_speed;

/* TODO: currently don't support half duplex */
if (cmd->duplex == DUPLEX_HALF) {
netdev_err(dev, "HALF DUPLEX is not supported!\n");
Expand All @@ -833,14 +861,19 @@ static int bnxt_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
if (cmd->duplex == DUPLEX_UNKNOWN)
cmd->duplex = DUPLEX_FULL;
speed = ethtool_cmd_speed(cmd);
link_info->req_link_speed = bnxt_get_fw_speed(dev, speed);
fw_speed = bnxt_get_fw_speed(dev, speed);
if (!fw_speed) {
rc = -EINVAL;
goto set_setting_exit;
}
link_info->req_link_speed = fw_speed;
link_info->req_duplex = BNXT_LINK_DUPLEX_FULL;
link_info->autoneg = 0;
link_info->advertising = 0;
}

if (netif_running(dev))
rc = bnxt_hwrm_set_link_setting(bp, set_pause);
rc = bnxt_hwrm_set_link_setting(bp, set_pause, false);

set_setting_exit:
return rc;
Expand Down Expand Up @@ -874,25 +907,23 @@ static int bnxt_set_pauseparam(struct net_device *dev,
return -EINVAL;

link_info->autoneg |= BNXT_AUTONEG_FLOW_CTRL;
link_info->req_flow_ctrl |= BNXT_LINK_PAUSE_BOTH;
if (bp->hwrm_spec_code >= 0x10201)
link_info->req_flow_ctrl =
PORT_PHY_CFG_REQ_AUTO_PAUSE_AUTONEG_PAUSE;
} else {
/* when transition from auto pause to force pause,
* force a link change
*/
if (link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL)
link_info->force_link_chng = true;
link_info->autoneg &= ~BNXT_AUTONEG_FLOW_CTRL;
link_info->req_flow_ctrl &= ~BNXT_LINK_PAUSE_BOTH;
link_info->req_flow_ctrl = 0;
}
if (epause->rx_pause)
link_info->req_flow_ctrl |= BNXT_LINK_PAUSE_RX;
else
link_info->req_flow_ctrl &= ~BNXT_LINK_PAUSE_RX;

if (epause->tx_pause)
link_info->req_flow_ctrl |= BNXT_LINK_PAUSE_TX;
else
link_info->req_flow_ctrl &= ~BNXT_LINK_PAUSE_TX;

if (netif_running(dev))
rc = bnxt_hwrm_set_pause(bp);
Expand Down Expand Up @@ -1381,6 +1412,80 @@ static int bnxt_set_eeprom(struct net_device *dev,
eeprom->len);
}

static int bnxt_set_eee(struct net_device *dev, struct ethtool_eee *edata)
{
struct bnxt *bp = netdev_priv(dev);
struct ethtool_eee *eee = &bp->eee;
struct bnxt_link_info *link_info = &bp->link_info;
u32 advertising =
_bnxt_fw_to_ethtool_adv_spds(link_info->advertising, 0);
int rc = 0;

if (BNXT_VF(bp))
return 0;

if (!(bp->flags & BNXT_FLAG_EEE_CAP))
return -EOPNOTSUPP;

if (!edata->eee_enabled)
goto eee_ok;

if (!(link_info->autoneg & BNXT_AUTONEG_SPEED)) {
netdev_warn(dev, "EEE requires autoneg\n");
return -EINVAL;
}
if (edata->tx_lpi_enabled) {
if (bp->lpi_tmr_hi && (edata->tx_lpi_timer > bp->lpi_tmr_hi ||
edata->tx_lpi_timer < bp->lpi_tmr_lo)) {
netdev_warn(dev, "Valid LPI timer range is %d and %d microsecs\n",
bp->lpi_tmr_lo, bp->lpi_tmr_hi);
return -EINVAL;
} else if (!bp->lpi_tmr_hi) {
edata->tx_lpi_timer = eee->tx_lpi_timer;
}
}
if (!edata->advertised) {
edata->advertised = advertising & eee->supported;
} else if (edata->advertised & ~advertising) {
netdev_warn(dev, "EEE advertised %x must be a subset of autoneg advertised speeds %x\n",
edata->advertised, advertising);
return -EINVAL;
}

eee->advertised = edata->advertised;
eee->tx_lpi_enabled = edata->tx_lpi_enabled;
eee->tx_lpi_timer = edata->tx_lpi_timer;
eee_ok:
eee->eee_enabled = edata->eee_enabled;

if (netif_running(dev))
rc = bnxt_hwrm_set_link_setting(bp, false, true);

return rc;
}

static int bnxt_get_eee(struct net_device *dev, struct ethtool_eee *edata)
{
struct bnxt *bp = netdev_priv(dev);

if (!(bp->flags & BNXT_FLAG_EEE_CAP))
return -EOPNOTSUPP;

*edata = bp->eee;
if (!bp->eee.eee_enabled) {
/* Preserve tx_lpi_timer so that the last value will be used
* by default when it is re-enabled.
*/
edata->advertised = 0;
edata->tx_lpi_enabled = 0;
}

if (!bp->eee.eee_active)
edata->lp_advertised = 0;

return 0;
}

const struct ethtool_ops bnxt_ethtool_ops = {
.get_settings = bnxt_get_settings,
.set_settings = bnxt_set_settings,
Expand Down Expand Up @@ -1409,4 +1514,6 @@ const struct ethtool_ops bnxt_ethtool_ops = {
.get_eeprom = bnxt_get_eeprom,
.set_eeprom = bnxt_set_eeprom,
.get_link = bnxt_get_link,
.get_eee = bnxt_get_eee,
.set_eee = bnxt_set_eee,
};
4 changes: 3 additions & 1 deletion drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* Broadcom NetXtreme-C/E network driver.
*
* Copyright (c) 2014-2015 Broadcom Corporation
* Copyright (c) 2014-2016 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand All @@ -12,6 +12,8 @@

extern const struct ethtool_ops bnxt_ethtool_ops;

u32 _bnxt_fw_to_ethtool_adv_spds(u16, u8);
u32 bnxt_fw_to_ethtool_speed(u16);
u16 bnxt_get_fw_auto_link_speeds(u32);

#endif
2 changes: 1 addition & 1 deletion drivers/net/ethernet/broadcom/bnxt/bnxt_fw_hdr.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* Broadcom NetXtreme-C/E network driver.
*
* Copyright (c) 2014-2015 Broadcom Corporation
* Copyright (c) 2014-2016 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down
Loading

0 comments on commit f1cc809

Please sign in to comment.