#include <linux/netdevice.h>
#include <linux/inetdevice.h>
-#include <linux/etherdevice.h>
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
static void ether1394_header_cache_update(struct hh_cache *hh,
struct net_device *dev,
unsigned char *haddr);
-static int ether1394_mac_addr(struct net_device *dev, void *p);
-
static int ether1394_tx(struct sk_buff *skb, struct net_device *dev);
static void ether1394_iso(struct hpsb_iso *iso);
priv->bc_maxpayload = 512;
/* Determine speed limit */
- for (i = 0; i < host->node_count; i++)
+ /* FIXME: This is broken for nodes with link speed < PHY speed,
+ * and it is suboptimal for S200B...S800B hardware.
+ * The result of nodemgr's speed probe should be used somehow. */
+ for (i = 0; i < host->node_count; i++) {
+ /* take care of S100B...S400B PHY ports */
+ if (host->speed[i] == SELFID_SPEED_UNKNOWN) {
+ max_speed = IEEE1394_SPEED_100;
+ break;
+ }
if (max_speed > host->speed[i])
max_speed = host->speed[i];
+ }
priv->bc_sspd = max_speed;
if (set_mtu) {
spin_unlock_irqrestore(&priv->lock, flags);
}
-/* This function is called right before register_netdev */
static void ether1394_init_dev(struct net_device *dev)
{
- /* Our functions */
dev->open = ether1394_open;
dev->stop = ether1394_stop;
dev->hard_start_xmit = ether1394_tx;
dev->hard_header_cache = ether1394_header_cache;
dev->header_cache_update= ether1394_header_cache_update;
dev->hard_header_parse = ether1394_header_parse;
- dev->set_mac_address = ether1394_mac_addr;
+
SET_ETHTOOL_OPS(dev, ðtool_ops);
- /* Some constants */
dev->watchdog_timeo = ETHER1394_TIMEOUT;
dev->flags = IFF_BROADCAST | IFF_MULTICAST;
dev->features = NETIF_F_HIGHDMA;
dev->hard_header_len = ETH1394_HLEN;
dev->type = ARPHRD_IEEE1394;
- ether1394_reset_priv(dev, 1);
+ /* FIXME: This value was copied from ether_setup(). Is it too much? */
+ dev->tx_queue_len = 1000;
}
/*
return;
}
- /* We should really have our own alloc_hpsbdev() function in
- * net_init.c instead of calling the one for ethernet then hijacking
- * it for ourselves. That way we'd be a real networking device. */
- dev = alloc_etherdev(sizeof (struct eth1394_priv));
-
+ dev = alloc_netdev(sizeof(*priv), "eth%d", ether1394_init_dev);
if (dev == NULL) {
ETH1394_PRINT_G(KERN_ERR, "Out of memory\n");
goto out;
#endif
priv = netdev_priv(dev);
-
INIT_LIST_HEAD(&priv->ip_node_list);
-
spin_lock_init(&priv->lock);
priv->host = host;
priv->local_fifo = fifo_addr;
hi = hpsb_create_hostinfo(ð1394_highlevel, host, sizeof(*hi));
-
if (hi == NULL) {
ETH1394_PRINT_G(KERN_ERR, "Out of memory\n");
goto out;
}
- ether1394_init_dev(dev);
+ ether1394_reset_priv(dev, 1);
if (register_netdev(dev)) {
ETH1394_PRINT_G(KERN_ERR, "Cannot register the driver\n");
memcpy((u8 *)hh->hh_data + 16 - ETH1394_HLEN, haddr, dev->addr_len);
}
-static int ether1394_mac_addr(struct net_device *dev, void *p)
-{
- if (netif_running(dev))
- return -EBUSY;
-
- /* Not going to allow setting the MAC address, we really need to use
- * the real one supplied by the hardware */
- return -EINVAL;
-}
-
/******************************************
* Datagram reception code
******************************************/
static int fragment_overlap(struct list_head *frag_list, int offset, int len)
{
struct fragment_info *fi;
+ int end = offset + len;
- list_for_each_entry(fi, frag_list, list) {
- if ( ! ((offset > (fi->offset + fi->len - 1)) ||
- ((offset + len - 1) < fi->offset)))
+ list_for_each_entry(fi, frag_list, list)
+ if (offset < fi->offset + fi->len && end > fi->offset)
return 1;
- }
+
return 0;
}
if (!ud) {
struct eth1394_node_ref *node;
node = eth1394_find_node_nodeid(&priv->ip_node_list, srcid);
- if (!node) {
+ if (unlikely(!node)) {
HPSB_PRINT(KERN_ERR, "ether1394 rx: sender nodeid "
"lookup failure: " NODE_BUS_FMT,
NODE_BUS_ARGS(priv->host, srcid));
* high level network layer. */
skb = dev_alloc_skb(len + dev->hard_header_len + 15);
- if (!skb) {
+ if (unlikely(!skb)) {
ETH1394_PRINT_G(KERN_ERR, "Out of memory\n");
priv->stats.rx_dropped++;
return -1;
struct eth1394_host_info *hi;
hi = hpsb_get_hostinfo(ð1394_highlevel, host);
- if (hi == NULL) {
+ if (unlikely(!hi)) {
ETH1394_PRINT_G(KERN_ERR, "No net device at fw-host%d\n",
host->id);
return RCODE_ADDRESS_ERROR;
int nready;
hi = hpsb_get_hostinfo(ð1394_highlevel, iso->host);
- if (hi == NULL) {
+ if (unlikely(!hi)) {
ETH1394_PRINT_G(KERN_ERR, "No net device at fw-host%d\n",
iso->host->id);
return;
p->data[1] = cpu_to_be32(ETHER1394_GASP_SPECIFIER_ID_LO << 24 |
ETHER1394_GASP_VERSION);
- /* Setting the node id to ALL_NODES (not LOCAL_BUS | ALL_NODES)
- * prevents hpsb_send_packet() from setting the speed to an arbitrary
- * value based on packet->node_id if packet->node_id is not set. */
- p->node_id = ALL_NODES;
p->speed_code = priv->bc_sspd;
+
+ /* prevent hpsb_send_packet() from overriding our speed code */
+ p->node_id = LOCAL_BUS | ALL_NODES;
}
static void ether1394_free_packet(struct hpsb_packet *packet)
/* Transmit a packet (called by kernel) */
static int ether1394_tx(struct sk_buff *skb, struct net_device *dev)
{
- gfp_t kmflags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
struct eth1394hdr *eth;
struct eth1394_priv *priv = netdev_priv(dev);
__be16 proto;
unsigned long flags;
nodeid_t dest_node;
eth1394_tx_type tx_type;
- int ret = 0;
unsigned int tx_len;
unsigned int max_payload;
u16 dg_size;
struct eth1394_node_ref *node;
struct eth1394_node_info *node_info = NULL;
- ptask = kmem_cache_alloc(packet_task_cache, kmflags);
- if (ptask == NULL) {
- ret = -ENOMEM;
+ ptask = kmem_cache_alloc(packet_task_cache, GFP_ATOMIC);
+ if (ptask == NULL)
goto fail;
- }
/* XXX Ignore this for now. Noticed that when MacOSX is the IRM,
* it does not set our validity bit. We need to compensate for
* that somewhere else, but not in eth1394. */
#if 0
- if ((priv->host->csr.broadcast_channel & 0xc0000000) != 0xc0000000) {
- ret = -EAGAIN;
+ if ((priv->host->csr.broadcast_channel & 0xc0000000) != 0xc0000000)
goto fail;
- }
#endif
- skb = skb_share_check(skb, kmflags);
- if (!skb) {
- ret = -ENOMEM;
+ skb = skb_share_check(skb, GFP_ATOMIC);
+ if (!skb)
goto fail;
- }
/* Get rid of the fake eth1394 header, but save a pointer */
eth = (struct eth1394hdr *)skb->data;
node = eth1394_find_node_guid(&priv->ip_node_list,
be64_to_cpu(guid));
- if (!node) {
- ret = -EAGAIN;
+ if (!node)
goto fail;
- }
+
node_info =
(struct eth1394_node_info *)node->ud->device.driver_data;
- if (node_info->fifo == CSR1212_INVALID_ADDR_SPACE) {
- ret = -EAGAIN;
+ if (node_info->fifo == CSR1212_INVALID_ADDR_SPACE)
goto fail;
- }
dest_node = node->ud->ne->nodeid;
max_payload = node_info->maxpayload;
goto fail;
netif_wake_queue(dev);
- return 0;
+ return NETDEV_TX_OK;
fail:
if (ptask)
kmem_cache_free(packet_task_cache, ptask);
if (netif_queue_stopped(dev))
netif_wake_queue(dev);
- return 0; /* returning non-zero causes serious problems */
+ /*
+ * FIXME: According to a patch from 2003-02-26, "returning non-zero
+ * causes serious problems" here, allegedly. Before that patch,
+ * -ERRNO was returned which is not appropriate under Linux 2.6.
+ * Perhaps more needs to be done? Stop the queue in serious
+ * conditions and restart it elsewhere?
+ */
+ /* return NETDEV_TX_BUSY; */
+ return NETDEV_TX_OK;
}
static void ether1394_get_drvinfo(struct net_device *dev,
.get_drvinfo = ether1394_get_drvinfo
};
-static int __init ether1394_init_module (void)
+static int __init ether1394_init_module(void)
{
+ int err;
+
packet_task_cache = kmem_cache_create("packet_task",
sizeof(struct packet_task),
0, 0, NULL, NULL);
+ if (!packet_task_cache)
+ return -ENOMEM;
hpsb_register_highlevel(ð1394_highlevel);
- return hpsb_register_protocol(ð1394_proto_driver);
+ err = hpsb_register_protocol(ð1394_proto_driver);
+ if (err) {
+ hpsb_unregister_highlevel(ð1394_highlevel);
+ kmem_cache_destroy(packet_task_cache);
+ }
+ return err;
}
-static void __exit ether1394_exit_module (void)
+static void __exit ether1394_exit_module(void)
{
hpsb_unregister_protocol(ð1394_proto_driver);
hpsb_unregister_highlevel(ð1394_highlevel);