3131#include <linux/phy.h>
3232#include <linux/platform_device.h>
3333#include <net/ip.h>
34+ #include <net/ncsi.h>
3435
3536#include "ftgmac100.h"
3637
@@ -68,10 +69,13 @@ struct ftgmac100 {
6869
6970 struct net_device * netdev ;
7071 struct device * dev ;
72+ struct ncsi_dev * ndev ;
7173 struct napi_struct napi ;
7274
7375 struct mii_bus * mii_bus ;
7476 int old_speed ;
77+ bool use_ncsi ;
78+ bool enabled ;
7579};
7680
7781static int ftgmac100_alloc_rx_page (struct ftgmac100 * priv ,
@@ -1010,7 +1014,10 @@ static irqreturn_t ftgmac100_interrupt(int irq, void *dev_id)
10101014 struct net_device * netdev = dev_id ;
10111015 struct ftgmac100 * priv = netdev_priv (netdev );
10121016
1013- if (likely (netif_running (netdev ))) {
1017+ /* When running in NCSI mode, the interface should be ready for
1018+ * receiving or transmitting NCSI packets before it's opened.
1019+ */
1020+ if (likely (priv -> use_ncsi || netif_running (netdev ))) {
10141021 /* Disable interrupts for polling */
10151022 iowrite32 (0 , priv -> base + FTGMAC100_OFFSET_IER );
10161023 napi_schedule (& priv -> napi );
@@ -1123,17 +1130,33 @@ static int ftgmac100_open(struct net_device *netdev)
11231130 goto err_hw ;
11241131
11251132 ftgmac100_init_hw (priv );
1126- ftgmac100_start_hw (priv , 10 );
1127-
1128- phy_start (netdev -> phydev );
1133+ ftgmac100_start_hw (priv , priv -> use_ncsi ? 100 : 10 );
1134+ if (netdev -> phydev )
1135+ phy_start (netdev -> phydev );
1136+ else if (priv -> use_ncsi )
1137+ netif_carrier_on (netdev );
11291138
11301139 napi_enable (& priv -> napi );
11311140 netif_start_queue (netdev );
11321141
11331142 /* enable all interrupts */
11341143 iowrite32 (INT_MASK_ALL_ENABLED , priv -> base + FTGMAC100_OFFSET_IER );
1144+
1145+ /* Start the NCSI device */
1146+ if (priv -> use_ncsi ) {
1147+ err = ncsi_start_dev (priv -> ndev );
1148+ if (err )
1149+ goto err_ncsi ;
1150+ }
1151+
1152+ priv -> enabled = true;
1153+
11351154 return 0 ;
11361155
1156+ err_ncsi :
1157+ napi_disable (& priv -> napi );
1158+ netif_stop_queue (netdev );
1159+ iowrite32 (0 , priv -> base + FTGMAC100_OFFSET_IER );
11371160err_hw :
11381161 free_irq (priv -> irq , netdev );
11391162err_irq :
@@ -1146,12 +1169,17 @@ static int ftgmac100_stop(struct net_device *netdev)
11461169{
11471170 struct ftgmac100 * priv = netdev_priv (netdev );
11481171
1172+ if (!priv -> enabled )
1173+ return 0 ;
1174+
11491175 /* disable all interrupts */
1176+ priv -> enabled = false;
11501177 iowrite32 (0 , priv -> base + FTGMAC100_OFFSET_IER );
11511178
11521179 netif_stop_queue (netdev );
11531180 napi_disable (& priv -> napi );
1154- phy_stop (netdev -> phydev );
1181+ if (netdev -> phydev )
1182+ phy_stop (netdev -> phydev );
11551183
11561184 ftgmac100_stop_hw (priv );
11571185 free_irq (priv -> irq , netdev );
@@ -1192,6 +1220,9 @@ static int ftgmac100_hard_start_xmit(struct sk_buff *skb,
11921220/* optional */
11931221static int ftgmac100_do_ioctl (struct net_device * netdev , struct ifreq * ifr , int cmd )
11941222{
1223+ if (!netdev -> phydev )
1224+ return - ENXIO ;
1225+
11951226 return phy_mii_ioctl (netdev -> phydev , ifr , cmd );
11961227}
11971228
@@ -1258,6 +1289,15 @@ static void ftgmac100_destroy_mdio(struct net_device *netdev)
12581289 mdiobus_free (priv -> mii_bus );
12591290}
12601291
1292+ static void ftgmac100_ncsi_handler (struct ncsi_dev * nd )
1293+ {
1294+ if (unlikely (nd -> state != ncsi_dev_state_functional ))
1295+ return ;
1296+
1297+ netdev_info (nd -> dev , "NCSI interface %s\n" ,
1298+ nd -> link_up ? "up" : "down" );
1299+ }
1300+
12611301/******************************************************************************
12621302 * struct platform_driver functions
12631303 *****************************************************************************/
@@ -1267,7 +1307,7 @@ static int ftgmac100_probe(struct platform_device *pdev)
12671307 int irq ;
12681308 struct net_device * netdev ;
12691309 struct ftgmac100 * priv ;
1270- int err ;
1310+ int err = 0 ;
12711311
12721312 if (!pdev )
12731313 return - ENODEV ;
@@ -1291,7 +1331,6 @@ static int ftgmac100_probe(struct platform_device *pdev)
12911331
12921332 netdev -> ethtool_ops = & ftgmac100_ethtool_ops ;
12931333 netdev -> netdev_ops = & ftgmac100_netdev_ops ;
1294- netdev -> features = NETIF_F_IP_CSUM | NETIF_F_GRO ;
12951334
12961335 platform_set_drvdata (pdev , netdev );
12971336
@@ -1326,9 +1365,34 @@ static int ftgmac100_probe(struct platform_device *pdev)
13261365 /* MAC address from chip or random one */
13271366 ftgmac100_setup_mac (priv );
13281367
1329- err = ftgmac100_setup_mdio (netdev );
1330- if (err )
1331- goto err_setup_mdio ;
1368+ if (pdev -> dev .of_node &&
1369+ of_get_property (pdev -> dev .of_node , "use-ncsi" , NULL )) {
1370+ if (!IS_ENABLED (CONFIG_NET_NCSI )) {
1371+ dev_err (& pdev -> dev , "NCSI stack not enabled\n" );
1372+ goto err_ncsi_dev ;
1373+ }
1374+
1375+ dev_info (& pdev -> dev , "Using NCSI interface\n" );
1376+ priv -> use_ncsi = true;
1377+ priv -> ndev = ncsi_register_dev (netdev , ftgmac100_ncsi_handler );
1378+ if (!priv -> ndev )
1379+ goto err_ncsi_dev ;
1380+ } else {
1381+ priv -> use_ncsi = false;
1382+ err = ftgmac100_setup_mdio (netdev );
1383+ if (err )
1384+ goto err_setup_mdio ;
1385+ }
1386+
1387+ /* We have to disable on-chip IP checksum functionality
1388+ * when NCSI is enabled on the interface. It doesn't work
1389+ * in that case.
1390+ */
1391+ netdev -> features = NETIF_F_IP_CSUM | NETIF_F_GRO ;
1392+ if (priv -> use_ncsi &&
1393+ of_get_property (pdev -> dev .of_node , "no-hw-checksum" , NULL ))
1394+ netdev -> features &= ~NETIF_F_IP_CSUM ;
1395+
13321396
13331397 /* register network device */
13341398 err = register_netdev (netdev );
@@ -1341,6 +1405,7 @@ static int ftgmac100_probe(struct platform_device *pdev)
13411405
13421406 return 0 ;
13431407
1408+ err_ncsi_dev :
13441409err_register_netdev :
13451410 ftgmac100_destroy_mdio (netdev );
13461411err_setup_mdio :
0 commit comments