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,6 +69,7 @@ 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 ;
@@ -1038,7 +1040,11 @@ static irqreturn_t ftgmac100_interrupt(int irq, void *dev_id)
10381040 struct net_device * netdev = dev_id ;
10391041 struct ftgmac100 * priv = netdev_priv (netdev );
10401042
1041- if (likely (netif_running (netdev ))) {
1043+ /* When running in NCSI mode, the interface should be
1044+ * ready to receive or transmit NCSI packet before it's
1045+ * opened.
1046+ */
1047+ if (likely (priv -> use_ncsi || netif_running (netdev ))) {
10421048 /* Disable interrupts for polling */
10431049 iowrite32 (0 , priv -> base + FTGMAC100_OFFSET_IER );
10441050 napi_schedule (& priv -> napi );
@@ -1162,8 +1168,18 @@ static int ftgmac100_open(struct net_device *netdev)
11621168
11631169 /* enable all interrupts */
11641170 iowrite32 (INT_MASK_ALL_ENABLED , priv -> base + FTGMAC100_OFFSET_IER );
1171+ /* Start the NCSI device */
1172+ if (priv -> use_ncsi ){
1173+ err = ncsi_start_dev (priv -> ndev );
1174+ if (err )
1175+ goto err_ncsi ;
1176+ }
11651177 return 0 ;
11661178
1179+ err_ncsi :
1180+ napi_disable (& priv -> napi );
1181+ netif_stop_queue (netdev );
1182+ iowrite32 (0 , priv -> base + FTGMAC100_OFFSET_IER );
11671183err_hw :
11681184 free_irq (priv -> irq , netdev );
11691185err_irq :
@@ -1172,7 +1188,7 @@ static int ftgmac100_open(struct net_device *netdev)
11721188 return err ;
11731189}
11741190
1175- static int ftgmac100_stop (struct net_device * netdev )
1191+ static int ftgmac100_stop_dev (struct net_device * netdev )
11761192{
11771193 struct ftgmac100 * priv = netdev_priv (netdev );
11781194
@@ -1191,6 +1207,18 @@ static int ftgmac100_stop(struct net_device *netdev)
11911207 return 0 ;
11921208}
11931209
1210+ static int ftgmac100_stop (struct net_device * netdev )
1211+ {
1212+ struct ftgmac100 * priv = netdev_priv (netdev );
1213+
1214+ /* Stop NCSI device */
1215+ if (priv -> use_ncsi ) {
1216+ ncsi_stop_dev (priv -> ndev );
1217+ return 0 ;
1218+ }
1219+
1220+ return ftgmac100_stop_dev (netdev );
1221+ }
11941222static int ftgmac100_hard_start_xmit (struct sk_buff * skb ,
11951223 struct net_device * netdev )
11961224{
@@ -1291,6 +1319,21 @@ static const struct net_device_ops ftgmac100_netdev_ops = {
12911319 .ndo_do_ioctl = ftgmac100_do_ioctl ,
12921320};
12931321
1322+ static void ftgmac100_ncsi_handler (struct ncsi_dev * nd )
1323+ {
1324+ struct net_device * netdev = nd -> nd_dev ;
1325+
1326+ if (nd -> nd_state != ncsi_dev_state_functional )
1327+ return ;
1328+
1329+ if (nd -> nd_link_up ) {
1330+ pr_info ("NCSI dev is up\n" );
1331+ netif_start_queue (netdev );
1332+ } else {
1333+ pr_info ("NCSI dev is down\n" );
1334+ ftgmac100_stop_dev (netdev );
1335+ }
1336+ }
12941337/******************************************************************************
12951338 * struct platform_driver functions
12961339 *****************************************************************************/
@@ -1300,7 +1343,7 @@ static int ftgmac100_probe(struct platform_device *pdev)
13001343 int irq ;
13011344 struct net_device * netdev ;
13021345 struct ftgmac100 * priv ;
1303- int err ;
1346+ int err = 0 ;
13041347
13051348 if (!pdev )
13061349 return - ENODEV ;
@@ -1320,7 +1363,17 @@ static int ftgmac100_probe(struct platform_device *pdev)
13201363 goto err_alloc_etherdev ;
13211364 }
13221365
1366+ /* Check for NCSI mode */
1367+ priv = netdev_priv (netdev );
13231368 SET_NETDEV_DEV (netdev , & pdev -> dev );
1369+ if (pdev -> dev .of_node &&
1370+ of_get_property (pdev -> dev .of_node , "use-nc-si" , NULL )) {
1371+ dev_info (& pdev -> dev , "Using NCSI interface\n" );
1372+ priv -> phydev = NULL ;
1373+ priv -> use_ncsi = true;
1374+ } else {
1375+ priv -> use_ncsi = false;
1376+ }
13241377
13251378 netdev -> ethtool_ops = & ftgmac100_ethtool_ops ;
13261379 netdev -> netdev_ops = & ftgmac100_netdev_ops ;
@@ -1329,7 +1382,6 @@ static int ftgmac100_probe(struct platform_device *pdev)
13291382 platform_set_drvdata (pdev , netdev );
13301383
13311384 /* setup private data */
1332- priv = netdev_priv (netdev );
13331385 priv -> netdev = netdev ;
13341386 priv -> dev = & pdev -> dev ;
13351387
@@ -1356,24 +1408,14 @@ static int ftgmac100_probe(struct platform_device *pdev)
13561408
13571409 priv -> irq = irq ;
13581410
1359- /* Check for NC-SI mode */
1360- if (pdev -> dev .of_node &&
1361- of_get_property (pdev -> dev .of_node , "use-nc-si" , NULL ))
1362- priv -> use_ncsi = true;
1363- else
1364- priv -> use_ncsi = false;
1411+ /* Read MAC address or setup a new one */
1412+ ftgmac100_setup_mac (priv );
13651413
1366- /* If we use NC-SI, we need to set that up, which isn't implemented yet
1367- * so we pray things were setup by the bootloader and just mark our link
1368- * as up (otherwise we can't get packets through).
1369- *
1370- * Eventually, we'll have a proper NC-SI stack as a helper we can
1371- * instanciate
1372- */
1414+ /* Register NCSI device */
13731415 if (priv -> use_ncsi ) {
1374- /* XXX */
1375- priv -> phydev = NULL ;
1376- dev_info ( & pdev -> dev , "Using NC-SI interface\n" ) ;
1416+ priv -> ndev = ncsi_register_dev ( netdev , ftgmac100_ncsi_handler );
1417+ if (! priv -> ndev )
1418+ goto err_ncsi_dev ;
13771419 } else {
13781420 err = ftgmac100_setup_mdio (priv );
13791421
@@ -1384,9 +1426,6 @@ static int ftgmac100_probe(struct platform_device *pdev)
13841426 dev_warn (& pdev -> dev , "Error %d setting up MDIO\n" , err );
13851427 }
13861428
1387- /* Read MAC address or setup a new one */
1388- ftgmac100_setup_mac (priv );
1389-
13901429 /* Register network device */
13911430 err = register_netdev (netdev );
13921431 if (err ) {
@@ -1399,7 +1438,11 @@ static int ftgmac100_probe(struct platform_device *pdev)
13991438 return 0 ;
14001439
14011440err_register_netdev :
1402- ftgmac100_destroy_mdio (priv );
1441+ if (!priv -> use_ncsi )
1442+ ftgmac100_destroy_mdio (priv );
1443+ else
1444+ ncsi_unregister_dev (priv -> ndev );
1445+ err_ncsi_dev :
14031446 iounmap (priv -> base );
14041447err_ioremap :
14051448 release_resource (priv -> res );
0 commit comments