summaryrefslogtreecommitdiffstats
path: root/drivers/firewire
diff options
context:
space:
mode:
authorMaxim Levitsky <maximlevitsky@gmail.com>2010-12-08 04:22:57 +0200
committerStefan Richter <stefanr@s5r6.in-berlin.de>2010-12-19 15:27:01 +0100
commit18bb36f9fab5980efeff063755c037a622f0231c (patch)
treef12d16c98aab9934306d29dc7584095479077813 /drivers/firewire
parentc4d6fd40df38eb4c187565d48807f5f902481ba8 (diff)
downloadlinux-18bb36f9fab5980efeff063755c037a622f0231c.tar.gz
linux-18bb36f9fab5980efeff063755c037a622f0231c.tar.bz2
linux-18bb36f9fab5980efeff063755c037a622f0231c.zip
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>
Diffstat (limited to 'drivers/firewire')
-rw-r--r--drivers/firewire/net.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index ea31e3084d67..7fd51c9e243d 100644
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -178,6 +178,7 @@ struct fwnet_device {
/* 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 @@ static int fwnet_change_mtu(struct net_device *net, int new_mtu)
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 @@ static void fwnet_init_dev(struct net_device *net)
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 @@ static int fwnet_add_peer(struct fwnet_device *dev,
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 @@ static int fwnet_probe(struct device *_dev)
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 @@ static void fwnet_remove_peer(struct fwnet_peer *peer)
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 @@ static int fwnet_remove(struct device *_dev)
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);