mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-04 10:56:06 -04:00
net: ti: icssg-prueth: Add Support for Multicast filtering with VLAN in HSR mode
Add multicast filtering support for VLAN interfaces in HSR offload mode for ICSSG driver. The driver calls vlan_for_each() API on the hsr device's ndev to get the list of available vlans for the hsr device. The driver then sync mc addr of vlan interface with a locally mainatined list emac->vlan_mcast_list[vid] using __hw_addr_sync_multiple() API. The driver then calls the sync / unsync callbacks. In the sync / unsync call back, driver checks if the vdev's real dev is hsr device or not. If the real dev is hsr device, driver gets the per port device using hsr_get_port_ndev() and then driver passes appropriate vid to FDB helper functions. Signed-off-by: MD Danish Anwar <danishanwar@ti.com> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
committed by
Paolo Abeni
parent
9c10dd8eed
commit
161087db66
@@ -604,32 +604,66 @@ static int icssg_prueth_del_mcast(struct net_device *ndev, const u8 *addr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int icssg_prueth_hsr_add_mcast(struct net_device *ndev, const u8 *addr)
|
||||
static void icssg_prueth_hsr_fdb_add_del(struct prueth_emac *emac,
|
||||
const u8 *addr, u8 vid, bool add)
|
||||
{
|
||||
struct prueth_emac *emac = netdev_priv(ndev);
|
||||
struct prueth *prueth = emac->prueth;
|
||||
|
||||
icssg_fdb_add_del(emac, addr, prueth->default_vlan,
|
||||
icssg_fdb_add_del(emac, addr, vid,
|
||||
ICSSG_FDB_ENTRY_P0_MEMBERSHIP |
|
||||
ICSSG_FDB_ENTRY_P1_MEMBERSHIP |
|
||||
ICSSG_FDB_ENTRY_P2_MEMBERSHIP |
|
||||
ICSSG_FDB_ENTRY_BLOCK, true);
|
||||
ICSSG_FDB_ENTRY_BLOCK, add);
|
||||
|
||||
if (add)
|
||||
icssg_vtbl_modify(emac, vid, BIT(emac->port_id),
|
||||
BIT(emac->port_id), add);
|
||||
}
|
||||
|
||||
static int icssg_prueth_hsr_add_mcast(struct net_device *ndev, const u8 *addr)
|
||||
{
|
||||
struct net_device *real_dev;
|
||||
struct prueth_emac *emac;
|
||||
u8 vlan_id, i;
|
||||
|
||||
vlan_id = is_vlan_dev(ndev) ? vlan_dev_vlan_id(ndev) : PRUETH_DFLT_VLAN_HSR;
|
||||
real_dev = is_vlan_dev(ndev) ? vlan_dev_real_dev(ndev) : ndev;
|
||||
|
||||
if (is_hsr_master(real_dev)) {
|
||||
for (i = HSR_PT_SLAVE_A; i < HSR_PT_INTERLINK; i++) {
|
||||
emac = netdev_priv(hsr_get_port_ndev(real_dev, i));
|
||||
if (!emac)
|
||||
return -EINVAL;
|
||||
icssg_prueth_hsr_fdb_add_del(emac, addr, vlan_id,
|
||||
true);
|
||||
}
|
||||
} else {
|
||||
emac = netdev_priv(real_dev);
|
||||
icssg_prueth_hsr_fdb_add_del(emac, addr, vlan_id, true);
|
||||
}
|
||||
|
||||
icssg_vtbl_modify(emac, emac->port_vlan, BIT(emac->port_id),
|
||||
BIT(emac->port_id), true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int icssg_prueth_hsr_del_mcast(struct net_device *ndev, const u8 *addr)
|
||||
{
|
||||
struct prueth_emac *emac = netdev_priv(ndev);
|
||||
struct prueth *prueth = emac->prueth;
|
||||
struct net_device *real_dev;
|
||||
struct prueth_emac *emac;
|
||||
u8 vlan_id, i;
|
||||
|
||||
icssg_fdb_add_del(emac, addr, prueth->default_vlan,
|
||||
ICSSG_FDB_ENTRY_P0_MEMBERSHIP |
|
||||
ICSSG_FDB_ENTRY_P1_MEMBERSHIP |
|
||||
ICSSG_FDB_ENTRY_P2_MEMBERSHIP |
|
||||
ICSSG_FDB_ENTRY_BLOCK, false);
|
||||
vlan_id = is_vlan_dev(ndev) ? vlan_dev_vlan_id(ndev) : PRUETH_DFLT_VLAN_HSR;
|
||||
real_dev = is_vlan_dev(ndev) ? vlan_dev_real_dev(ndev) : ndev;
|
||||
|
||||
if (is_hsr_master(real_dev)) {
|
||||
for (i = HSR_PT_SLAVE_A; i < HSR_PT_INTERLINK; i++) {
|
||||
emac = netdev_priv(hsr_get_port_ndev(real_dev, i));
|
||||
if (!emac)
|
||||
return -EINVAL;
|
||||
icssg_prueth_hsr_fdb_add_del(emac, addr, vlan_id,
|
||||
false);
|
||||
}
|
||||
} else {
|
||||
emac = netdev_priv(real_dev);
|
||||
icssg_prueth_hsr_fdb_add_del(emac, addr, vlan_id, false);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -647,8 +681,14 @@ static int icssg_update_vlan_mcast(struct net_device *vdev, int vid,
|
||||
vdev->addr_len);
|
||||
netif_addr_unlock_bh(vdev);
|
||||
|
||||
__hw_addr_sync_dev(&emac->vlan_mcast_list[vid], vdev,
|
||||
icssg_prueth_add_mcast, icssg_prueth_del_mcast);
|
||||
if (emac->prueth->is_hsr_offload_mode)
|
||||
__hw_addr_sync_dev(&emac->vlan_mcast_list[vid], vdev,
|
||||
icssg_prueth_hsr_add_mcast,
|
||||
icssg_prueth_hsr_del_mcast);
|
||||
else
|
||||
__hw_addr_sync_dev(&emac->vlan_mcast_list[vid], vdev,
|
||||
icssg_prueth_add_mcast,
|
||||
icssg_prueth_del_mcast);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -893,6 +933,11 @@ static void emac_ndo_set_rx_mode_work(struct work_struct *work)
|
||||
if (emac->prueth->is_hsr_offload_mode) {
|
||||
__dev_mc_sync(ndev, icssg_prueth_hsr_add_mcast,
|
||||
icssg_prueth_hsr_del_mcast);
|
||||
if (rtnl_trylock()) {
|
||||
vlan_for_each(emac->prueth->hsr_dev,
|
||||
icssg_update_vlan_mcast, emac);
|
||||
rtnl_unlock();
|
||||
}
|
||||
} else {
|
||||
__dev_mc_sync(ndev, icssg_prueth_add_mcast,
|
||||
icssg_prueth_del_mcast);
|
||||
@@ -1290,7 +1335,7 @@ static int prueth_netdevice_port_link(struct net_device *ndev,
|
||||
if (prueth->br_members & BIT(PRUETH_PORT_MII0) &&
|
||||
prueth->br_members & BIT(PRUETH_PORT_MII1)) {
|
||||
prueth->is_switch_mode = true;
|
||||
prueth->default_vlan = 1;
|
||||
prueth->default_vlan = PRUETH_DFLT_VLAN_SW;
|
||||
emac->port_vlan = prueth->default_vlan;
|
||||
icssg_change_mode(prueth);
|
||||
}
|
||||
@@ -1348,7 +1393,7 @@ static int prueth_hsr_port_link(struct net_device *ndev)
|
||||
NETIF_PRUETH_HSR_OFFLOAD_FEATURES))
|
||||
return -EOPNOTSUPP;
|
||||
prueth->is_hsr_offload_mode = true;
|
||||
prueth->default_vlan = 1;
|
||||
prueth->default_vlan = PRUETH_DFLT_VLAN_HSR;
|
||||
emac0->port_vlan = prueth->default_vlan;
|
||||
emac1->port_vlan = prueth->default_vlan;
|
||||
icssg_change_mode(prueth);
|
||||
|
||||
@@ -84,6 +84,8 @@
|
||||
#define ICSS_CMD_ADD_MAC 0x8
|
||||
|
||||
/* VLAN Filtering Related MACROs */
|
||||
#define PRUETH_DFLT_VLAN_HSR 1
|
||||
#define PRUETH_DFLT_VLAN_SW 1
|
||||
#define PRUETH_DFLT_VLAN_MAC 0
|
||||
#define MAX_VLAN_ID 256
|
||||
|
||||
|
||||
Reference in New Issue
Block a user