31
31
#include <linux/phy.h>
32
32
#include <linux/platform_device.h>
33
33
#include <net/ip.h>
34
+ #include <net/ncsi.h>
34
35
35
36
#include "ftgmac100.h"
36
37
@@ -68,10 +69,13 @@ struct ftgmac100 {
68
69
69
70
struct net_device * netdev ;
70
71
struct device * dev ;
72
+ struct ncsi_dev * ndev ;
71
73
struct napi_struct napi ;
72
74
73
75
struct mii_bus * mii_bus ;
74
76
int old_speed ;
77
+ bool use_ncsi ;
78
+ bool enabled ;
75
79
};
76
80
77
81
static int ftgmac100_alloc_rx_page (struct ftgmac100 * priv ,
@@ -1010,7 +1014,10 @@ static irqreturn_t ftgmac100_interrupt(int irq, void *dev_id)
1010
1014
struct net_device * netdev = dev_id ;
1011
1015
struct ftgmac100 * priv = netdev_priv (netdev );
1012
1016
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 ))) {
1014
1021
/* Disable interrupts for polling */
1015
1022
iowrite32 (0 , priv -> base + FTGMAC100_OFFSET_IER );
1016
1023
napi_schedule (& priv -> napi );
@@ -1123,17 +1130,33 @@ static int ftgmac100_open(struct net_device *netdev)
1123
1130
goto err_hw ;
1124
1131
1125
1132
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 );
1129
1138
1130
1139
napi_enable (& priv -> napi );
1131
1140
netif_start_queue (netdev );
1132
1141
1133
1142
/* enable all interrupts */
1134
1143
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
+
1135
1154
return 0 ;
1136
1155
1156
+ err_ncsi :
1157
+ napi_disable (& priv -> napi );
1158
+ netif_stop_queue (netdev );
1159
+ iowrite32 (0 , priv -> base + FTGMAC100_OFFSET_IER );
1137
1160
err_hw :
1138
1161
free_irq (priv -> irq , netdev );
1139
1162
err_irq :
@@ -1146,12 +1169,17 @@ static int ftgmac100_stop(struct net_device *netdev)
1146
1169
{
1147
1170
struct ftgmac100 * priv = netdev_priv (netdev );
1148
1171
1172
+ if (!priv -> enabled )
1173
+ return 0 ;
1174
+
1149
1175
/* disable all interrupts */
1176
+ priv -> enabled = false;
1150
1177
iowrite32 (0 , priv -> base + FTGMAC100_OFFSET_IER );
1151
1178
1152
1179
netif_stop_queue (netdev );
1153
1180
napi_disable (& priv -> napi );
1154
- phy_stop (netdev -> phydev );
1181
+ if (netdev -> phydev )
1182
+ phy_stop (netdev -> phydev );
1155
1183
1156
1184
ftgmac100_stop_hw (priv );
1157
1185
free_irq (priv -> irq , netdev );
@@ -1192,6 +1220,9 @@ static int ftgmac100_hard_start_xmit(struct sk_buff *skb,
1192
1220
/* optional */
1193
1221
static int ftgmac100_do_ioctl (struct net_device * netdev , struct ifreq * ifr , int cmd )
1194
1222
{
1223
+ if (!netdev -> phydev )
1224
+ return - ENXIO ;
1225
+
1195
1226
return phy_mii_ioctl (netdev -> phydev , ifr , cmd );
1196
1227
}
1197
1228
@@ -1258,6 +1289,15 @@ static void ftgmac100_destroy_mdio(struct net_device *netdev)
1258
1289
mdiobus_free (priv -> mii_bus );
1259
1290
}
1260
1291
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
+
1261
1301
/******************************************************************************
1262
1302
* struct platform_driver functions
1263
1303
*****************************************************************************/
@@ -1267,7 +1307,7 @@ static int ftgmac100_probe(struct platform_device *pdev)
1267
1307
int irq ;
1268
1308
struct net_device * netdev ;
1269
1309
struct ftgmac100 * priv ;
1270
- int err ;
1310
+ int err = 0 ;
1271
1311
1272
1312
if (!pdev )
1273
1313
return - ENODEV ;
@@ -1291,7 +1331,6 @@ static int ftgmac100_probe(struct platform_device *pdev)
1291
1331
1292
1332
netdev -> ethtool_ops = & ftgmac100_ethtool_ops ;
1293
1333
netdev -> netdev_ops = & ftgmac100_netdev_ops ;
1294
- netdev -> features = NETIF_F_IP_CSUM | NETIF_F_GRO ;
1295
1334
1296
1335
platform_set_drvdata (pdev , netdev );
1297
1336
@@ -1326,9 +1365,34 @@ static int ftgmac100_probe(struct platform_device *pdev)
1326
1365
/* MAC address from chip or random one */
1327
1366
ftgmac100_setup_mac (priv );
1328
1367
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
+
1332
1396
1333
1397
/* register network device */
1334
1398
err = register_netdev (netdev );
@@ -1341,6 +1405,7 @@ static int ftgmac100_probe(struct platform_device *pdev)
1341
1405
1342
1406
return 0 ;
1343
1407
1408
+ err_ncsi_dev :
1344
1409
err_register_netdev :
1345
1410
ftgmac100_destroy_mdio (netdev );
1346
1411
err_setup_mdio :
0 commit comments