firewire: net: add carrier detection
To make userland, e.g. NetworkManager work with firewire, we need to
detect whether cable is plugged or not. Simple and correct way of doing
that is just counting number of peers. No peers - no link and vice
versa.
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index ea31e30..7fd51c9 100644
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -178,6 +178,7 @@
/* Number of tx datagrams that have been queued but not yet acked */
int queued_datagrams;
+ int peer_count;
struct list_head peer_list;
struct fw_card *card;
@@ -1405,6 +1406,10 @@
return 0;
}
+static const struct ethtool_ops fwnet_ethtool_ops = {
+ .get_link = ethtool_op_get_link,
+};
+
static const struct net_device_ops fwnet_netdev_ops = {
.ndo_open = fwnet_open,
.ndo_stop = fwnet_stop,
@@ -1423,6 +1428,8 @@
net->hard_header_len = FWNET_HLEN;
net->type = ARPHRD_IEEE1394;
net->tx_queue_len = FWNET_TX_QUEUE_LEN;
+ net->ethtool_ops = &fwnet_ethtool_ops;
+
}
/* caller must hold fwnet_device_mutex */
@@ -1463,6 +1470,7 @@
spin_lock_irq(&dev->lock);
list_add_tail(&peer->peer_link, &dev->peer_list);
+ dev->peer_count++;
spin_unlock_irq(&dev->lock);
return 0;
@@ -1534,6 +1542,9 @@
unregister_netdev(net);
list_del(&dev->dev_link);
}
+
+ if (dev->peer_count > 1)
+ netif_carrier_on(net);
out:
if (ret && allocated_netdev)
free_netdev(net);
@@ -1549,6 +1560,7 @@
spin_lock_irq(&peer->dev->lock);
list_del(&peer->peer_link);
+ peer->dev->peer_count--;
spin_unlock_irq(&peer->dev->lock);
list_for_each_entry_safe(pd, pd_next, &peer->pd_list, pd_link)
@@ -1568,6 +1580,11 @@
fwnet_remove_peer(peer);
+ /* If we serve just one node, that means we lost link
+ with outer world */
+ if (dev->peer_count == 1)
+ netif_carrier_off(dev->netdev);
+
if (list_empty(&dev->peer_list)) {
net = dev->netdev;
unregister_netdev(net);