aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2010-12-17 16:22:33 -0500
committerStefan Richter <stefanr@s5r6.in-berlin.de>2010-12-19 09:27:02 -0500
commitc16714704bb35165e5b85d927873dcc643772648 (patch)
treec8aa70b7d7aaf3984a7c1b8579bd7f2ae29ec39d /drivers/firewire
parent18bb36f9fab5980efeff063755c037a622f0231c (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.c36
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
1226static 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 */
1226static int fwnet_open(struct net_device *net) 1235static 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
1557static void fwnet_remove_peer(struct fwnet_peer *peer) 1567static 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;