@@ -1332,19 +1332,142 @@ static int dsa_slave_netdevice_event(struct notifier_block *nb,
1332
1332
return NOTIFY_DONE ;
1333
1333
}
1334
1334
1335
+ struct dsa_switchdev_event_work {
1336
+ struct work_struct work ;
1337
+ struct switchdev_notifier_fdb_info fdb_info ;
1338
+ struct net_device * dev ;
1339
+ unsigned long event ;
1340
+ };
1341
+
1342
+ static void dsa_slave_switchdev_event_work (struct work_struct * work )
1343
+ {
1344
+ struct dsa_switchdev_event_work * switchdev_work =
1345
+ container_of (work , struct dsa_switchdev_event_work , work );
1346
+ struct net_device * dev = switchdev_work -> dev ;
1347
+ struct switchdev_notifier_fdb_info * fdb_info ;
1348
+ struct dsa_slave_priv * p = netdev_priv (dev );
1349
+ int err ;
1350
+
1351
+ rtnl_lock ();
1352
+ switch (switchdev_work -> event ) {
1353
+ case SWITCHDEV_FDB_ADD_TO_DEVICE :
1354
+ fdb_info = & switchdev_work -> fdb_info ;
1355
+ err = dsa_port_fdb_add (p -> dp , fdb_info -> addr , fdb_info -> vid );
1356
+ if (err ) {
1357
+ netdev_dbg (dev , "fdb add failed err=%d\n" , err );
1358
+ break ;
1359
+ }
1360
+ call_switchdev_notifiers (SWITCHDEV_FDB_OFFLOADED , dev ,
1361
+ & fdb_info -> info );
1362
+ break ;
1363
+
1364
+ case SWITCHDEV_FDB_DEL_TO_DEVICE :
1365
+ fdb_info = & switchdev_work -> fdb_info ;
1366
+ err = dsa_port_fdb_del (p -> dp , fdb_info -> addr , fdb_info -> vid );
1367
+ if (err ) {
1368
+ netdev_dbg (dev , "fdb del failed err=%d\n" , err );
1369
+ dev_close (dev );
1370
+ }
1371
+ break ;
1372
+ }
1373
+ rtnl_unlock ();
1374
+
1375
+ kfree (switchdev_work -> fdb_info .addr );
1376
+ kfree (switchdev_work );
1377
+ dev_put (dev );
1378
+ }
1379
+
1380
+ static int
1381
+ dsa_slave_switchdev_fdb_work_init (struct dsa_switchdev_event_work *
1382
+ switchdev_work ,
1383
+ const struct switchdev_notifier_fdb_info *
1384
+ fdb_info )
1385
+ {
1386
+ memcpy (& switchdev_work -> fdb_info , fdb_info ,
1387
+ sizeof (switchdev_work -> fdb_info ));
1388
+ switchdev_work -> fdb_info .addr = kzalloc (ETH_ALEN , GFP_ATOMIC );
1389
+ if (!switchdev_work -> fdb_info .addr )
1390
+ return - ENOMEM ;
1391
+ ether_addr_copy ((u8 * )switchdev_work -> fdb_info .addr ,
1392
+ fdb_info -> addr );
1393
+ return 0 ;
1394
+ }
1395
+
1396
+ /* Called under rcu_read_lock() */
1397
+ static int dsa_slave_switchdev_event (struct notifier_block * unused ,
1398
+ unsigned long event , void * ptr )
1399
+ {
1400
+ struct net_device * dev = switchdev_notifier_info_to_dev (ptr );
1401
+ struct dsa_switchdev_event_work * switchdev_work ;
1402
+
1403
+ if (!dsa_slave_dev_check (dev ))
1404
+ return NOTIFY_DONE ;
1405
+
1406
+ switchdev_work = kzalloc (sizeof (* switchdev_work ), GFP_ATOMIC );
1407
+ if (!switchdev_work )
1408
+ return NOTIFY_BAD ;
1409
+
1410
+ INIT_WORK (& switchdev_work -> work ,
1411
+ dsa_slave_switchdev_event_work );
1412
+ switchdev_work -> dev = dev ;
1413
+ switchdev_work -> event = event ;
1414
+
1415
+ switch (event ) {
1416
+ case SWITCHDEV_FDB_ADD_TO_DEVICE : /* fall through */
1417
+ case SWITCHDEV_FDB_DEL_TO_DEVICE :
1418
+ if (dsa_slave_switchdev_fdb_work_init (switchdev_work ,
1419
+ ptr ))
1420
+ goto err_fdb_work_init ;
1421
+ dev_hold (dev );
1422
+ break ;
1423
+ default :
1424
+ kfree (switchdev_work );
1425
+ return NOTIFY_DONE ;
1426
+ }
1427
+
1428
+ dsa_schedule_work (& switchdev_work -> work );
1429
+ return NOTIFY_OK ;
1430
+
1431
+ err_fdb_work_init :
1432
+ kfree (switchdev_work );
1433
+ return NOTIFY_BAD ;
1434
+ }
1435
+
1335
1436
static struct notifier_block dsa_slave_nb __read_mostly = {
1336
- .notifier_call = dsa_slave_netdevice_event ,
1437
+ .notifier_call = dsa_slave_netdevice_event ,
1438
+ };
1439
+
1440
+ static struct notifier_block dsa_slave_switchdev_notifier = {
1441
+ .notifier_call = dsa_slave_switchdev_event ,
1337
1442
};
1338
1443
1339
1444
int dsa_slave_register_notifier (void )
1340
1445
{
1341
- return register_netdevice_notifier (& dsa_slave_nb );
1446
+ int err ;
1447
+
1448
+ err = register_netdevice_notifier (& dsa_slave_nb );
1449
+ if (err )
1450
+ return err ;
1451
+
1452
+ err = register_switchdev_notifier (& dsa_slave_switchdev_notifier );
1453
+ if (err )
1454
+ goto err_switchdev_nb ;
1455
+
1456
+ return 0 ;
1457
+
1458
+ err_switchdev_nb :
1459
+ unregister_netdevice_notifier (& dsa_slave_nb );
1460
+ return err ;
1342
1461
}
1343
1462
1344
1463
void dsa_slave_unregister_notifier (void )
1345
1464
{
1346
1465
int err ;
1347
1466
1467
+ err = unregister_switchdev_notifier (& dsa_slave_switchdev_notifier );
1468
+ if (err )
1469
+ pr_err ("DSA: failed to unregister switchdev notifier (%d)\n" , err );
1470
+
1348
1471
err = unregister_netdevice_notifier (& dsa_slave_nb );
1349
1472
if (err )
1350
1473
pr_err ("DSA: failed to unregister slave notifier (%d)\n" , err );
0 commit comments