Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: bcmgenet: add RX_CLS_LOC_ANY support

If a matching flow spec exists its current location is as good
as ANY. If not add the new flow spec at the first available
location.

Signed-off-by: Doug Berger <opendmb@gmail.com>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Link: https://lore.kernel.org/r/20221019215123.316997-1-opendmb@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Doug Berger and committed by
Jakub Kicinski
070f822d 377eb9aa

+27 -4
+27 -4
drivers/net/ethernet/broadcom/genet/bcmgenet.c
··· 1387 1387 struct ethtool_usrip4_spec *l4_mask; 1388 1388 struct ethhdr *eth_mask; 1389 1389 1390 - if (cmd->fs.location >= MAX_NUM_OF_FS_RULES) { 1390 + if (cmd->fs.location >= MAX_NUM_OF_FS_RULES && 1391 + cmd->fs.location != RX_CLS_LOC_ANY) { 1391 1392 netdev_err(dev, "rxnfc: Invalid location (%d)\n", 1392 1393 cmd->fs.location); 1393 1394 return -EINVAL; ··· 1453 1452 { 1454 1453 struct bcmgenet_priv *priv = netdev_priv(dev); 1455 1454 struct bcmgenet_rxnfc_rule *loc_rule; 1456 - int err; 1455 + int err, i; 1457 1456 1458 1457 if (priv->hw_params->hfb_filter_size < 128) { 1459 1458 netdev_err(dev, "rxnfc: Not supported by this device\n"); ··· 1471 1470 if (err) 1472 1471 return err; 1473 1472 1474 - loc_rule = &priv->rxnfc_rules[cmd->fs.location]; 1473 + if (cmd->fs.location == RX_CLS_LOC_ANY) { 1474 + list_for_each_entry(loc_rule, &priv->rxnfc_list, list) { 1475 + cmd->fs.location = loc_rule->fs.location; 1476 + err = memcmp(&loc_rule->fs, &cmd->fs, 1477 + sizeof(struct ethtool_rx_flow_spec)); 1478 + if (!err) 1479 + /* rule exists so return current location */ 1480 + return 0; 1481 + } 1482 + for (i = 0; i < MAX_NUM_OF_FS_RULES; i++) { 1483 + loc_rule = &priv->rxnfc_rules[i]; 1484 + if (loc_rule->state == BCMGENET_RXNFC_STATE_UNUSED) { 1485 + cmd->fs.location = i; 1486 + break; 1487 + } 1488 + } 1489 + if (i == MAX_NUM_OF_FS_RULES) { 1490 + cmd->fs.location = RX_CLS_LOC_ANY; 1491 + return -ENOSPC; 1492 + } 1493 + } else { 1494 + loc_rule = &priv->rxnfc_rules[cmd->fs.location]; 1495 + } 1475 1496 if (loc_rule->state == BCMGENET_RXNFC_STATE_ENABLED) 1476 1497 bcmgenet_hfb_disable_filter(priv, cmd->fs.location); 1477 1498 if (loc_rule->state != BCMGENET_RXNFC_STATE_UNUSED) { ··· 1606 1583 break; 1607 1584 case ETHTOOL_GRXCLSRLCNT: 1608 1585 cmd->rule_cnt = bcmgenet_get_num_flows(priv); 1609 - cmd->data = MAX_NUM_OF_FS_RULES; 1586 + cmd->data = MAX_NUM_OF_FS_RULES | RX_CLS_LOC_SPECIAL; 1610 1587 break; 1611 1588 case ETHTOOL_GRXCLSRULE: 1612 1589 err = bcmgenet_get_flow(dev, cmd, cmd->fs.location);