slave.c (db6da59cf27b5661ced03754ae0550f8914eda9e) | slave.c (d06f925f13976ab82167c93467c70a337a0a3cda) |
---|---|
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * net/dsa/slave.c - Slave device handling 4 * Copyright (c) 2008-2009 Marvell Semiconductor 5 */ 6 7#include <linux/list.h> 8#include <linux/etherdevice.h> --- 13 unchanged lines hidden (view full) --- 22#include <net/dcbnl.h> 23#include <linux/netpoll.h> 24 25#include "dsa.h" 26#include "port.h" 27#include "master.h" 28#include "netlink.h" 29#include "slave.h" | 1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * net/dsa/slave.c - Slave device handling 4 * Copyright (c) 2008-2009 Marvell Semiconductor 5 */ 6 7#include <linux/list.h> 8#include <linux/etherdevice.h> --- 13 unchanged lines hidden (view full) --- 22#include <net/dcbnl.h> 23#include <linux/netpoll.h> 24 25#include "dsa.h" 26#include "port.h" 27#include "master.h" 28#include "netlink.h" 29#include "slave.h" |
30#include "switch.h" |
|
30#include "tag.h" 31 32struct dsa_switchdev_event_work { 33 struct net_device *dev; 34 struct net_device *orig_dev; 35 struct work_struct work; 36 unsigned long event; 37 /* Specific for SWITCHDEV_FDB_ADD_TO_DEVICE and --- 118 unchanged lines hidden (view full) --- 156 ether_addr_copy(standalone_work->addr, addr); 157 standalone_work->vid = vid; 158 159 dsa_schedule_work(&standalone_work->work); 160 161 return 0; 162} 163 | 31#include "tag.h" 32 33struct dsa_switchdev_event_work { 34 struct net_device *dev; 35 struct net_device *orig_dev; 36 struct work_struct work; 37 unsigned long event; 38 /* Specific for SWITCHDEV_FDB_ADD_TO_DEVICE and --- 118 unchanged lines hidden (view full) --- 157 ether_addr_copy(standalone_work->addr, addr); 158 standalone_work->vid = vid; 159 160 dsa_schedule_work(&standalone_work->work); 161 162 return 0; 163} 164 |
164static int dsa_slave_host_vlan_rx_filtering(struct net_device *vdev, int vid, 165 void *arg) | 165static int dsa_slave_host_vlan_rx_filtering(void *arg, int vid) |
166{ 167 struct dsa_host_vlan_rx_filtering_ctx *ctx = arg; 168 169 return dsa_slave_schedule_standalone_work(ctx->dev, ctx->event, 170 ctx->addr, vid); 171} 172 | 166{ 167 struct dsa_host_vlan_rx_filtering_ctx *ctx = arg; 168 169 return dsa_slave_schedule_standalone_work(ctx->dev, ctx->event, 170 ctx->addr, vid); 171} 172 |
173static int dsa_slave_vlan_for_each(struct net_device *dev, 174 int (*cb)(void *arg, int vid), void *arg) 175{ 176 struct dsa_port *dp = dsa_slave_to_port(dev); 177 struct dsa_vlan *v; 178 int err; 179 180 lockdep_assert_held(&dev->addr_list_lock); 181 182 err = cb(arg, 0); 183 if (err) 184 return err; 185 186 list_for_each_entry(v, &dp->user_vlans, list) { 187 err = cb(arg, v->vid); 188 if (err) 189 return err; 190 } 191 192 return 0; 193} 194 |
|
173static int dsa_slave_sync_uc(struct net_device *dev, 174 const unsigned char *addr) 175{ 176 struct net_device *master = dsa_slave_to_master(dev); 177 struct dsa_port *dp = dsa_slave_to_port(dev); 178 struct dsa_host_vlan_rx_filtering_ctx ctx = { 179 .dev = dev, 180 .addr = addr, 181 .event = DSA_UC_ADD, 182 }; | 195static int dsa_slave_sync_uc(struct net_device *dev, 196 const unsigned char *addr) 197{ 198 struct net_device *master = dsa_slave_to_master(dev); 199 struct dsa_port *dp = dsa_slave_to_port(dev); 200 struct dsa_host_vlan_rx_filtering_ctx ctx = { 201 .dev = dev, 202 .addr = addr, 203 .event = DSA_UC_ADD, 204 }; |
183 int err; | |
184 185 dev_uc_add(master, addr); 186 187 if (!dsa_switch_supports_uc_filtering(dp->ds)) 188 return 0; 189 | 205 206 dev_uc_add(master, addr); 207 208 if (!dsa_switch_supports_uc_filtering(dp->ds)) 209 return 0; 210 |
190 err = dsa_slave_schedule_standalone_work(dev, DSA_UC_ADD, addr, 0); 191 if (err) 192 return err; 193 194 return vlan_for_each(dev, dsa_slave_host_vlan_rx_filtering, &ctx); | 211 return dsa_slave_vlan_for_each(dev, dsa_slave_host_vlan_rx_filtering, 212 &ctx); |
195} 196 197static int dsa_slave_unsync_uc(struct net_device *dev, 198 const unsigned char *addr) 199{ 200 struct net_device *master = dsa_slave_to_master(dev); 201 struct dsa_port *dp = dsa_slave_to_port(dev); 202 struct dsa_host_vlan_rx_filtering_ctx ctx = { 203 .dev = dev, 204 .addr = addr, 205 .event = DSA_UC_DEL, 206 }; | 213} 214 215static int dsa_slave_unsync_uc(struct net_device *dev, 216 const unsigned char *addr) 217{ 218 struct net_device *master = dsa_slave_to_master(dev); 219 struct dsa_port *dp = dsa_slave_to_port(dev); 220 struct dsa_host_vlan_rx_filtering_ctx ctx = { 221 .dev = dev, 222 .addr = addr, 223 .event = DSA_UC_DEL, 224 }; |
207 int err; | |
208 209 dev_uc_del(master, addr); 210 211 if (!dsa_switch_supports_uc_filtering(dp->ds)) 212 return 0; 213 | 225 226 dev_uc_del(master, addr); 227 228 if (!dsa_switch_supports_uc_filtering(dp->ds)) 229 return 0; 230 |
214 err = dsa_slave_schedule_standalone_work(dev, DSA_UC_DEL, addr, 0); 215 if (err) 216 return err; 217 218 return vlan_for_each(dev, dsa_slave_host_vlan_rx_filtering, &ctx); | 231 return dsa_slave_vlan_for_each(dev, dsa_slave_host_vlan_rx_filtering, 232 &ctx); |
219} 220 221static int dsa_slave_sync_mc(struct net_device *dev, 222 const unsigned char *addr) 223{ 224 struct net_device *master = dsa_slave_to_master(dev); 225 struct dsa_port *dp = dsa_slave_to_port(dev); 226 struct dsa_host_vlan_rx_filtering_ctx ctx = { 227 .dev = dev, 228 .addr = addr, 229 .event = DSA_MC_ADD, 230 }; | 233} 234 235static int dsa_slave_sync_mc(struct net_device *dev, 236 const unsigned char *addr) 237{ 238 struct net_device *master = dsa_slave_to_master(dev); 239 struct dsa_port *dp = dsa_slave_to_port(dev); 240 struct dsa_host_vlan_rx_filtering_ctx ctx = { 241 .dev = dev, 242 .addr = addr, 243 .event = DSA_MC_ADD, 244 }; |
231 int err; | |
232 233 dev_mc_add(master, addr); 234 235 if (!dsa_switch_supports_mc_filtering(dp->ds)) 236 return 0; 237 | 245 246 dev_mc_add(master, addr); 247 248 if (!dsa_switch_supports_mc_filtering(dp->ds)) 249 return 0; 250 |
238 err = dsa_slave_schedule_standalone_work(dev, DSA_MC_ADD, addr, 0); 239 if (err) 240 return err; 241 242 return vlan_for_each(dev, dsa_slave_host_vlan_rx_filtering, &ctx); | 251 return dsa_slave_vlan_for_each(dev, dsa_slave_host_vlan_rx_filtering, 252 &ctx); |
243} 244 245static int dsa_slave_unsync_mc(struct net_device *dev, 246 const unsigned char *addr) 247{ 248 struct net_device *master = dsa_slave_to_master(dev); 249 struct dsa_port *dp = dsa_slave_to_port(dev); 250 struct dsa_host_vlan_rx_filtering_ctx ctx = { 251 .dev = dev, 252 .addr = addr, 253 .event = DSA_MC_DEL, 254 }; | 253} 254 255static int dsa_slave_unsync_mc(struct net_device *dev, 256 const unsigned char *addr) 257{ 258 struct net_device *master = dsa_slave_to_master(dev); 259 struct dsa_port *dp = dsa_slave_to_port(dev); 260 struct dsa_host_vlan_rx_filtering_ctx ctx = { 261 .dev = dev, 262 .addr = addr, 263 .event = DSA_MC_DEL, 264 }; |
255 int err; | |
256 257 dev_mc_del(master, addr); 258 259 if (!dsa_switch_supports_mc_filtering(dp->ds)) 260 return 0; 261 | 265 266 dev_mc_del(master, addr); 267 268 if (!dsa_switch_supports_mc_filtering(dp->ds)) 269 return 0; 270 |
262 err = dsa_slave_schedule_standalone_work(dev, DSA_MC_DEL, addr, 0); 263 if (err) 264 return err; 265 266 return vlan_for_each(dev, dsa_slave_host_vlan_rx_filtering, &ctx); | 271 return dsa_slave_vlan_for_each(dev, dsa_slave_host_vlan_rx_filtering, 272 &ctx); |
267} 268 269void dsa_slave_sync_ha(struct net_device *dev) 270{ 271 struct dsa_port *dp = dsa_slave_to_port(dev); 272 struct dsa_switch *ds = dp->ds; 273 struct netdev_hw_addr *ha; 274 --- 1479 unchanged lines hidden (view full) --- 1754 .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN, 1755 .vid = vid, 1756 /* This API only allows programming tagged, non-PVID VIDs */ 1757 .flags = 0, 1758 }; 1759 struct netlink_ext_ack extack = {0}; 1760 struct dsa_switch *ds = dp->ds; 1761 struct netdev_hw_addr *ha; | 273} 274 275void dsa_slave_sync_ha(struct net_device *dev) 276{ 277 struct dsa_port *dp = dsa_slave_to_port(dev); 278 struct dsa_switch *ds = dp->ds; 279 struct netdev_hw_addr *ha; 280 --- 1479 unchanged lines hidden (view full) --- 1760 .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN, 1761 .vid = vid, 1762 /* This API only allows programming tagged, non-PVID VIDs */ 1763 .flags = 0, 1764 }; 1765 struct netlink_ext_ack extack = {0}; 1766 struct dsa_switch *ds = dp->ds; 1767 struct netdev_hw_addr *ha; |
1768 struct dsa_vlan *v; |
|
1762 int ret; 1763 1764 /* User port... */ 1765 ret = dsa_port_vlan_add(dp, &vlan, &extack); 1766 if (ret) { 1767 if (extack._msg) 1768 netdev_err(dev, "%s\n", extack._msg); 1769 return ret; --- 7 unchanged lines hidden (view full) --- 1777 extack._msg); 1778 return ret; 1779 } 1780 1781 if (!dsa_switch_supports_uc_filtering(ds) && 1782 !dsa_switch_supports_mc_filtering(ds)) 1783 return 0; 1784 | 1769 int ret; 1770 1771 /* User port... */ 1772 ret = dsa_port_vlan_add(dp, &vlan, &extack); 1773 if (ret) { 1774 if (extack._msg) 1775 netdev_err(dev, "%s\n", extack._msg); 1776 return ret; --- 7 unchanged lines hidden (view full) --- 1784 extack._msg); 1785 return ret; 1786 } 1787 1788 if (!dsa_switch_supports_uc_filtering(ds) && 1789 !dsa_switch_supports_mc_filtering(ds)) 1790 return 0; 1791 |
1792 v = kzalloc(sizeof(*v), GFP_KERNEL); 1793 if (!v) { 1794 ret = -ENOMEM; 1795 goto rollback; 1796 } 1797 |
|
1785 netif_addr_lock_bh(dev); 1786 | 1798 netif_addr_lock_bh(dev); 1799 |
1800 v->vid = vid; 1801 list_add_tail(&v->list, &dp->user_vlans); 1802 |
|
1787 if (dsa_switch_supports_mc_filtering(ds)) { 1788 netdev_for_each_synced_mc_addr(ha, dev) { 1789 dsa_slave_schedule_standalone_work(dev, DSA_MC_ADD, 1790 ha->addr, vid); 1791 } 1792 } 1793 1794 if (dsa_switch_supports_uc_filtering(ds)) { 1795 netdev_for_each_synced_uc_addr(ha, dev) { 1796 dsa_slave_schedule_standalone_work(dev, DSA_UC_ADD, 1797 ha->addr, vid); 1798 } 1799 } 1800 1801 netif_addr_unlock_bh(dev); 1802 1803 dsa_flush_workqueue(); 1804 1805 return 0; | 1803 if (dsa_switch_supports_mc_filtering(ds)) { 1804 netdev_for_each_synced_mc_addr(ha, dev) { 1805 dsa_slave_schedule_standalone_work(dev, DSA_MC_ADD, 1806 ha->addr, vid); 1807 } 1808 } 1809 1810 if (dsa_switch_supports_uc_filtering(ds)) { 1811 netdev_for_each_synced_uc_addr(ha, dev) { 1812 dsa_slave_schedule_standalone_work(dev, DSA_UC_ADD, 1813 ha->addr, vid); 1814 } 1815 } 1816 1817 netif_addr_unlock_bh(dev); 1818 1819 dsa_flush_workqueue(); 1820 1821 return 0; |
1822 1823rollback: 1824 dsa_port_host_vlan_del(dp, &vlan); 1825 dsa_port_vlan_del(dp, &vlan); 1826 1827 return ret; |
|
1806} 1807 1808static int dsa_slave_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, 1809 u16 vid) 1810{ 1811 struct dsa_port *dp = dsa_slave_to_port(dev); 1812 struct switchdev_obj_port_vlan vlan = { 1813 .vid = vid, 1814 /* This API only allows programming tagged, non-PVID VIDs */ 1815 .flags = 0, 1816 }; 1817 struct dsa_switch *ds = dp->ds; 1818 struct netdev_hw_addr *ha; | 1828} 1829 1830static int dsa_slave_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, 1831 u16 vid) 1832{ 1833 struct dsa_port *dp = dsa_slave_to_port(dev); 1834 struct switchdev_obj_port_vlan vlan = { 1835 .vid = vid, 1836 /* This API only allows programming tagged, non-PVID VIDs */ 1837 .flags = 0, 1838 }; 1839 struct dsa_switch *ds = dp->ds; 1840 struct netdev_hw_addr *ha; |
1841 struct dsa_vlan *v; |
|
1819 int err; 1820 1821 err = dsa_port_vlan_del(dp, &vlan); 1822 if (err) 1823 return err; 1824 1825 err = dsa_port_host_vlan_del(dp, &vlan); 1826 if (err) 1827 return err; 1828 1829 if (!dsa_switch_supports_uc_filtering(ds) && 1830 !dsa_switch_supports_mc_filtering(ds)) 1831 return 0; 1832 1833 netif_addr_lock_bh(dev); 1834 | 1842 int err; 1843 1844 err = dsa_port_vlan_del(dp, &vlan); 1845 if (err) 1846 return err; 1847 1848 err = dsa_port_host_vlan_del(dp, &vlan); 1849 if (err) 1850 return err; 1851 1852 if (!dsa_switch_supports_uc_filtering(ds) && 1853 !dsa_switch_supports_mc_filtering(ds)) 1854 return 0; 1855 1856 netif_addr_lock_bh(dev); 1857 |
1858 v = dsa_vlan_find(&dp->user_vlans, &vlan); 1859 if (!v) { 1860 netif_addr_unlock_bh(dev); 1861 return -ENOENT; 1862 } 1863 1864 list_del(&v->list); 1865 kfree(v); 1866 |
|
1835 if (dsa_switch_supports_mc_filtering(ds)) { 1836 netdev_for_each_synced_mc_addr(ha, dev) { 1837 dsa_slave_schedule_standalone_work(dev, DSA_MC_DEL, 1838 ha->addr, vid); 1839 } 1840 } 1841 1842 if (dsa_switch_supports_uc_filtering(ds)) { --- 1845 unchanged lines hidden --- | 1867 if (dsa_switch_supports_mc_filtering(ds)) { 1868 netdev_for_each_synced_mc_addr(ha, dev) { 1869 dsa_slave_schedule_standalone_work(dev, DSA_MC_DEL, 1870 ha->addr, vid); 1871 } 1872 } 1873 1874 if (dsa_switch_supports_uc_filtering(ds)) { --- 1845 unchanged lines hidden --- |