@@ -594,12 +594,18 @@ static int dpaa2_switch_port_change_mtu(struct net_device *netdev, int mtu)
594
594
return 0 ;
595
595
}
596
596
597
- static int dpaa2_switch_port_carrier_state_sync (struct net_device * netdev )
597
+ static int dpaa2_switch_port_link_state_update (struct net_device * netdev )
598
598
{
599
599
struct ethsw_port_priv * port_priv = netdev_priv (netdev );
600
600
struct dpsw_link_state state ;
601
601
int err ;
602
602
603
+ /* When we manage the MAC/PHY using phylink there is no need
604
+ * to manually update the netif_carrier.
605
+ */
606
+ if (dpaa2_switch_port_is_type_phy (port_priv ))
607
+ return 0 ;
608
+
603
609
/* Interrupts are received even though no one issued an 'ifconfig up'
604
610
* on the switch interface. Ignore these link state update interrupts
605
611
*/
@@ -677,12 +683,14 @@ static int dpaa2_switch_port_open(struct net_device *netdev)
677
683
struct ethsw_core * ethsw = port_priv -> ethsw_data ;
678
684
int err ;
679
685
680
- /* Explicitly set carrier off, otherwise
681
- * netif_carrier_ok() will return true and cause 'ip link show'
682
- * to report the LOWER_UP flag, even though the link
683
- * notification wasn't even received.
684
- */
685
- netif_carrier_off (netdev );
686
+ if (!dpaa2_switch_port_is_type_phy (port_priv )) {
687
+ /* Explicitly set carrier off, otherwise
688
+ * netif_carrier_ok() will return true and cause 'ip link show'
689
+ * to report the LOWER_UP flag, even though the link
690
+ * notification wasn't even received.
691
+ */
692
+ netif_carrier_off (netdev );
693
+ }
686
694
687
695
err = dpsw_if_enable (port_priv -> ethsw_data -> mc_io , 0 ,
688
696
port_priv -> ethsw_data -> dpsw_handle ,
@@ -692,23 +700,12 @@ static int dpaa2_switch_port_open(struct net_device *netdev)
692
700
return err ;
693
701
}
694
702
695
- /* sync carrier state */
696
- err = dpaa2_switch_port_carrier_state_sync (netdev );
697
- if (err ) {
698
- netdev_err (netdev ,
699
- "dpaa2_switch_port_carrier_state_sync err %d\n" , err );
700
- goto err_carrier_sync ;
701
- }
702
-
703
703
dpaa2_switch_enable_ctrl_if_napi (ethsw );
704
704
705
- return 0 ;
705
+ if (dpaa2_switch_port_is_type_phy (port_priv ))
706
+ phylink_start (port_priv -> mac -> phylink );
706
707
707
- err_carrier_sync :
708
- dpsw_if_disable (port_priv -> ethsw_data -> mc_io , 0 ,
709
- port_priv -> ethsw_data -> dpsw_handle ,
710
- port_priv -> idx );
711
- return err ;
708
+ return 0 ;
712
709
}
713
710
714
711
static int dpaa2_switch_port_stop (struct net_device * netdev )
@@ -717,6 +714,13 @@ static int dpaa2_switch_port_stop(struct net_device *netdev)
717
714
struct ethsw_core * ethsw = port_priv -> ethsw_data ;
718
715
int err ;
719
716
717
+ if (dpaa2_switch_port_is_type_phy (port_priv )) {
718
+ phylink_stop (port_priv -> mac -> phylink );
719
+ } else {
720
+ netif_tx_stop_all_queues (netdev );
721
+ netif_carrier_off (netdev );
722
+ }
723
+
720
724
err = dpsw_if_disable (port_priv -> ethsw_data -> mc_io , 0 ,
721
725
port_priv -> ethsw_data -> dpsw_handle ,
722
726
port_priv -> idx );
@@ -1419,41 +1423,103 @@ bool dpaa2_switch_port_dev_check(const struct net_device *netdev)
1419
1423
return netdev -> netdev_ops == & dpaa2_switch_port_ops ;
1420
1424
}
1421
1425
1422
- static void dpaa2_switch_links_state_update (struct ethsw_core * ethsw )
1426
+ static int dpaa2_switch_port_connect_mac (struct ethsw_port_priv * port_priv )
1423
1427
{
1424
- int i ;
1428
+ struct fsl_mc_device * dpsw_port_dev , * dpmac_dev ;
1429
+ struct dpaa2_mac * mac ;
1430
+ int err ;
1425
1431
1426
- for (i = 0 ; i < ethsw -> sw_attr .num_ifs ; i ++ ) {
1427
- dpaa2_switch_port_carrier_state_sync (ethsw -> ports [i ]-> netdev );
1428
- dpaa2_switch_port_set_mac_addr (ethsw -> ports [i ]);
1432
+ dpsw_port_dev = to_fsl_mc_device (port_priv -> netdev -> dev .parent );
1433
+ dpmac_dev = fsl_mc_get_endpoint (dpsw_port_dev , port_priv -> idx );
1434
+
1435
+ if (PTR_ERR (dpmac_dev ) == - EPROBE_DEFER )
1436
+ return PTR_ERR (dpmac_dev );
1437
+
1438
+ if (IS_ERR (dpmac_dev ) || dpmac_dev -> dev .type != & fsl_mc_bus_dpmac_type )
1439
+ return 0 ;
1440
+
1441
+ mac = kzalloc (sizeof (* mac ), GFP_KERNEL );
1442
+ if (!mac )
1443
+ return - ENOMEM ;
1444
+
1445
+ mac -> mc_dev = dpmac_dev ;
1446
+ mac -> mc_io = port_priv -> ethsw_data -> mc_io ;
1447
+ mac -> net_dev = port_priv -> netdev ;
1448
+
1449
+ err = dpaa2_mac_open (mac );
1450
+ if (err )
1451
+ goto err_free_mac ;
1452
+ port_priv -> mac = mac ;
1453
+
1454
+ if (dpaa2_switch_port_is_type_phy (port_priv )) {
1455
+ err = dpaa2_mac_connect (mac );
1456
+ if (err ) {
1457
+ netdev_err (port_priv -> netdev ,
1458
+ "Error connecting to the MAC endpoint %pe\n" ,
1459
+ ERR_PTR (err ));
1460
+ goto err_close_mac ;
1461
+ }
1429
1462
}
1463
+
1464
+ return 0 ;
1465
+
1466
+ err_close_mac :
1467
+ dpaa2_mac_close (mac );
1468
+ port_priv -> mac = NULL ;
1469
+ err_free_mac :
1470
+ kfree (mac );
1471
+ return err ;
1472
+ }
1473
+
1474
+ static void dpaa2_switch_port_disconnect_mac (struct ethsw_port_priv * port_priv )
1475
+ {
1476
+ if (dpaa2_switch_port_is_type_phy (port_priv ))
1477
+ dpaa2_mac_disconnect (port_priv -> mac );
1478
+
1479
+ if (!dpaa2_switch_port_has_mac (port_priv ))
1480
+ return ;
1481
+
1482
+ dpaa2_mac_close (port_priv -> mac );
1483
+ kfree (port_priv -> mac );
1484
+ port_priv -> mac = NULL ;
1430
1485
}
1431
1486
1432
1487
static irqreturn_t dpaa2_switch_irq0_handler_thread (int irq_num , void * arg )
1433
1488
{
1434
1489
struct device * dev = (struct device * )arg ;
1435
1490
struct ethsw_core * ethsw = dev_get_drvdata (dev );
1436
-
1437
- /* Mask the events and the if_id reserved bits to be cleared on read */
1438
- u32 status = DPSW_IRQ_EVENT_LINK_CHANGED | 0xFFFF0000 ;
1439
- int err ;
1491
+ struct ethsw_port_priv * port_priv ;
1492
+ u32 status = ~0 ;
1493
+ int err , if_id ;
1440
1494
1441
1495
err = dpsw_get_irq_status (ethsw -> mc_io , 0 , ethsw -> dpsw_handle ,
1442
1496
DPSW_IRQ_INDEX_IF , & status );
1443
1497
if (err ) {
1444
1498
dev_err (dev , "Can't get irq status (err %d)\n" , err );
1445
-
1446
- err = dpsw_clear_irq_status (ethsw -> mc_io , 0 , ethsw -> dpsw_handle ,
1447
- DPSW_IRQ_INDEX_IF , 0xFFFFFFFF );
1448
- if (err )
1449
- dev_err (dev , "Can't clear irq status (err %d)\n" , err );
1450
1499
goto out ;
1451
1500
}
1452
1501
1453
- if (status & DPSW_IRQ_EVENT_LINK_CHANGED )
1454
- dpaa2_switch_links_state_update (ethsw );
1502
+ if_id = (status & 0xFFFF0000 ) >> 16 ;
1503
+ port_priv = ethsw -> ports [if_id ];
1504
+
1505
+ if (status & DPSW_IRQ_EVENT_LINK_CHANGED ) {
1506
+ dpaa2_switch_port_link_state_update (port_priv -> netdev );
1507
+ dpaa2_switch_port_set_mac_addr (port_priv );
1508
+ }
1509
+
1510
+ if (status & DPSW_IRQ_EVENT_ENDPOINT_CHANGED ) {
1511
+ if (dpaa2_switch_port_has_mac (port_priv ))
1512
+ dpaa2_switch_port_disconnect_mac (port_priv );
1513
+ else
1514
+ dpaa2_switch_port_connect_mac (port_priv );
1515
+ }
1455
1516
1456
1517
out :
1518
+ err = dpsw_clear_irq_status (ethsw -> mc_io , 0 , ethsw -> dpsw_handle ,
1519
+ DPSW_IRQ_INDEX_IF , status );
1520
+ if (err )
1521
+ dev_err (dev , "Can't clear irq status (err %d)\n" , err );
1522
+
1457
1523
return IRQ_HANDLED ;
1458
1524
}
1459
1525
@@ -3133,6 +3199,7 @@ static int dpaa2_switch_remove(struct fsl_mc_device *sw_dev)
3133
3199
for (i = 0 ; i < ethsw -> sw_attr .num_ifs ; i ++ ) {
3134
3200
port_priv = ethsw -> ports [i ];
3135
3201
unregister_netdev (port_priv -> netdev );
3202
+ dpaa2_switch_port_disconnect_mac (port_priv );
3136
3203
free_netdev (port_priv -> netdev );
3137
3204
}
3138
3205
@@ -3212,6 +3279,10 @@ static int dpaa2_switch_probe_port(struct ethsw_core *ethsw,
3212
3279
goto err_port_probe ;
3213
3280
port_priv -> learn_ena = false;
3214
3281
3282
+ err = dpaa2_switch_port_connect_mac (port_priv );
3283
+ if (err )
3284
+ goto err_port_probe ;
3285
+
3215
3286
return 0 ;
3216
3287
3217
3288
err_port_probe :
@@ -3288,12 +3359,6 @@ static int dpaa2_switch_probe(struct fsl_mc_device *sw_dev)
3288
3359
& ethsw -> fq [i ].napi , dpaa2_switch_poll ,
3289
3360
NAPI_POLL_WEIGHT );
3290
3361
3291
- err = dpsw_enable (ethsw -> mc_io , 0 , ethsw -> dpsw_handle );
3292
- if (err ) {
3293
- dev_err (ethsw -> dev , "dpsw_enable err %d\n" , err );
3294
- goto err_free_netdev ;
3295
- }
3296
-
3297
3362
/* Setup IRQs */
3298
3363
err = dpaa2_switch_setup_irqs (sw_dev );
3299
3364
if (err )
0 commit comments