Skip to content

Commit 9afad4a

Browse files
bmarreddykuba-moo
authored andcommitted
bng_en: Configure default VNIC
Add functions to add a filter to the VNIC to configure unicast addresses. Also, add multicast, broadcast, and promiscuous settings to the default VNIC. Signed-off-by: Bhargava Marreddy <[email protected]> Reviewed-by: Vikas Gupta <[email protected]> Reviewed-by: Rajashekar Hudumula <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 58930c0 commit 9afad4a

File tree

4 files changed

+386
-0
lines changed

4 files changed

+386
-0
lines changed

drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -854,6 +854,78 @@ void bnge_hwrm_update_rss_hash_cfg(struct bnge_net *bn)
854854
bnge_hwrm_req_drop(bd, req);
855855
}
856856

857+
int bnge_hwrm_l2_filter_free(struct bnge_dev *bd, struct bnge_l2_filter *fltr)
858+
{
859+
struct hwrm_cfa_l2_filter_free_input *req;
860+
int rc;
861+
862+
rc = bnge_hwrm_req_init(bd, req, HWRM_CFA_L2_FILTER_FREE);
863+
if (rc)
864+
return rc;
865+
866+
req->l2_filter_id = fltr->base.filter_id;
867+
return bnge_hwrm_req_send(bd, req);
868+
}
869+
870+
int bnge_hwrm_l2_filter_alloc(struct bnge_dev *bd, struct bnge_l2_filter *fltr)
871+
{
872+
struct hwrm_cfa_l2_filter_alloc_output *resp;
873+
struct hwrm_cfa_l2_filter_alloc_input *req;
874+
int rc;
875+
876+
rc = bnge_hwrm_req_init(bd, req, HWRM_CFA_L2_FILTER_ALLOC);
877+
if (rc)
878+
return rc;
879+
880+
req->flags = cpu_to_le32(CFA_L2_FILTER_ALLOC_REQ_FLAGS_PATH_RX);
881+
882+
req->flags |= cpu_to_le32(CFA_L2_FILTER_ALLOC_REQ_FLAGS_OUTERMOST);
883+
req->dst_id = cpu_to_le16(fltr->base.fw_vnic_id);
884+
req->enables =
885+
cpu_to_le32(CFA_L2_FILTER_ALLOC_REQ_ENABLES_L2_ADDR |
886+
CFA_L2_FILTER_ALLOC_REQ_ENABLES_DST_ID |
887+
CFA_L2_FILTER_ALLOC_REQ_ENABLES_L2_ADDR_MASK);
888+
ether_addr_copy(req->l2_addr, fltr->l2_key.dst_mac_addr);
889+
eth_broadcast_addr(req->l2_addr_mask);
890+
891+
if (fltr->l2_key.vlan) {
892+
req->enables |=
893+
cpu_to_le32(CFA_L2_FILTER_ALLOC_REQ_ENABLES_L2_IVLAN |
894+
CFA_L2_FILTER_ALLOC_REQ_ENABLES_L2_IVLAN_MASK |
895+
CFA_L2_FILTER_ALLOC_REQ_ENABLES_NUM_VLANS);
896+
req->num_vlans = 1;
897+
req->l2_ivlan = cpu_to_le16(fltr->l2_key.vlan);
898+
req->l2_ivlan_mask = cpu_to_le16(0xfff);
899+
}
900+
901+
resp = bnge_hwrm_req_hold(bd, req);
902+
rc = bnge_hwrm_req_send(bd, req);
903+
if (!rc)
904+
fltr->base.filter_id = resp->l2_filter_id;
905+
906+
bnge_hwrm_req_drop(bd, req);
907+
return rc;
908+
}
909+
910+
int bnge_hwrm_cfa_l2_set_rx_mask(struct bnge_dev *bd,
911+
struct bnge_vnic_info *vnic)
912+
{
913+
struct hwrm_cfa_l2_set_rx_mask_input *req;
914+
int rc;
915+
916+
rc = bnge_hwrm_req_init(bd, req, HWRM_CFA_L2_SET_RX_MASK);
917+
if (rc)
918+
return rc;
919+
920+
req->vnic_id = cpu_to_le32(vnic->fw_vnic_id);
921+
if (vnic->rx_mask & CFA_L2_SET_RX_MASK_REQ_MASK_MCAST) {
922+
req->num_mc_entries = cpu_to_le32(vnic->mc_list_count);
923+
req->mc_tbl_addr = cpu_to_le64(vnic->mc_list_mapping);
924+
}
925+
req->mask = cpu_to_le32(vnic->rx_mask);
926+
return bnge_hwrm_req_send_silent(bd, req);
927+
}
928+
857929
int bnge_hwrm_vnic_alloc(struct bnge_dev *bd, struct bnge_vnic_info *vnic,
858930
unsigned int nr_rings)
859931
{

drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ int bnge_hwrm_vnic_alloc(struct bnge_dev *bd, struct bnge_vnic_info *vnic,
4343
void bnge_hwrm_vnic_free_one(struct bnge_dev *bd, struct bnge_vnic_info *vnic);
4444
void bnge_hwrm_vnic_ctx_free_one(struct bnge_dev *bd,
4545
struct bnge_vnic_info *vnic, u16 ctx_idx);
46+
int bnge_hwrm_l2_filter_free(struct bnge_dev *bd, struct bnge_l2_filter *fltr);
47+
int bnge_hwrm_l2_filter_alloc(struct bnge_dev *bd, struct bnge_l2_filter *fltr);
48+
int bnge_hwrm_cfa_l2_set_rx_mask(struct bnge_dev *bd,
49+
struct bnge_vnic_info *vnic);
4650
void bnge_hwrm_stat_ctx_free(struct bnge_net *bn);
4751
int bnge_hwrm_stat_ctx_alloc(struct bnge_net *bn);
4852
int hwrm_ring_free_send_msg(struct bnge_net *bn, struct bnge_ring_struct *ring,

drivers/net/ethernet/broadcom/bnge/bnge_netdev.c

Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1531,6 +1531,230 @@ static int bnge_setup_vnic(struct bnge_net *bn, struct bnge_vnic_info *vnic)
15311531
return rc;
15321532
}
15331533

1534+
static void bnge_del_l2_filter(struct bnge_net *bn, struct bnge_l2_filter *fltr)
1535+
{
1536+
if (!refcount_dec_and_test(&fltr->refcnt))
1537+
return;
1538+
hlist_del_rcu(&fltr->base.hash);
1539+
kfree_rcu(fltr, base.rcu);
1540+
}
1541+
1542+
static void bnge_init_l2_filter(struct bnge_net *bn,
1543+
struct bnge_l2_filter *fltr,
1544+
struct bnge_l2_key *key, u32 idx)
1545+
{
1546+
struct hlist_head *head;
1547+
1548+
ether_addr_copy(fltr->l2_key.dst_mac_addr, key->dst_mac_addr);
1549+
fltr->l2_key.vlan = key->vlan;
1550+
fltr->base.type = BNGE_FLTR_TYPE_L2;
1551+
1552+
head = &bn->l2_fltr_hash_tbl[idx];
1553+
hlist_add_head_rcu(&fltr->base.hash, head);
1554+
refcount_set(&fltr->refcnt, 1);
1555+
}
1556+
1557+
static struct bnge_l2_filter *__bnge_lookup_l2_filter(struct bnge_net *bn,
1558+
struct bnge_l2_key *key,
1559+
u32 idx)
1560+
{
1561+
struct bnge_l2_filter *fltr;
1562+
struct hlist_head *head;
1563+
1564+
head = &bn->l2_fltr_hash_tbl[idx];
1565+
hlist_for_each_entry_rcu(fltr, head, base.hash) {
1566+
struct bnge_l2_key *l2_key = &fltr->l2_key;
1567+
1568+
if (ether_addr_equal(l2_key->dst_mac_addr, key->dst_mac_addr) &&
1569+
l2_key->vlan == key->vlan)
1570+
return fltr;
1571+
}
1572+
return NULL;
1573+
}
1574+
1575+
static struct bnge_l2_filter *bnge_lookup_l2_filter(struct bnge_net *bn,
1576+
struct bnge_l2_key *key,
1577+
u32 idx)
1578+
{
1579+
struct bnge_l2_filter *fltr;
1580+
1581+
rcu_read_lock();
1582+
fltr = __bnge_lookup_l2_filter(bn, key, idx);
1583+
if (fltr)
1584+
refcount_inc(&fltr->refcnt);
1585+
rcu_read_unlock();
1586+
return fltr;
1587+
}
1588+
1589+
static struct bnge_l2_filter *bnge_alloc_l2_filter(struct bnge_net *bn,
1590+
struct bnge_l2_key *key,
1591+
gfp_t gfp)
1592+
{
1593+
struct bnge_l2_filter *fltr;
1594+
u32 idx;
1595+
1596+
idx = jhash2(&key->filter_key, BNGE_L2_KEY_SIZE, bn->hash_seed) &
1597+
BNGE_L2_FLTR_HASH_MASK;
1598+
fltr = bnge_lookup_l2_filter(bn, key, idx);
1599+
if (fltr)
1600+
return fltr;
1601+
1602+
fltr = kzalloc(sizeof(*fltr), gfp);
1603+
if (!fltr)
1604+
return ERR_PTR(-ENOMEM);
1605+
1606+
bnge_init_l2_filter(bn, fltr, key, idx);
1607+
return fltr;
1608+
}
1609+
1610+
static int bnge_hwrm_set_vnic_filter(struct bnge_net *bn, u16 vnic_id, u16 idx,
1611+
const u8 *mac_addr)
1612+
{
1613+
struct bnge_l2_filter *fltr;
1614+
struct bnge_l2_key key;
1615+
int rc;
1616+
1617+
ether_addr_copy(key.dst_mac_addr, mac_addr);
1618+
key.vlan = 0;
1619+
fltr = bnge_alloc_l2_filter(bn, &key, GFP_KERNEL);
1620+
if (IS_ERR(fltr))
1621+
return PTR_ERR(fltr);
1622+
1623+
fltr->base.fw_vnic_id = bn->vnic_info[vnic_id].fw_vnic_id;
1624+
rc = bnge_hwrm_l2_filter_alloc(bn->bd, fltr);
1625+
if (rc)
1626+
goto err_del_l2_filter;
1627+
bn->vnic_info[vnic_id].l2_filters[idx] = fltr;
1628+
return rc;
1629+
1630+
err_del_l2_filter:
1631+
bnge_del_l2_filter(bn, fltr);
1632+
return rc;
1633+
}
1634+
1635+
static bool bnge_mc_list_updated(struct bnge_net *bn, u32 *rx_mask)
1636+
{
1637+
struct bnge_vnic_info *vnic = &bn->vnic_info[BNGE_VNIC_DEFAULT];
1638+
struct net_device *dev = bn->netdev;
1639+
struct netdev_hw_addr *ha;
1640+
int mc_count = 0, off = 0;
1641+
bool update = false;
1642+
u8 *haddr;
1643+
1644+
netdev_for_each_mc_addr(ha, dev) {
1645+
if (mc_count >= BNGE_MAX_MC_ADDRS) {
1646+
*rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_ALL_MCAST;
1647+
vnic->mc_list_count = 0;
1648+
return false;
1649+
}
1650+
haddr = ha->addr;
1651+
if (!ether_addr_equal(haddr, vnic->mc_list + off)) {
1652+
memcpy(vnic->mc_list + off, haddr, ETH_ALEN);
1653+
update = true;
1654+
}
1655+
off += ETH_ALEN;
1656+
mc_count++;
1657+
}
1658+
if (mc_count)
1659+
*rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_MCAST;
1660+
1661+
if (mc_count != vnic->mc_list_count) {
1662+
vnic->mc_list_count = mc_count;
1663+
update = true;
1664+
}
1665+
return update;
1666+
}
1667+
1668+
static bool bnge_uc_list_updated(struct bnge_net *bn)
1669+
{
1670+
struct bnge_vnic_info *vnic = &bn->vnic_info[BNGE_VNIC_DEFAULT];
1671+
struct net_device *dev = bn->netdev;
1672+
struct netdev_hw_addr *ha;
1673+
int off = 0;
1674+
1675+
if (netdev_uc_count(dev) != (vnic->uc_filter_count - 1))
1676+
return true;
1677+
1678+
netdev_for_each_uc_addr(ha, dev) {
1679+
if (!ether_addr_equal(ha->addr, vnic->uc_list + off))
1680+
return true;
1681+
1682+
off += ETH_ALEN;
1683+
}
1684+
return false;
1685+
}
1686+
1687+
static bool bnge_promisc_ok(struct bnge_net *bn)
1688+
{
1689+
return true;
1690+
}
1691+
1692+
static int bnge_cfg_def_vnic(struct bnge_net *bn)
1693+
{
1694+
struct bnge_vnic_info *vnic = &bn->vnic_info[BNGE_VNIC_DEFAULT];
1695+
struct net_device *dev = bn->netdev;
1696+
struct bnge_dev *bd = bn->bd;
1697+
struct netdev_hw_addr *ha;
1698+
int i, off = 0, rc;
1699+
bool uc_update;
1700+
1701+
netif_addr_lock_bh(dev);
1702+
uc_update = bnge_uc_list_updated(bn);
1703+
netif_addr_unlock_bh(dev);
1704+
1705+
if (!uc_update)
1706+
goto skip_uc;
1707+
1708+
for (i = 1; i < vnic->uc_filter_count; i++) {
1709+
struct bnge_l2_filter *fltr = vnic->l2_filters[i];
1710+
1711+
bnge_hwrm_l2_filter_free(bd, fltr);
1712+
bnge_del_l2_filter(bn, fltr);
1713+
}
1714+
1715+
vnic->uc_filter_count = 1;
1716+
1717+
netif_addr_lock_bh(dev);
1718+
if (netdev_uc_count(dev) > (BNGE_MAX_UC_ADDRS - 1)) {
1719+
vnic->rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS;
1720+
} else {
1721+
netdev_for_each_uc_addr(ha, dev) {
1722+
memcpy(vnic->uc_list + off, ha->addr, ETH_ALEN);
1723+
off += ETH_ALEN;
1724+
vnic->uc_filter_count++;
1725+
}
1726+
}
1727+
netif_addr_unlock_bh(dev);
1728+
1729+
for (i = 1, off = 0; i < vnic->uc_filter_count; i++, off += ETH_ALEN) {
1730+
rc = bnge_hwrm_set_vnic_filter(bn, 0, i, vnic->uc_list + off);
1731+
if (rc) {
1732+
netdev_err(dev, "HWRM vnic filter failure rc: %d\n", rc);
1733+
vnic->uc_filter_count = i;
1734+
return rc;
1735+
}
1736+
}
1737+
1738+
skip_uc:
1739+
if ((vnic->rx_mask & CFA_L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS) &&
1740+
!bnge_promisc_ok(bn))
1741+
vnic->rx_mask &= ~CFA_L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS;
1742+
rc = bnge_hwrm_cfa_l2_set_rx_mask(bd, vnic);
1743+
if (rc && (vnic->rx_mask & CFA_L2_SET_RX_MASK_REQ_MASK_MCAST)) {
1744+
netdev_info(dev, "Failed setting MC filters rc: %d, turning on ALL_MCAST mode\n",
1745+
rc);
1746+
vnic->rx_mask &= ~CFA_L2_SET_RX_MASK_REQ_MASK_MCAST;
1747+
vnic->rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_ALL_MCAST;
1748+
vnic->mc_list_count = 0;
1749+
rc = bnge_hwrm_cfa_l2_set_rx_mask(bd, vnic);
1750+
}
1751+
if (rc)
1752+
netdev_err(dev, "HWRM cfa l2 rx mask failure rc: %d\n",
1753+
rc);
1754+
1755+
return rc;
1756+
}
1757+
15341758
static void bnge_hwrm_vnic_free(struct bnge_net *bn)
15351759
{
15361760
int i;
@@ -1554,8 +1778,24 @@ static void bnge_hwrm_vnic_ctx_free(struct bnge_net *bn)
15541778
bn->rsscos_nr_ctxs = 0;
15551779
}
15561780

1781+
static void bnge_hwrm_clear_vnic_filter(struct bnge_net *bn)
1782+
{
1783+
struct bnge_vnic_info *vnic = &bn->vnic_info[BNGE_VNIC_DEFAULT];
1784+
int i;
1785+
1786+
for (i = 0; i < vnic->uc_filter_count; i++) {
1787+
struct bnge_l2_filter *fltr = vnic->l2_filters[i];
1788+
1789+
bnge_hwrm_l2_filter_free(bn->bd, fltr);
1790+
bnge_del_l2_filter(bn, fltr);
1791+
}
1792+
1793+
vnic->uc_filter_count = 0;
1794+
}
1795+
15571796
static void bnge_clear_vnic(struct bnge_net *bn)
15581797
{
1798+
bnge_hwrm_clear_vnic_filter(bn);
15591799
bnge_hwrm_vnic_free(bn);
15601800
bnge_hwrm_vnic_ctx_free(bn);
15611801
}
@@ -1808,6 +2048,36 @@ static int bnge_init_chip(struct bnge_net *bn)
18082048

18092049
if (bd->rss_cap & BNGE_RSS_CAP_RSS_HASH_TYPE_DELTA)
18102050
bnge_hwrm_update_rss_hash_cfg(bn);
2051+
2052+
/* Filter for default vnic 0 */
2053+
rc = bnge_hwrm_set_vnic_filter(bn, 0, 0, bn->netdev->dev_addr);
2054+
if (rc) {
2055+
netdev_err(bn->netdev, "HWRM vnic filter failure rc: %d\n", rc);
2056+
goto err_out;
2057+
}
2058+
vnic->uc_filter_count = 1;
2059+
2060+
vnic->rx_mask = 0;
2061+
2062+
if (bn->netdev->flags & IFF_BROADCAST)
2063+
vnic->rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_BCAST;
2064+
2065+
if (bn->netdev->flags & IFF_PROMISC)
2066+
vnic->rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS;
2067+
2068+
if (bn->netdev->flags & IFF_ALLMULTI) {
2069+
vnic->rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_ALL_MCAST;
2070+
vnic->mc_list_count = 0;
2071+
} else if (bn->netdev->flags & IFF_MULTICAST) {
2072+
u32 mask = 0;
2073+
2074+
bnge_mc_list_updated(bn, &mask);
2075+
vnic->rx_mask |= mask;
2076+
}
2077+
2078+
rc = bnge_cfg_def_vnic(bn);
2079+
if (rc)
2080+
goto err_out;
18112081
return 0;
18122082

18132083
err_out:

0 commit comments

Comments
 (0)