Skip to content

Commit

Permalink
Merge branch 'net-atlantic-QoS-implementation'
Browse files Browse the repository at this point in the history
Igor Russkikh says:

====================
net: atlantic: QoS implementation

This patch series adds support for mqprio rate limiters and multi-TC:
 * max_rate is supported on both A1 and A2;
 * min_rate is supported on A2 only;

This is a joint work of Mark and Dmitry.

To implement this feature, a couple of rearrangements and code
improvements were done, in areas of TC/ring management, allocation
control, etc.

One of the problems we faced is conflicting ptp functionality, which
consumes a whole traffic class due to hardware limitations.
Patches below have a more detailed description on how PTP and multi-TC
co-exist right now.

v2:
 * accommodated review comments (-Wmissing-prototypes and
   -Wunused-but-set-variable findings);
 * added user notification in case of conflicting multi-TC<->PTP
   configuration;
 * added automatic PTP disabling, if a conflicting configuration is
   detected;
 * removed module param, which was used for PTP disabling in v1;

v1: https://patchwork.ozlabs.org/cover/1294380/
====================

Acked-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed May 22, 2020
2 parents 59b8d27 + 40f05e5 commit b79f91f
Show file tree
Hide file tree
Showing 26 changed files with 1,197 additions and 381 deletions.
74 changes: 40 additions & 34 deletions drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,13 @@ static const char aq_ethtool_stat_names[][ETH_GSTRING_LEN] = {
"InDroppedDma",
};

static const char aq_ethtool_queue_stat_names[][ETH_GSTRING_LEN] = {
"Queue[%d] InPackets",
"Queue[%d] OutPackets",
"Queue[%d] Restarts",
"Queue[%d] InJumboPackets",
"Queue[%d] InLroPackets",
"Queue[%d] InErrors",
static const char * const aq_ethtool_queue_stat_names[] = {
"%sQueue[%d] InPackets",
"%sQueue[%d] OutPackets",
"%sQueue[%d] Restarts",
"%sQueue[%d] InJumboPackets",
"%sQueue[%d] InLroPackets",
"%sQueue[%d] InErrors",
};

#if IS_ENABLED(CONFIG_MACSEC)
Expand Down Expand Up @@ -166,7 +166,8 @@ static u32 aq_ethtool_n_stats(struct net_device *ndev)
struct aq_nic_s *nic = netdev_priv(ndev);
struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(nic);
u32 n_stats = ARRAY_SIZE(aq_ethtool_stat_names) +
ARRAY_SIZE(aq_ethtool_queue_stat_names) * cfg->vecs;
ARRAY_SIZE(aq_ethtool_queue_stat_names) * cfg->vecs *
cfg->tcs;

#if IS_ENABLED(CONFIG_MACSEC)
if (nic->macsec_cfg) {
Expand Down Expand Up @@ -223,40 +224,51 @@ static void aq_ethtool_get_drvinfo(struct net_device *ndev,
static void aq_ethtool_get_strings(struct net_device *ndev,
u32 stringset, u8 *data)
{
struct aq_nic_s *aq_nic = netdev_priv(ndev);
struct aq_nic_s *nic = netdev_priv(ndev);
struct aq_nic_cfg_s *cfg;
u8 *p = data;
int i, si;
#if IS_ENABLED(CONFIG_MACSEC)
int sa;
#endif

cfg = aq_nic_get_cfg(aq_nic);
cfg = aq_nic_get_cfg(nic);

switch (stringset) {
case ETH_SS_STATS:
case ETH_SS_STATS: {
const int stat_cnt = ARRAY_SIZE(aq_ethtool_queue_stat_names);
char tc_string[8];
int tc;

memset(tc_string, 0, sizeof(tc_string));
memcpy(p, aq_ethtool_stat_names,
sizeof(aq_ethtool_stat_names));
p = p + sizeof(aq_ethtool_stat_names);
for (i = 0; i < cfg->vecs; i++) {
for (si = 0;
si < ARRAY_SIZE(aq_ethtool_queue_stat_names);
si++) {
snprintf(p, ETH_GSTRING_LEN,
aq_ethtool_queue_stat_names[si], i);
p += ETH_GSTRING_LEN;

for (tc = 0; tc < cfg->tcs; tc++) {
if (cfg->is_qos)
snprintf(tc_string, 8, "TC%d ", tc);

for (i = 0; i < cfg->vecs; i++) {
for (si = 0; si < stat_cnt; si++) {
snprintf(p, ETH_GSTRING_LEN,
aq_ethtool_queue_stat_names[si],
tc_string,
AQ_NIC_CFG_TCVEC2RING(cfg, tc, i));
p += ETH_GSTRING_LEN;
}
}
}
#if IS_ENABLED(CONFIG_MACSEC)
if (!aq_nic->macsec_cfg)
if (!nic->macsec_cfg)
break;

memcpy(p, aq_macsec_stat_names, sizeof(aq_macsec_stat_names));
p = p + sizeof(aq_macsec_stat_names);
for (i = 0; i < AQ_MACSEC_MAX_SC; i++) {
struct aq_macsec_txsc *aq_txsc;

if (!(test_bit(i, &aq_nic->macsec_cfg->txsc_idx_busy)))
if (!(test_bit(i, &nic->macsec_cfg->txsc_idx_busy)))
continue;

for (si = 0;
Expand All @@ -266,7 +278,7 @@ static void aq_ethtool_get_strings(struct net_device *ndev,
aq_macsec_txsc_stat_names[si], i);
p += ETH_GSTRING_LEN;
}
aq_txsc = &aq_nic->macsec_cfg->aq_txsc[i];
aq_txsc = &nic->macsec_cfg->aq_txsc[i];
for (sa = 0; sa < MACSEC_NUM_AN; sa++) {
if (!(test_bit(sa, &aq_txsc->tx_sa_idx_busy)))
continue;
Expand All @@ -283,10 +295,10 @@ static void aq_ethtool_get_strings(struct net_device *ndev,
for (i = 0; i < AQ_MACSEC_MAX_SC; i++) {
struct aq_macsec_rxsc *aq_rxsc;

if (!(test_bit(i, &aq_nic->macsec_cfg->rxsc_idx_busy)))
if (!(test_bit(i, &nic->macsec_cfg->rxsc_idx_busy)))
continue;

aq_rxsc = &aq_nic->macsec_cfg->aq_rxsc[i];
aq_rxsc = &nic->macsec_cfg->aq_rxsc[i];
for (sa = 0; sa < MACSEC_NUM_AN; sa++) {
if (!(test_bit(sa, &aq_rxsc->rx_sa_idx_busy)))
continue;
Expand All @@ -302,6 +314,7 @@ static void aq_ethtool_get_strings(struct net_device *ndev,
}
#endif
break;
}
case ETH_SS_PRIV_FLAGS:
memcpy(p, aq_ethtool_priv_flag_names,
sizeof(aq_ethtool_priv_flag_names));
Expand Down Expand Up @@ -780,8 +793,6 @@ static int aq_set_ringparam(struct net_device *ndev,
dev_close(ndev);
}

aq_nic_free_vectors(aq_nic);

cfg->rxds = max(ring->rx_pending, hw_caps->rxds_min);
cfg->rxds = min(cfg->rxds, hw_caps->rxds_max);
cfg->rxds = ALIGN(cfg->rxds, AQ_HW_RXD_MULTIPLE);
Expand All @@ -790,15 +801,10 @@ static int aq_set_ringparam(struct net_device *ndev,
cfg->txds = min(cfg->txds, hw_caps->txds_max);
cfg->txds = ALIGN(cfg->txds, AQ_HW_TXD_MULTIPLE);

for (aq_nic->aq_vecs = 0; aq_nic->aq_vecs < cfg->vecs;
aq_nic->aq_vecs++) {
aq_nic->aq_vec[aq_nic->aq_vecs] =
aq_vec_alloc(aq_nic, aq_nic->aq_vecs, cfg);
if (unlikely(!aq_nic->aq_vec[aq_nic->aq_vecs])) {
err = -ENOMEM;
goto err_exit;
}
}
err = aq_nic_realloc_vectors(aq_nic);
if (err)
goto err_exit;

if (ndev_running)
err = dev_open(ndev, NULL);

Expand Down
11 changes: 7 additions & 4 deletions drivers/net/ethernet/aquantia/atlantic/aq_filters.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ aq_check_approve_fvlan(struct aq_nic_s *aq_nic,
struct aq_hw_rx_fltrs_s *rx_fltrs,
struct ethtool_rx_flow_spec *fsp)
{
struct aq_nic_cfg_s *cfg = &aq_nic->aq_nic_cfg;

if (fsp->location < AQ_RX_FIRST_LOC_FVLANID ||
fsp->location > AQ_RX_LAST_LOC_FVLANID) {
netdev_err(aq_nic->ndev,
Expand All @@ -170,10 +172,10 @@ aq_check_approve_fvlan(struct aq_nic_s *aq_nic,
return -EINVAL;
}

if (fsp->ring_cookie > aq_nic->aq_nic_cfg.num_rss_queues) {
if (fsp->ring_cookie > cfg->num_rss_queues * cfg->tcs) {
netdev_err(aq_nic->ndev,
"ethtool: queue number must be in range [0, %d]",
aq_nic->aq_nic_cfg.num_rss_queues - 1);
cfg->num_rss_queues * cfg->tcs - 1);
return -EINVAL;
}
return 0;
Expand Down Expand Up @@ -262,6 +264,7 @@ static bool __must_check
aq_rule_is_not_correct(struct aq_nic_s *aq_nic,
struct ethtool_rx_flow_spec *fsp)
{
struct aq_nic_cfg_s *cfg = &aq_nic->aq_nic_cfg;
bool rule_is_not_correct = false;

if (!aq_nic) {
Expand All @@ -274,11 +277,11 @@ aq_rule_is_not_correct(struct aq_nic_s *aq_nic,
} else if (aq_check_filter(aq_nic, fsp)) {
rule_is_not_correct = true;
} else if (fsp->ring_cookie != RX_CLS_FLOW_DISC) {
if (fsp->ring_cookie >= aq_nic->aq_nic_cfg.num_rss_queues) {
if (fsp->ring_cookie >= cfg->num_rss_queues * cfg->tcs) {
netdev_err(aq_nic->ndev,
"ethtool: The specified action is invalid.\n"
"Maximum allowable value action is %u.\n",
aq_nic->aq_nic_cfg.num_rss_queues - 1);
cfg->num_rss_queues * cfg->tcs - 1);
rule_is_not_correct = true;
}
}
Expand Down
20 changes: 15 additions & 5 deletions drivers/net/ethernet/aquantia/atlantic/aq_hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@
#define AQ_HW_MAC_COUNTER_HZ 312500000ll
#define AQ_HW_PHY_COUNTER_HZ 160000000ll

enum aq_tc_mode {
AQ_TC_MODE_INVALID = -1,
AQ_TC_MODE_8TCS,
AQ_TC_MODE_4TCS,
};

#define AQ_RX_FIRST_LOC_FVLANID 0U
#define AQ_RX_LAST_LOC_FVLANID 15U
#define AQ_RX_FIRST_LOC_FETHERT 16U
Expand All @@ -29,6 +35,9 @@
(AQ_RX_LAST_LOC_FVLANID - AQ_RX_FIRST_LOC_FVLANID + 1U)
#define AQ_RX_QUEUE_NOT_ASSIGNED 0xFFU

/* Used for rate to Mbps conversion */
#define AQ_MBPS_DIVISOR 125000 /* 1000000 / 8 */

/* NIC H/W capabilities */
struct aq_hw_caps_s {
u64 hw_features;
Expand All @@ -46,7 +55,7 @@ struct aq_hw_caps_s {
u32 mac_regs_count;
u32 hw_alive_check_addr;
u8 msix_irqs;
u8 tcs;
u8 tcs_max;
u8 rxd_alignment;
u8 rxd_size;
u8 txd_alignment;
Expand Down Expand Up @@ -118,8 +127,11 @@ struct aq_stats_s {
#define AQ_HW_TXD_MULTIPLE 8U
#define AQ_HW_RXD_MULTIPLE 8U

#define AQ_HW_QUEUES_MAX 32U
#define AQ_HW_MULTICAST_ADDRESS_MAX 32U

#define AQ_HW_PTP_TC 2U

#define AQ_HW_LED_BLINK 0x2U
#define AQ_HW_LED_DEFAULT 0x0U

Expand Down Expand Up @@ -268,6 +280,8 @@ struct aq_hw_ops {
int (*hw_rss_hash_set)(struct aq_hw_s *self,
struct aq_rss_parameters *rss_params);

int (*hw_tc_rate_limit_set)(struct aq_hw_s *self);

int (*hw_get_regs)(struct aq_hw_s *self,
const struct aq_hw_caps_s *aq_hw_caps,
u32 *regs_buff);
Expand All @@ -279,10 +293,6 @@ struct aq_hw_ops {
int (*hw_set_offload)(struct aq_hw_s *self,
struct aq_nic_cfg_s *aq_nic_cfg);

int (*hw_tx_tc_mode_get)(struct aq_hw_s *self, u32 *tc_mode);

int (*hw_rx_tc_mode_get)(struct aq_hw_s *self, u32 *tc_mode);

int (*hw_ring_hwts_rx_fill)(struct aq_hw_s *self,
struct aq_ring_s *aq_ring);

Expand Down
26 changes: 26 additions & 0 deletions drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,29 @@ int aq_hw_err_from_flags(struct aq_hw_s *hw)
err_exit:
return err;
}

int aq_hw_num_tcs(struct aq_hw_s *hw)
{
switch (hw->aq_nic_cfg->tc_mode) {
case AQ_TC_MODE_8TCS:
return 8;
case AQ_TC_MODE_4TCS:
return 4;
default:
break;
}

return 1;
}

int aq_hw_q_per_tc(struct aq_hw_s *hw)
{
switch (hw->aq_nic_cfg->tc_mode) {
case AQ_TC_MODE_8TCS:
return 4;
case AQ_TC_MODE_4TCS:
return 8;
default:
return 4;
}
}
2 changes: 2 additions & 0 deletions drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,7 @@ u32 aq_hw_read_reg(struct aq_hw_s *hw, u32 reg);
void aq_hw_write_reg(struct aq_hw_s *hw, u32 reg, u32 value);
u64 aq_hw_read_reg64(struct aq_hw_s *hw, u32 reg);
int aq_hw_err_from_flags(struct aq_hw_s *hw);
int aq_hw_num_tcs(struct aq_hw_s *hw);
int aq_hw_q_per_tc(struct aq_hw_s *hw);

#endif /* AQ_HW_UTILS_H */
2 changes: 1 addition & 1 deletion drivers/net/ethernet/aquantia/atlantic/aq_macsec.c
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ static int aq_mdo_add_secy(struct macsec_context *ctx)

set_bit(txsc_idx, &cfg->txsc_idx_busy);

return 0;
return ret;
}

static int aq_mdo_upd_secy(struct macsec_context *ctx)
Expand Down
Loading

0 comments on commit b79f91f

Please sign in to comment.