diff options
author | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2010-12-17 16:22:33 -0500 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2010-12-19 09:27:02 -0500 |
commit | c16714704bb35165e5b85d927873dcc643772648 (patch) | |
tree | c8aa70b7d7aaf3984a7c1b8579bd7f2ae29ec39d /drivers/firewire | |
parent | 18bb36f9fab5980efeff063755c037a622f0231c (diff) |
firewire: net: set carrier state at ifup
At ifup, carrier status would be shown on even if it actually was off.
Also add an include for ethtool_ops rather than to rely on the one from
netdevice.h.
Note, we can alas not use fwnet_device_mutex to serialize access to
dev->peer_count (as I originally wanted). This would cause a lock
inversion:
- fwnet_probe | takes fwnet_device_mutex
+ register_netdev | takes rtnl_mutex
- devinet_ioctl | takes rtnl_mutex
+ fwnet_open | ...must not take fwnet_device_mutex
Hence use the dev->lock spinlock for serialization.
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire')
-rw-r--r-- | drivers/firewire/net.c | 36 |
1 files changed, 21 insertions, 15 deletions
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c index 7fd51c9e243d..c2e194c58667 100644 --- a/drivers/firewire/net.c +++ b/drivers/firewire/net.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/bug.h> | 9 | #include <linux/bug.h> |
10 | #include <linux/delay.h> | 10 | #include <linux/delay.h> |
11 | #include <linux/device.h> | 11 | #include <linux/device.h> |
12 | #include <linux/ethtool.h> | ||
12 | #include <linux/firewire.h> | 13 | #include <linux/firewire.h> |
13 | #include <linux/firewire-constants.h> | 14 | #include <linux/firewire-constants.h> |
14 | #include <linux/highmem.h> | 15 | #include <linux/highmem.h> |
@@ -178,8 +179,8 @@ struct fwnet_device { | |||
178 | 179 | ||
179 | /* Number of tx datagrams that have been queued but not yet acked */ | 180 | /* Number of tx datagrams that have been queued but not yet acked */ |
180 | int queued_datagrams; | 181 | int queued_datagrams; |
181 | int peer_count; | ||
182 | 182 | ||
183 | int peer_count; | ||
183 | struct list_head peer_list; | 184 | struct list_head peer_list; |
184 | struct fw_card *card; | 185 | struct fw_card *card; |
185 | struct net_device *netdev; | 186 | struct net_device *netdev; |
@@ -1222,6 +1223,14 @@ static int fwnet_broadcast_start(struct fwnet_device *dev) | |||
1222 | return retval; | 1223 | return retval; |
1223 | } | 1224 | } |
1224 | 1225 | ||
1226 | static void set_carrier_state(struct fwnet_device *dev) | ||
1227 | { | ||
1228 | if (dev->peer_count > 1) | ||
1229 | netif_carrier_on(dev->netdev); | ||
1230 | else | ||
1231 | netif_carrier_off(dev->netdev); | ||
1232 | } | ||
1233 | |||
1225 | /* ifup */ | 1234 | /* ifup */ |
1226 | static int fwnet_open(struct net_device *net) | 1235 | static int fwnet_open(struct net_device *net) |
1227 | { | 1236 | { |
@@ -1235,6 +1244,10 @@ static int fwnet_open(struct net_device *net) | |||
1235 | } | 1244 | } |
1236 | netif_start_queue(net); | 1245 | netif_start_queue(net); |
1237 | 1246 | ||
1247 | spin_lock_irq(&dev->lock); | ||
1248 | set_carrier_state(dev); | ||
1249 | spin_unlock_irq(&dev->lock); | ||
1250 | |||
1238 | return 0; | 1251 | return 0; |
1239 | } | 1252 | } |
1240 | 1253 | ||
@@ -1429,7 +1442,6 @@ static void fwnet_init_dev(struct net_device *net) | |||
1429 | net->type = ARPHRD_IEEE1394; | 1442 | net->type = ARPHRD_IEEE1394; |
1430 | net->tx_queue_len = FWNET_TX_QUEUE_LEN; | 1443 | net->tx_queue_len = FWNET_TX_QUEUE_LEN; |
1431 | net->ethtool_ops = &fwnet_ethtool_ops; | 1444 | net->ethtool_ops = &fwnet_ethtool_ops; |
1432 | |||
1433 | } | 1445 | } |
1434 | 1446 | ||
1435 | /* caller must hold fwnet_device_mutex */ | 1447 | /* caller must hold fwnet_device_mutex */ |
@@ -1471,6 +1483,7 @@ static int fwnet_add_peer(struct fwnet_device *dev, | |||
1471 | spin_lock_irq(&dev->lock); | 1483 | spin_lock_irq(&dev->lock); |
1472 | list_add_tail(&peer->peer_link, &dev->peer_list); | 1484 | list_add_tail(&peer->peer_link, &dev->peer_list); |
1473 | dev->peer_count++; | 1485 | dev->peer_count++; |
1486 | set_carrier_state(dev); | ||
1474 | spin_unlock_irq(&dev->lock); | 1487 | spin_unlock_irq(&dev->lock); |
1475 | 1488 | ||
1476 | return 0; | 1489 | return 0; |
@@ -1542,9 +1555,6 @@ static int fwnet_probe(struct device *_dev) | |||
1542 | unregister_netdev(net); | 1555 | unregister_netdev(net); |
1543 | list_del(&dev->dev_link); | 1556 | list_del(&dev->dev_link); |
1544 | } | 1557 | } |
1545 | |||
1546 | if (dev->peer_count > 1) | ||
1547 | netif_carrier_on(net); | ||
1548 | out: | 1558 | out: |
1549 | if (ret && allocated_netdev) | 1559 | if (ret && allocated_netdev) |
1550 | free_netdev(net); | 1560 | free_netdev(net); |
@@ -1554,14 +1564,15 @@ static int fwnet_probe(struct device *_dev) | |||
1554 | return ret; | 1564 | return ret; |
1555 | } | 1565 | } |
1556 | 1566 | ||
1557 | static void fwnet_remove_peer(struct fwnet_peer *peer) | 1567 | static void fwnet_remove_peer(struct fwnet_peer *peer, struct fwnet_device *dev) |
1558 | { | 1568 | { |
1559 | struct fwnet_partial_datagram *pd, *pd_next; | 1569 | struct fwnet_partial_datagram *pd, *pd_next; |
1560 | 1570 | ||
1561 | spin_lock_irq(&peer->dev->lock); | 1571 | spin_lock_irq(&dev->lock); |
1562 | list_del(&peer->peer_link); | 1572 | list_del(&peer->peer_link); |
1563 | peer->dev->peer_count--; | 1573 | dev->peer_count--; |
1564 | spin_unlock_irq(&peer->dev->lock); | 1574 | set_carrier_state(dev); |
1575 | spin_unlock_irq(&dev->lock); | ||
1565 | 1576 | ||
1566 | list_for_each_entry_safe(pd, pd_next, &peer->pd_list, pd_link) | 1577 | list_for_each_entry_safe(pd, pd_next, &peer->pd_list, pd_link) |
1567 | fwnet_pd_delete(pd); | 1578 | fwnet_pd_delete(pd); |
@@ -1578,12 +1589,7 @@ static int fwnet_remove(struct device *_dev) | |||
1578 | 1589 | ||
1579 | mutex_lock(&fwnet_device_mutex); | 1590 | mutex_lock(&fwnet_device_mutex); |
1580 | 1591 | ||
1581 | fwnet_remove_peer(peer); | 1592 | fwnet_remove_peer(peer, dev); |
1582 | |||
1583 | /* If we serve just one node, that means we lost link | ||
1584 | with outer world */ | ||
1585 | if (dev->peer_count == 1) | ||
1586 | netif_carrier_off(dev->netdev); | ||
1587 | 1593 | ||
1588 | if (list_empty(&dev->peer_list)) { | 1594 | if (list_empty(&dev->peer_list)) { |
1589 | net = dev->netdev; | 1595 | net = dev->netdev; |