mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 14:42:24 +00:00
octeontx2-pf: ethtool RSS config support
Added support to show or configure RSS hash key, indirection table, 2,4 tuple via ethtool. Also added debug msg_level support to dump messages when HW reports errors in packet received or transmitted. Signed-off-by: Prakash Brahmajyosyula <bprakash@marvell.com> Signed-off-by: Sunil Goutham <sgoutham@marvell.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
d45d897984
commit
6e92d71bf8
@ -220,7 +220,7 @@ int otx2_hw_set_mtu(struct otx2_nic *pfvf, int mtu)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int otx2_set_flowkey_cfg(struct otx2_nic *pfvf)
|
||||
int otx2_set_flowkey_cfg(struct otx2_nic *pfvf)
|
||||
{
|
||||
struct otx2_rss_info *rss = &pfvf->hw.rss_info;
|
||||
struct nix_rss_flowkey_cfg *req;
|
||||
@ -241,7 +241,7 @@ static int otx2_set_flowkey_cfg(struct otx2_nic *pfvf)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int otx2_set_rss_table(struct otx2_nic *pfvf)
|
||||
int otx2_set_rss_table(struct otx2_nic *pfvf)
|
||||
{
|
||||
struct otx2_rss_info *rss = &pfvf->hw.rss_info;
|
||||
struct mbox *mbox = &pfvf->mbox;
|
||||
@ -280,7 +280,7 @@ static int otx2_set_rss_table(struct otx2_nic *pfvf)
|
||||
return err;
|
||||
}
|
||||
|
||||
static void otx2_set_rss_key(struct otx2_nic *pfvf)
|
||||
void otx2_set_rss_key(struct otx2_nic *pfvf)
|
||||
{
|
||||
struct otx2_rss_info *rss = &pfvf->hw.rss_info;
|
||||
u64 *key = (u64 *)&rss->key[4];
|
||||
|
@ -222,6 +222,9 @@ struct otx2_nic {
|
||||
struct work_struct reset_task;
|
||||
struct refill_work *refill_wrk;
|
||||
|
||||
/* Ethtool stuff */
|
||||
u32 msg_enable;
|
||||
|
||||
/* Block address of NIX either BLKADDR_NIX0 or BLKADDR_NIX1 */
|
||||
int nix_blkaddr;
|
||||
};
|
||||
@ -580,6 +583,9 @@ void otx2_cleanup_tx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq);
|
||||
|
||||
/* RSS configuration APIs*/
|
||||
int otx2_rss_init(struct otx2_nic *pfvf);
|
||||
int otx2_set_flowkey_cfg(struct otx2_nic *pfvf);
|
||||
void otx2_set_rss_key(struct otx2_nic *pfvf);
|
||||
int otx2_set_rss_table(struct otx2_nic *pfvf);
|
||||
|
||||
/* Mbox handlers */
|
||||
void mbox_handler_msix_offset(struct otx2_nic *pfvf,
|
||||
|
@ -389,7 +389,253 @@ static int otx2_set_coalesce(struct net_device *netdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int otx2_get_rss_hash_opts(struct otx2_nic *pfvf,
|
||||
struct ethtool_rxnfc *nfc)
|
||||
{
|
||||
struct otx2_rss_info *rss = &pfvf->hw.rss_info;
|
||||
|
||||
if (!(rss->flowkey_cfg &
|
||||
(NIX_FLOW_KEY_TYPE_IPV4 | NIX_FLOW_KEY_TYPE_IPV6)))
|
||||
return 0;
|
||||
|
||||
/* Mimimum is IPv4 and IPv6, SIP/DIP */
|
||||
nfc->data = RXH_IP_SRC | RXH_IP_DST;
|
||||
|
||||
switch (nfc->flow_type) {
|
||||
case TCP_V4_FLOW:
|
||||
case TCP_V6_FLOW:
|
||||
if (rss->flowkey_cfg & NIX_FLOW_KEY_TYPE_TCP)
|
||||
nfc->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
|
||||
break;
|
||||
case UDP_V4_FLOW:
|
||||
case UDP_V6_FLOW:
|
||||
if (rss->flowkey_cfg & NIX_FLOW_KEY_TYPE_UDP)
|
||||
nfc->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
|
||||
break;
|
||||
case SCTP_V4_FLOW:
|
||||
case SCTP_V6_FLOW:
|
||||
if (rss->flowkey_cfg & NIX_FLOW_KEY_TYPE_SCTP)
|
||||
nfc->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
|
||||
break;
|
||||
case AH_ESP_V4_FLOW:
|
||||
case AH_V4_FLOW:
|
||||
case ESP_V4_FLOW:
|
||||
case IPV4_FLOW:
|
||||
case AH_ESP_V6_FLOW:
|
||||
case AH_V6_FLOW:
|
||||
case ESP_V6_FLOW:
|
||||
case IPV6_FLOW:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int otx2_set_rss_hash_opts(struct otx2_nic *pfvf,
|
||||
struct ethtool_rxnfc *nfc)
|
||||
{
|
||||
struct otx2_rss_info *rss = &pfvf->hw.rss_info;
|
||||
u32 rxh_l4 = RXH_L4_B_0_1 | RXH_L4_B_2_3;
|
||||
u32 rss_cfg = rss->flowkey_cfg;
|
||||
|
||||
if (!rss->enable) {
|
||||
netdev_err(pfvf->netdev,
|
||||
"RSS is disabled, cannot change settings\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Mimimum is IPv4 and IPv6, SIP/DIP */
|
||||
if (!(nfc->data & RXH_IP_SRC) || !(nfc->data & RXH_IP_DST))
|
||||
return -EINVAL;
|
||||
|
||||
switch (nfc->flow_type) {
|
||||
case TCP_V4_FLOW:
|
||||
case TCP_V6_FLOW:
|
||||
/* Different config for v4 and v6 is not supported.
|
||||
* Both of them have to be either 4-tuple or 2-tuple.
|
||||
*/
|
||||
switch (nfc->data & rxh_l4) {
|
||||
case 0:
|
||||
rss_cfg &= ~NIX_FLOW_KEY_TYPE_TCP;
|
||||
break;
|
||||
case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
|
||||
rss_cfg |= NIX_FLOW_KEY_TYPE_TCP;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case UDP_V4_FLOW:
|
||||
case UDP_V6_FLOW:
|
||||
switch (nfc->data & rxh_l4) {
|
||||
case 0:
|
||||
rss_cfg &= ~NIX_FLOW_KEY_TYPE_UDP;
|
||||
break;
|
||||
case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
|
||||
rss_cfg |= NIX_FLOW_KEY_TYPE_UDP;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case SCTP_V4_FLOW:
|
||||
case SCTP_V6_FLOW:
|
||||
switch (nfc->data & rxh_l4) {
|
||||
case 0:
|
||||
rss_cfg &= ~NIX_FLOW_KEY_TYPE_SCTP;
|
||||
break;
|
||||
case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
|
||||
rss_cfg |= NIX_FLOW_KEY_TYPE_SCTP;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case IPV4_FLOW:
|
||||
case IPV6_FLOW:
|
||||
rss_cfg = NIX_FLOW_KEY_TYPE_IPV4 | NIX_FLOW_KEY_TYPE_IPV6;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rss->flowkey_cfg = rss_cfg;
|
||||
otx2_set_flowkey_cfg(pfvf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int otx2_get_rxnfc(struct net_device *dev,
|
||||
struct ethtool_rxnfc *nfc, u32 *rules)
|
||||
{
|
||||
struct otx2_nic *pfvf = netdev_priv(dev);
|
||||
int ret = -EOPNOTSUPP;
|
||||
|
||||
switch (nfc->cmd) {
|
||||
case ETHTOOL_GRXRINGS:
|
||||
nfc->data = pfvf->hw.rx_queues;
|
||||
ret = 0;
|
||||
break;
|
||||
case ETHTOOL_GRXFH:
|
||||
return otx2_get_rss_hash_opts(pfvf, nfc);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int otx2_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *nfc)
|
||||
{
|
||||
struct otx2_nic *pfvf = netdev_priv(dev);
|
||||
int ret = -EOPNOTSUPP;
|
||||
|
||||
switch (nfc->cmd) {
|
||||
case ETHTOOL_SRXFH:
|
||||
ret = otx2_set_rss_hash_opts(pfvf, nfc);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32 otx2_get_rxfh_key_size(struct net_device *netdev)
|
||||
{
|
||||
struct otx2_nic *pfvf = netdev_priv(netdev);
|
||||
struct otx2_rss_info *rss;
|
||||
|
||||
rss = &pfvf->hw.rss_info;
|
||||
|
||||
return sizeof(rss->key);
|
||||
}
|
||||
|
||||
static u32 otx2_get_rxfh_indir_size(struct net_device *dev)
|
||||
{
|
||||
struct otx2_nic *pfvf = netdev_priv(dev);
|
||||
|
||||
return pfvf->hw.rss_info.rss_size;
|
||||
}
|
||||
|
||||
/* Get RSS configuration */
|
||||
static int otx2_get_rxfh(struct net_device *dev, u32 *indir,
|
||||
u8 *hkey, u8 *hfunc)
|
||||
{
|
||||
struct otx2_nic *pfvf = netdev_priv(dev);
|
||||
struct otx2_rss_info *rss;
|
||||
int idx;
|
||||
|
||||
rss = &pfvf->hw.rss_info;
|
||||
|
||||
if (indir) {
|
||||
for (idx = 0; idx < rss->rss_size; idx++)
|
||||
indir[idx] = rss->ind_tbl[idx];
|
||||
}
|
||||
|
||||
if (hkey)
|
||||
memcpy(hkey, rss->key, sizeof(rss->key));
|
||||
|
||||
if (hfunc)
|
||||
*hfunc = ETH_RSS_HASH_TOP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Configure RSS table and hash key */
|
||||
static int otx2_set_rxfh(struct net_device *dev, const u32 *indir,
|
||||
const u8 *hkey, const u8 hfunc)
|
||||
{
|
||||
struct otx2_nic *pfvf = netdev_priv(dev);
|
||||
struct otx2_rss_info *rss;
|
||||
int idx;
|
||||
|
||||
if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
rss = &pfvf->hw.rss_info;
|
||||
|
||||
if (!rss->enable) {
|
||||
netdev_err(dev, "RSS is disabled, cannot change settings\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (indir) {
|
||||
for (idx = 0; idx < rss->rss_size; idx++)
|
||||
rss->ind_tbl[idx] = indir[idx];
|
||||
}
|
||||
|
||||
if (hkey) {
|
||||
memcpy(rss->key, hkey, sizeof(rss->key));
|
||||
otx2_set_rss_key(pfvf);
|
||||
}
|
||||
|
||||
otx2_set_rss_table(pfvf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 otx2_get_msglevel(struct net_device *netdev)
|
||||
{
|
||||
struct otx2_nic *pfvf = netdev_priv(netdev);
|
||||
|
||||
return pfvf->msg_enable;
|
||||
}
|
||||
|
||||
static void otx2_set_msglevel(struct net_device *netdev, u32 val)
|
||||
{
|
||||
struct otx2_nic *pfvf = netdev_priv(netdev);
|
||||
|
||||
pfvf->msg_enable = val;
|
||||
}
|
||||
|
||||
static u32 otx2_get_link(struct net_device *netdev)
|
||||
{
|
||||
struct otx2_nic *pfvf = netdev_priv(netdev);
|
||||
|
||||
return pfvf->linfo.link_up;
|
||||
}
|
||||
|
||||
static const struct ethtool_ops otx2_ethtool_ops = {
|
||||
.get_link = otx2_get_link,
|
||||
.get_drvinfo = otx2_get_drvinfo,
|
||||
.get_strings = otx2_get_strings,
|
||||
.get_ethtool_stats = otx2_get_ethtool_stats,
|
||||
@ -400,6 +646,14 @@ static const struct ethtool_ops otx2_ethtool_ops = {
|
||||
.set_ringparam = otx2_set_ringparam,
|
||||
.get_coalesce = otx2_get_coalesce,
|
||||
.set_coalesce = otx2_set_coalesce,
|
||||
.get_rxnfc = otx2_get_rxnfc,
|
||||
.set_rxnfc = otx2_set_rxnfc,
|
||||
.get_rxfh_key_size = otx2_get_rxfh_key_size,
|
||||
.get_rxfh_indir_size = otx2_get_rxfh_indir_size,
|
||||
.get_rxfh = otx2_get_rxfh,
|
||||
.set_rxfh = otx2_set_rxfh,
|
||||
.get_msglevel = otx2_get_msglevel,
|
||||
.set_msglevel = otx2_set_msglevel,
|
||||
};
|
||||
|
||||
void otx2_set_ethtool_ops(struct net_device *netdev)
|
||||
|
@ -84,7 +84,7 @@ static void otx2_snd_pkt_handler(struct otx2_nic *pfvf,
|
||||
struct sk_buff *skb = NULL;
|
||||
struct sg_list *sg;
|
||||
|
||||
if (unlikely(snd_comp->status))
|
||||
if (unlikely(snd_comp->status) && netif_msg_tx_err(pfvf))
|
||||
net_err_ratelimited("%s: TX%d: Error in send CQ status:%x\n",
|
||||
pfvf->netdev->name, cq->cint_idx,
|
||||
snd_comp->status);
|
||||
@ -144,6 +144,11 @@ static bool otx2_check_rcv_errors(struct otx2_nic *pfvf,
|
||||
struct otx2_drv_stats *stats = &pfvf->hw.drv_stats;
|
||||
struct nix_rx_parse_s *parse = &cqe->parse;
|
||||
|
||||
if (netif_msg_rx_err(pfvf))
|
||||
netdev_err(pfvf->netdev,
|
||||
"RQ%d: Error pkt with errlev:0x%x errcode:0x%x\n",
|
||||
qidx, parse->errlev, parse->errcode);
|
||||
|
||||
if (parse->errlev == NPC_ERRLVL_RE) {
|
||||
switch (parse->errcode) {
|
||||
case ERRCODE_FCS:
|
||||
|
Loading…
Reference in New Issue
Block a user