Commit 18bb36f9 authored by Maxim Levitsky's avatar Maxim Levitsky Committed by Stefan Richter

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: default avatarStefan Richter <stefanr@s5r6.in-berlin.de>
parent c4d6fd40
...@@ -178,6 +178,7 @@ struct fwnet_device { ...@@ -178,6 +178,7 @@ struct fwnet_device {
/* Number of tx datagrams that have been queued but not yet acked */ /* Number of tx datagrams that have been queued but not yet acked */
int queued_datagrams; int queued_datagrams;
int peer_count;
struct list_head peer_list; struct list_head peer_list;
struct fw_card *card; struct fw_card *card;
...@@ -1405,6 +1406,10 @@ static int fwnet_change_mtu(struct net_device *net, int new_mtu) ...@@ -1405,6 +1406,10 @@ static int fwnet_change_mtu(struct net_device *net, int new_mtu)
return 0; 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 = { static const struct net_device_ops fwnet_netdev_ops = {
.ndo_open = fwnet_open, .ndo_open = fwnet_open,
.ndo_stop = fwnet_stop, .ndo_stop = fwnet_stop,
...@@ -1423,6 +1428,8 @@ static void fwnet_init_dev(struct net_device *net) ...@@ -1423,6 +1428,8 @@ static void fwnet_init_dev(struct net_device *net)
net->hard_header_len = FWNET_HLEN; net->hard_header_len = FWNET_HLEN;
net->type = ARPHRD_IEEE1394; net->type = ARPHRD_IEEE1394;
net->tx_queue_len = FWNET_TX_QUEUE_LEN; net->tx_queue_len = FWNET_TX_QUEUE_LEN;
net->ethtool_ops = &fwnet_ethtool_ops;
} }
/* caller must hold fwnet_device_mutex */ /* caller must hold fwnet_device_mutex */
...@@ -1463,6 +1470,7 @@ static int fwnet_add_peer(struct fwnet_device *dev, ...@@ -1463,6 +1470,7 @@ static int fwnet_add_peer(struct fwnet_device *dev,
spin_lock_irq(&dev->lock); spin_lock_irq(&dev->lock);
list_add_tail(&peer->peer_link, &dev->peer_list); list_add_tail(&peer->peer_link, &dev->peer_list);
dev->peer_count++;
spin_unlock_irq(&dev->lock); spin_unlock_irq(&dev->lock);
return 0; return 0;
...@@ -1534,6 +1542,9 @@ static int fwnet_probe(struct device *_dev) ...@@ -1534,6 +1542,9 @@ static int fwnet_probe(struct device *_dev)
unregister_netdev(net); unregister_netdev(net);
list_del(&dev->dev_link); list_del(&dev->dev_link);
} }
if (dev->peer_count > 1)
netif_carrier_on(net);
out: out:
if (ret && allocated_netdev) if (ret && allocated_netdev)
free_netdev(net); free_netdev(net);
...@@ -1549,6 +1560,7 @@ static void fwnet_remove_peer(struct fwnet_peer *peer) ...@@ -1549,6 +1560,7 @@ static void fwnet_remove_peer(struct fwnet_peer *peer)
spin_lock_irq(&peer->dev->lock); spin_lock_irq(&peer->dev->lock);
list_del(&peer->peer_link); list_del(&peer->peer_link);
peer->dev->peer_count--;
spin_unlock_irq(&peer->dev->lock); spin_unlock_irq(&peer->dev->lock);
list_for_each_entry_safe(pd, pd_next, &peer->pd_list, pd_link) list_for_each_entry_safe(pd, pd_next, &peer->pd_list, pd_link)
...@@ -1568,6 +1580,11 @@ static int fwnet_remove(struct device *_dev) ...@@ -1568,6 +1580,11 @@ static int fwnet_remove(struct device *_dev)
fwnet_remove_peer(peer); 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)) { if (list_empty(&dev->peer_list)) {
net = dev->netdev; net = dev->netdev;
unregister_netdev(net); unregister_netdev(net);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment