git.openpandora.org
/
pandora-kernel.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Merge branch 'irq-cleanup-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[pandora-kernel.git]
/
drivers
/
firewire
/
net.c
diff --git
a/drivers/firewire/net.c
b/drivers/firewire/net.c
index
1a467a9
..
7ed08fd
100644
(file)
--- a/
drivers/firewire/net.c
+++ b/
drivers/firewire/net.c
@@
-9,6
+9,7
@@
#include <linux/bug.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/bug.h>
#include <linux/delay.h>
#include <linux/device.h>
+#include <linux/ethtool.h>
#include <linux/firewire.h>
#include <linux/firewire-constants.h>
#include <linux/highmem.h>
#include <linux/firewire.h>
#include <linux/firewire-constants.h>
#include <linux/highmem.h>
@@
-179,6
+180,7
@@
struct fwnet_device {
/* Number of tx datagrams that have been queued but not yet acked */
int queued_datagrams;
/* 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;
struct net_device *netdev;
struct list_head peer_list;
struct fw_card *card;
struct net_device *netdev;
@@
-189,6
+191,7
@@
struct fwnet_peer {
struct fwnet_device *dev;
u64 guid;
u64 fifo;
struct fwnet_device *dev;
u64 guid;
u64 fifo;
+ __be32 ip;
/* guarded by dev->lock */
struct list_head pd_list; /* received partial datagrams */
/* guarded by dev->lock */
struct list_head pd_list; /* received partial datagrams */
@@
-568,6
+571,8
@@
static int fwnet_finish_incoming_packet(struct net_device *net,
peer->speed = sspd;
if (peer->max_payload > max_payload)
peer->max_payload = max_payload;
peer->speed = sspd;
if (peer->max_payload > max_payload)
peer->max_payload = max_payload;
+
+ peer->ip = arp1394->sip;
}
spin_unlock_irqrestore(&dev->lock, flags);
}
spin_unlock_irqrestore(&dev->lock, flags);
@@
-996,15
+1001,23
@@
static void fwnet_transmit_packet_failed(struct fwnet_packet_task *ptask)
static void fwnet_write_complete(struct fw_card *card, int rcode,
void *payload, size_t length, void *data)
{
static void fwnet_write_complete(struct fw_card *card, int rcode,
void *payload, size_t length, void *data)
{
- struct fwnet_packet_task *ptask;
-
-
ptask = data
;
+ struct fwnet_packet_task *ptask
= data
;
+ static unsigned long j;
+
static int last_rcode, errors_skipped
;
if (rcode == RCODE_COMPLETE) {
fwnet_transmit_packet_done(ptask);
} else {
if (rcode == RCODE_COMPLETE) {
fwnet_transmit_packet_done(ptask);
} else {
- fw_error("fwnet_write_complete: failed: %x\n", rcode);
fwnet_transmit_packet_failed(ptask);
fwnet_transmit_packet_failed(ptask);
+
+ if (printk_timed_ratelimit(&j, 1000) || rcode != last_rcode) {
+ fw_error("fwnet_write_complete: "
+ "failed: %x (skipped %d)\n", rcode, errors_skipped);
+
+ errors_skipped = 0;
+ last_rcode = rcode;
+ } else
+ errors_skipped++;
}
}
}
}
@@
-1213,6
+1226,14
@@
static int fwnet_broadcast_start(struct fwnet_device *dev)
return retval;
}
return retval;
}
+static void set_carrier_state(struct fwnet_device *dev)
+{
+ if (dev->peer_count > 1)
+ netif_carrier_on(dev->netdev);
+ else
+ netif_carrier_off(dev->netdev);
+}
+
/* ifup */
static int fwnet_open(struct net_device *net)
{
/* ifup */
static int fwnet_open(struct net_device *net)
{
@@
-1226,6
+1247,10
@@
static int fwnet_open(struct net_device *net)
}
netif_start_queue(net);
}
netif_start_queue(net);
+ spin_lock_irq(&dev->lock);
+ set_carrier_state(dev);
+ spin_unlock_irq(&dev->lock);
+
return 0;
}
return 0;
}
@@
-1397,6
+1422,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 = {
.ndo_open = fwnet_open,
.ndo_stop = fwnet_stop,
static const struct net_device_ops fwnet_netdev_ops = {
.ndo_open = fwnet_open,
.ndo_stop = fwnet_stop,
@@
-1415,6
+1444,7
@@
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->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 */
}
/* caller must hold fwnet_device_mutex */
@@
-1443,6
+1473,7
@@
static int fwnet_add_peer(struct fwnet_device *dev,
peer->dev = dev;
peer->guid = (u64)device->config_rom[3] << 32 | device->config_rom[4];
peer->fifo = FWNET_NO_FIFO_ADDR;
peer->dev = dev;
peer->guid = (u64)device->config_rom[3] << 32 | device->config_rom[4];
peer->fifo = FWNET_NO_FIFO_ADDR;
+ peer->ip = 0;
INIT_LIST_HEAD(&peer->pd_list);
peer->pdg_size = 0;
peer->datagram_label = 0;
INIT_LIST_HEAD(&peer->pd_list);
peer->pdg_size = 0;
peer->datagram_label = 0;
@@
-1455,6
+1486,8
@@
static int fwnet_add_peer(struct fwnet_device *dev,
spin_lock_irq(&dev->lock);
list_add_tail(&peer->peer_link, &dev->peer_list);
spin_lock_irq(&dev->lock);
list_add_tail(&peer->peer_link, &dev->peer_list);
+ dev->peer_count++;
+ set_carrier_state(dev);
spin_unlock_irq(&dev->lock);
return 0;
spin_unlock_irq(&dev->lock);
return 0;
@@
-1535,13
+1568,15
@@
static int fwnet_probe(struct device *_dev)
return ret;
}
return ret;
}
-static void fwnet_remove_peer(struct fwnet_peer *peer)
+static void fwnet_remove_peer(struct fwnet_peer *peer
, struct fwnet_device *dev
)
{
struct fwnet_partial_datagram *pd, *pd_next;
{
struct fwnet_partial_datagram *pd, *pd_next;
- spin_lock_irq(&
peer->
dev->lock);
+ spin_lock_irq(&dev->lock);
list_del(&peer->peer_link);
list_del(&peer->peer_link);
- spin_unlock_irq(&peer->dev->lock);
+ dev->peer_count--;
+ set_carrier_state(dev);
+ spin_unlock_irq(&dev->lock);
list_for_each_entry_safe(pd, pd_next, &peer->pd_list, pd_link)
fwnet_pd_delete(pd);
list_for_each_entry_safe(pd, pd_next, &peer->pd_list, pd_link)
fwnet_pd_delete(pd);
@@
-1558,10
+1593,13
@@
static int fwnet_remove(struct device *_dev)
mutex_lock(&fwnet_device_mutex);
mutex_lock(&fwnet_device_mutex);
- fwnet_remove_peer(peer);
+ net = dev->netdev;
+ if (net && peer->ip)
+ arp_invalidate(net, peer->ip);
+
+ fwnet_remove_peer(peer, dev);
if (list_empty(&dev->peer_list)) {
if (list_empty(&dev->peer_list)) {
- net = dev->netdev;
unregister_netdev(net);
if (dev->local_fifo != FWNET_NO_FIFO_ADDR)
unregister_netdev(net);
if (dev->local_fifo != FWNET_NO_FIFO_ADDR)