Commit 9fc6726f authored by Ben Collins's avatar Ben Collins Committed by Linus Torvalds

[PATCH] Update IEEE1394 (r939)

- Adds fragementation support to eth1394
- Fix race conditition in packet completion task call
- Fix lack of proper logic in tlabel allocation
- Fix brokeness introduced by "stanford checker fixes for memset" in
  ohci1394
- Add trivial PM resume callback in ohci1394 to support sleep/resume.
parent 4fe33674
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
* *
* Copyright (C) 2001 Ben Collins <bcollins@debian.org> * Copyright (C) 2001 Ben Collins <bcollins@debian.org>
* 2000 Bonin Franck <boninf@free.fr> * 2000 Bonin Franck <boninf@free.fr>
* 2003 Steve Kinneberg <kinnebergsteve@acmsystems.com>
* *
* Mainly based on work by Emanuel Pirker and Andreas E. Bombe * Mainly based on work by Emanuel Pirker and Andreas E. Bombe
* *
...@@ -21,22 +22,28 @@ ...@@ -21,22 +22,28 @@
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* State of this driver: /* This driver intends to support RFC 2734, which describes a method for
*
* This driver intends to support RFC 2734, which describes a method for
* transporting IPv4 datagrams over IEEE-1394 serial busses. This driver * transporting IPv4 datagrams over IEEE-1394 serial busses. This driver
* will ultimately support that method, but currently falls short in * will ultimately support that method, but currently falls short in
* several areas. A few issues are: * several areas.
*
* TODO:
* RFC 2734 related:
* - Add support for broadcast messages
* - Use EUI instead of node id in internal ARP tables
* - Add Config ROM entry
* - Add MCAP and multicast
* *
* - Does not support send/recv over Async streams using GASP * Non-RFC 2734 related:
* packet formats, as per the RFC for ARP requests. * - Move generic GASP reception to core 1394 code
* - Does not yet support fragmented packets. * - Convert kmalloc/kfree for link fragments to use kmem_cache_* instead
* - Relies on hardware address being equal to the nodeid for some things. * - Stability improvements
* - Does not support multicast * - Performance enhancements
* - Hardcoded address for sending packets, instead of using discovery * - Change hardcoded 1394 bus address region to a dynamic memory space allocation
* (ARP, see first item) * - Consider garbage collecting old partial datagrams after X amount of time
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/sched.h> #include <linux/sched.h>
...@@ -56,7 +63,6 @@ ...@@ -56,7 +63,6 @@
#include <linux/tcp.h> #include <linux/tcp.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/workqueue.h>
#include <asm/delay.h> #include <asm/delay.h>
#include <asm/semaphore.h> #include <asm/semaphore.h>
#include <net/arp.h> #include <net/arp.h>
...@@ -76,10 +82,27 @@ ...@@ -76,10 +82,27 @@
printk(level ETHER1394_DRIVER_NAME": %s: " fmt, dev_name, ## args) printk(level ETHER1394_DRIVER_NAME": %s: " fmt, dev_name, ## args)
#define DEBUG(fmt, args...) \ #define DEBUG(fmt, args...) \
printk(KERN_ERR fmt, ## args) printk(KERN_ERR "eth1394:%s[%d]: "fmt"\n", __FUNCTION__, __LINE__, ## args)
#define TRACE() printk(KERN_ERR "eth1394:%s[%d] ---- TRACE\n", __FUNCTION__, __LINE__)
static char version[] __devinitdata = static char version[] __devinitdata =
"$Rev: 931 $ Ben Collins <bcollins@debian.org>"; "$Rev: 938 $ Ben Collins <bcollins@debian.org>";
struct fragment_info {
struct list_head list;
int offset;
int len;
};
struct partial_datagram {
struct list_head list;
u16 dgl;
u16 dg_size;
u16 ether_type;
struct sk_buff *skb;
char *pbuf;
struct list_head frag_info;
};
/* Our ieee1394 highlevel driver */ /* Our ieee1394 highlevel driver */
#define ETHER1394_DRIVER_NAME "ether1394" #define ETHER1394_DRIVER_NAME "ether1394"
...@@ -89,7 +112,7 @@ static kmem_cache_t *packet_task_cache; ...@@ -89,7 +112,7 @@ static kmem_cache_t *packet_task_cache;
static struct hpsb_highlevel eth1394_highlevel; static struct hpsb_highlevel eth1394_highlevel;
/* Use common.lf to determine header len */ /* Use common.lf to determine header len */
static int hdr_type_len[] = { static const int hdr_type_len[] = {
sizeof (struct eth1394_uf_hdr), sizeof (struct eth1394_uf_hdr),
sizeof (struct eth1394_ff_hdr), sizeof (struct eth1394_ff_hdr),
sizeof (struct eth1394_sf_hdr), sizeof (struct eth1394_sf_hdr),
...@@ -100,16 +123,111 @@ MODULE_AUTHOR("Ben Collins (bcollins@debian.org)"); ...@@ -100,16 +123,111 @@ MODULE_AUTHOR("Ben Collins (bcollins@debian.org)");
MODULE_DESCRIPTION("IEEE 1394 IPv4 Driver (IPv4-over-1394 as per RFC 2734)"); MODULE_DESCRIPTION("IEEE 1394 IPv4 Driver (IPv4-over-1394 as per RFC 2734)");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
/* The max_partial_datagrams parameter is the maximum number of fragmented datagrams
* per node that eth1394 will keep in memory. Providing an upper bound allows us to
* limit the amount of memory that partial datagrams consume in the event that some
* partial datagrams are never completed. This should probably change to a sysctl
* item or the like if possible.
*/
MODULE_PARM(max_partial_datagrams, "i");
MODULE_PARM_DESC(max_partial_datagrams,
"Maximum number of partially received fragmented datagrams (default = 25).");
static int max_partial_datagrams = 25;
static inline void purge_partial_datagram(struct list_head *old);
static int ether1394_tx(struct sk_buff *skb, struct net_device *dev);
static void ether1394_iso(struct hpsb_iso *iso); static void ether1394_iso(struct hpsb_iso *iso);
static int ether1394_init_bc(struct net_device *dev)
{
int ret = 0;
struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;
/* First time sending? Need a broadcast channel for ARP and for
* listening on */
if(priv->bc_state == ETHER1394_BC_CHECK) {
quadlet_t bc;
/* Get the local copy of the broadcast channel and check its
* validity (the IRM should validate it for us) */
bc = priv->host->csr.broadcast_channel;
if((bc & 0xc0000000) != 0xc0000000) {
/* broadcast channel not validated yet */
ETH1394_PRINT(KERN_WARNING, dev->name,
"Error BROADCAST_CHANNEL register valid "
"bit not set, can't send IP traffic\n");
if(!in_interrupt()) {
hpsb_iso_shutdown(priv->iso);
priv->bc_state = ETHER1394_BC_CLOSED;
}
ret = -EAGAIN;
goto fail;
}
if(priv->broadcast_channel != (bc & 0x3f)) {
/* This really shouldn't be possible, but just in case
* the IEEE 1394 spec changes regarding broadcast
* channels in the future. */
if(in_interrupt()) {
ret = -EAGAIN;
goto fail;
}
hpsb_iso_shutdown(priv->iso);
priv->broadcast_channel = bc & 0x3f;
ETH1394_PRINT(KERN_INFO, dev->name,
"Changing to broadcast channel %d...\n",
priv->broadcast_channel);
priv->iso = hpsb_iso_recv_init(priv->host, 16 * 4096,
16, priv->broadcast_channel,
1, ether1394_iso);
if(priv->iso == NULL) {
ETH1394_PRINT(KERN_ERR, dev->name,
"failed to change broadcast "
"channel\n");
ret = -EAGAIN;
goto fail;
}
}
if(hpsb_iso_recv_start(priv->iso, -1, (1 << 3), -1) < 0) {
ETH1394_PRINT(KERN_ERR, dev->name,
"Could not start data stream reception\n");
if(!in_interrupt()) {
hpsb_iso_shutdown(priv->iso);
priv->bc_state = ETHER1394_BC_CLOSED;
}
ret = -EAGAIN;
goto fail;
}
priv->bc_state = ETHER1394_BC_OPENED;
}
fail:
return ret;
}
/* This is called after an "ifup" */ /* This is called after an "ifup" */
static int ether1394_open (struct net_device *dev) static int ether1394_open (struct net_device *dev)
{ {
struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv; struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;
unsigned long flags;
int ret;
/* Set the spinlock before grabbing IRQ! */ /* Set the spinlock before grabbing IRQ! */
priv->lock = SPIN_LOCK_UNLOCKED; priv->lock = SPIN_LOCK_UNLOCKED;
spin_lock_irqsave(&priv->lock, flags);
ret = ether1394_init_bc(dev);
spin_unlock_irqrestore(&priv->lock, flags);
if(ret)
return ret;
netif_start_queue (dev); netif_start_queue (dev);
return 0; return 0;
...@@ -140,34 +258,6 @@ static void ether1394_tx_timeout (struct net_device *dev) ...@@ -140,34 +258,6 @@ static void ether1394_tx_timeout (struct net_device *dev)
netif_wake_queue (dev); netif_wake_queue (dev);
} }
/* We need to encapsulate the standard header with our own. We use the
* ethernet header's proto for our own.
*
* XXX: This is where we need to create a list of skb's for fragmented
* packets. */
static inline void ether1394_encapsulate (struct sk_buff *skb, struct net_device *dev,
int proto, struct packet_task *ptask)
{
union eth1394_hdr *hdr =
(union eth1394_hdr *)skb_push (skb, hdr_type_len[ETH1394_HDR_LF_UF]);
hdr->words.word1 = 0;
hdr->common.lf = ETH1394_HDR_LF_UF;
hdr->words.word1 = htons(hdr->words.word1);
hdr->uf.ether_type = proto;
/* Set the transmission type for the packet. Right now only ARP
* packets are sent via GASP. IP broadcast and IP multicast are not
* yet supported properly, they too should use GASP. */
switch(proto) {
case __constant_htons(ETH_P_ARP):
ptask->tx_type = ETH1394_GASP;
break;
default:
ptask->tx_type = ETH1394_WRREQ;
}
return;
}
/* Convert a standard ARP packet to 1394 ARP. The first 8 bytes (the /* Convert a standard ARP packet to 1394 ARP. The first 8 bytes (the
* entire arphdr) is the same format as the ip1394 header, so they * entire arphdr) is the same format as the ip1394 header, so they
...@@ -223,8 +313,6 @@ static inline void ether1394_register_limits (int nodeid, unsigned char max_rec, ...@@ -223,8 +313,6 @@ static inline void ether1394_register_limits (int nodeid, unsigned char max_rec,
unsigned char sspd, u64 eui, u16 fifo_hi, unsigned char sspd, u64 eui, u16 fifo_hi,
u32 fifo_lo, struct eth1394_priv *priv) u32 fifo_lo, struct eth1394_priv *priv)
{ {
int i;
if (nodeid < 0 || nodeid >= ALL_NODES) { if (nodeid < 0 || nodeid >= ALL_NODES) {
ETH1394_PRINT_G (KERN_ERR, "Cannot register invalid nodeid %d\n", nodeid); ETH1394_PRINT_G (KERN_ERR, "Cannot register invalid nodeid %d\n", nodeid);
return; return;
...@@ -236,20 +324,8 @@ static inline void ether1394_register_limits (int nodeid, unsigned char max_rec, ...@@ -236,20 +324,8 @@ static inline void ether1394_register_limits (int nodeid, unsigned char max_rec,
priv->fifo_lo[nodeid] = fifo_lo; priv->fifo_lo[nodeid] = fifo_lo;
priv->eui[nodeid] = eui; priv->eui[nodeid] = eui;
/* 63 is used for broadcasts to all hosts. It is equal to the priv->max_rec[ALL_NODES] = min(priv->max_rec[ALL_NODES], max_rec);
* minimum of all registered nodes. A registered node is one with priv->sspd[ALL_NODES] = min(priv->sspd[ALL_NODES], sspd);
* a nonzero offset. Set the values rediculously high to start. We
* know we have atleast one to change the default to. */
sspd = 0xff;
max_rec = 0xff;
for (i = 0; i < ALL_NODES; i++) {
if (!priv->fifo_hi && !priv->fifo_lo) continue; /* Unregistered */
if (priv->max_rec[i] < max_rec) max_rec = priv->max_rec[i];
if (priv->sspd[i] < sspd) sspd = priv->sspd[i];
}
priv->max_rec[ALL_NODES] = max_rec;
priv->sspd[ALL_NODES] = sspd;
return; return;
} }
...@@ -257,6 +333,7 @@ static inline void ether1394_register_limits (int nodeid, unsigned char max_rec, ...@@ -257,6 +333,7 @@ static inline void ether1394_register_limits (int nodeid, unsigned char max_rec,
static void ether1394_reset_priv (struct net_device *dev, int set_mtu) static void ether1394_reset_priv (struct net_device *dev, int set_mtu)
{ {
unsigned long flags; unsigned long flags;
int i;
struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv; struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;
int phy_id = NODEID_TO_NODE(priv->host->node_id); int phy_id = NODEID_TO_NODE(priv->host->node_id);
struct hpsb_host *host = priv->host; struct hpsb_host *host = priv->host;
...@@ -264,7 +341,7 @@ static void ether1394_reset_priv (struct net_device *dev, int set_mtu) ...@@ -264,7 +341,7 @@ static void ether1394_reset_priv (struct net_device *dev, int set_mtu)
spin_lock_irqsave (&priv->lock, flags); spin_lock_irqsave (&priv->lock, flags);
/* Clear the speed/payload/offset tables */ /* Clear the speed/payload/offset tables */
memset (priv->max_rec, 0, sizeof (priv->max_rec)); memset (priv->max_rec, 8, sizeof (priv->max_rec));
memset (priv->sspd, 0, sizeof (priv->sspd)); memset (priv->sspd, 0, sizeof (priv->sspd));
memset (priv->fifo_hi, 0, sizeof (priv->fifo_hi)); memset (priv->fifo_hi, 0, sizeof (priv->fifo_hi));
memset (priv->fifo_lo, 0, sizeof (priv->fifo_lo)); memset (priv->fifo_lo, 0, sizeof (priv->fifo_lo));
...@@ -281,16 +358,28 @@ static void ether1394_reset_priv (struct net_device *dev, int set_mtu) ...@@ -281,16 +358,28 @@ static void ether1394_reset_priv (struct net_device *dev, int set_mtu)
/* We'll use our max_rec as the default mtu */ /* We'll use our max_rec as the default mtu */
if (set_mtu) if (set_mtu)
dev->mtu = (1 << (priv->max_rec[phy_id] + 1)) - /* mtu = max_rec - */ dev->mtu = (1 << (priv->max_rec[phy_id] + 1)) -
(sizeof (union eth1394_hdr) + 8); /* (hdr + GASP) */ (sizeof (union eth1394_hdr) + ETHER1394_OVERHEAD);
/* Set our hardware address while we're at it */ /* Set our hardware address while we're at it */
*(nodeid_t *)dev->dev_addr = htons (host->node_id); *(nodeid_t *)dev->dev_addr = htons (host->node_id);
spin_unlock_irqrestore (&priv->lock, flags); spin_unlock_irqrestore (&priv->lock, flags);
}
static int ether1394_tx (struct sk_buff *skb, struct net_device *dev); for(i = 0; i < ALL_NODES; i++) {
struct list_head *lh, *n;
spin_lock_irqsave(&priv->pdg[i].lock, flags);
if(!set_mtu) {
list_for_each_safe(lh, n, &priv->pdg[i].list) {
purge_partial_datagram(lh);
}
}
INIT_LIST_HEAD(&(priv->pdg[i].list));
priv->pdg[i].sz = 0;
spin_unlock_irqrestore(&priv->pdg[i].lock, flags);
}
}
/* This function is called by register_netdev */ /* This function is called by register_netdev */
static int ether1394_init_dev (struct net_device *dev) static int ether1394_init_dev (struct net_device *dev)
...@@ -321,6 +410,7 @@ static int ether1394_init_dev (struct net_device *dev) ...@@ -321,6 +410,7 @@ static int ether1394_init_dev (struct net_device *dev)
*/ */
static void ether1394_add_host (struct hpsb_host *host) static void ether1394_add_host (struct hpsb_host *host)
{ {
int i;
struct host_info *hi = NULL; struct host_info *hi = NULL;
struct net_device *dev = NULL; struct net_device *dev = NULL;
struct eth1394_priv *priv; struct eth1394_priv *priv;
...@@ -343,6 +433,12 @@ static void ether1394_add_host (struct hpsb_host *host) ...@@ -343,6 +433,12 @@ static void ether1394_add_host (struct hpsb_host *host)
priv->host = host; priv->host = host;
spin_lock_init(&priv->lock); spin_lock_init(&priv->lock);
for(i = 0; i < ALL_NODES; i++) {
spin_lock_init(&priv->pdg[i].lock);
INIT_LIST_HEAD(&priv->pdg[i].list);
priv->pdg[i].sz = 0;
}
hi = hpsb_create_hostinfo(&eth1394_highlevel, host, sizeof(*hi)); hi = hpsb_create_hostinfo(&eth1394_highlevel, host, sizeof(*hi));
if (hi == NULL) if (hi == NULL)
...@@ -360,10 +456,10 @@ static void ether1394_add_host (struct hpsb_host *host) ...@@ -360,10 +456,10 @@ static void ether1394_add_host (struct hpsb_host *host)
hi->dev = dev; hi->dev = dev;
/* Ignore validity in hopes that it will be set in the future. It'll /* Ignore validity in hopes that it will be set in the future. It'll
* check it on transmit. */ * be checked when the eth device is opened. */
priv->broadcast_channel = host->csr.broadcast_channel & 0x3f; priv->broadcast_channel = host->csr.broadcast_channel & 0x3f;
priv->iso = hpsb_iso_recv_init(host, 8 * 4096, 8, priv->broadcast_channel, priv->iso = hpsb_iso_recv_init(host, 16 * 4096, 16, priv->broadcast_channel,
1, ether1394_iso); 1, ether1394_iso);
if (priv->iso == NULL) { if (priv->iso == NULL) {
priv->bc_state = ETHER1394_BC_CLOSED; priv->bc_state = ETHER1394_BC_CLOSED;
...@@ -372,7 +468,7 @@ static void ether1394_add_host (struct hpsb_host *host) ...@@ -372,7 +468,7 @@ static void ether1394_add_host (struct hpsb_host *host)
out: out:
if (dev != NULL) if (dev != NULL)
kfree (dev); kfree (dev); dev = NULL;
if (hi) if (hi)
hpsb_destroy_hostinfo(&eth1394_highlevel, host); hpsb_destroy_hostinfo(&eth1394_highlevel, host);
...@@ -393,7 +489,7 @@ static void ether1394_remove_host (struct hpsb_host *host) ...@@ -393,7 +489,7 @@ static void ether1394_remove_host (struct hpsb_host *host)
unregister_netdev (hi->dev); unregister_netdev (hi->dev);
hpsb_iso_shutdown(priv->iso); hpsb_iso_shutdown(priv->iso);
kfree (hi->dev); kfree (hi->dev); hi->dev = NULL;
} }
return; return;
...@@ -417,6 +513,11 @@ static void ether1394_host_reset (struct hpsb_host *host) ...@@ -417,6 +513,11 @@ static void ether1394_host_reset (struct hpsb_host *host)
netif_wake_queue (dev); netif_wake_queue (dev);
} }
/******************************************
* Datagram reception code
******************************************/
/* Copied from net/ethernet/eth.c */ /* Copied from net/ethernet/eth.c */
static inline unsigned short ether1394_type_trans(struct sk_buff *skb, struct net_device *dev) static inline unsigned short ether1394_type_trans(struct sk_buff *skb, struct net_device *dev)
{ {
...@@ -451,9 +552,8 @@ static inline unsigned short ether1394_type_trans(struct sk_buff *skb, struct ne ...@@ -451,9 +552,8 @@ static inline unsigned short ether1394_type_trans(struct sk_buff *skb, struct ne
/* Parse an encapsulated IP1394 header into an ethernet frame packet. /* Parse an encapsulated IP1394 header into an ethernet frame packet.
* We also perform ARP translation here, if need be. */ * We also perform ARP translation here, if need be. */
static inline unsigned short ether1394_parse_encap (struct sk_buff *skb, struct net_device *dev, static inline unsigned short ether1394_parse_encap (struct sk_buff *skb, struct net_device *dev,
nodeid_t srcid, nodeid_t destid) nodeid_t srcid, nodeid_t destid, u16 ether_type)
{ {
union eth1394_hdr *hdr = (union eth1394_hdr *)skb->data;
unsigned char src_hw[ETH_ALEN], dest_hw[ETH_ALEN]; unsigned char src_hw[ETH_ALEN], dest_hw[ETH_ALEN];
unsigned short ret = 0; unsigned short ret = 0;
...@@ -462,14 +562,10 @@ static inline unsigned short ether1394_parse_encap (struct sk_buff *skb, struct ...@@ -462,14 +562,10 @@ static inline unsigned short ether1394_parse_encap (struct sk_buff *skb, struct
*(u16 *)dest_hw = htons(destid); *(u16 *)dest_hw = htons(destid);
*(u16 *)src_hw = htons(srcid); *(u16 *)src_hw = htons(srcid);
/* Remove the encapsulation header */
hdr->words.word1 = ntohs(hdr->words.word1);
skb_pull (skb, hdr_type_len[hdr->common.lf]);
/* If this is an ARP packet, convert it. First, we want to make /* If this is an ARP packet, convert it. First, we want to make
* use of some of the fields, since they tell us a little bit * use of some of the fields, since they tell us a little bit
* about the sending machine. */ * about the sending machine. */
if (hdr->uf.ether_type == __constant_htons (ETH_P_ARP)) { if (ether_type == __constant_htons (ETH_P_ARP)) {
unsigned long flags; unsigned long flags;
u16 phy_id = NODEID_TO_NODE(srcid); u16 phy_id = NODEID_TO_NODE(srcid);
struct eth1394_priv *priv = struct eth1394_priv *priv =
...@@ -503,49 +599,318 @@ static inline unsigned short ether1394_parse_encap (struct sk_buff *skb, struct ...@@ -503,49 +599,318 @@ static inline unsigned short ether1394_parse_encap (struct sk_buff *skb, struct
} }
/* Now add the ethernet header. */ /* Now add the ethernet header. */
if (dev->hard_header (skb, dev, __constant_ntohs (hdr->uf.ether_type), if (dev->hard_header (skb, dev, __constant_ntohs (ether_type),
dest_hw, src_hw, skb->len) >= 0) dest_hw, src_hw, skb->len) >= 0)
ret = ether1394_type_trans(skb, dev); ret = ether1394_type_trans(skb, dev);
return ret; return ret;
} }
static inline int fragment_overlap(struct list_head *frag_list, int offset, int len)
{
struct list_head *lh;
struct fragment_info *fi;
list_for_each(lh, frag_list) {
fi = list_entry(lh, struct fragment_info, list);
if( ! ((offset > (fi->offset + fi->len - 1)) ||
((offset + len - 1) < fi->offset)))
return 1;
}
return 0;
}
static inline struct list_head *find_partial_datagram(struct list_head *pdgl, int dgl)
{
struct list_head *lh;
struct partial_datagram *pd;
list_for_each(lh, pdgl) {
pd = list_entry(lh, struct partial_datagram, list);
if(pd->dgl == dgl)
return lh;
}
return NULL;
}
/* Assumes that new fragment does not overlap any existing fragments */
static inline int new_fragment(struct list_head *frag_info, int offset, int len)
{
struct list_head *lh;
struct fragment_info *fi, *fi2, *new;
list_for_each(lh, frag_info) {
fi = list_entry(lh, struct fragment_info, list);
if((fi->offset + fi->len) == offset) {
/* The new fragment can be tacked on to the end */
fi->len += len;
/* Did the new fragment plug a hole? */
fi2 = list_entry(lh->next, struct fragment_info, list);
if((fi->offset + fi->len) == fi2->offset) {
/* glue fragments together */
fi->len += fi2->len;
list_del(lh->next);
kfree(fi2); fi2 = NULL;
}
return 0;
} else if((offset + len) == fi->offset) {
/* The new fragment can be tacked on to the beginning */
fi->offset = offset;
fi->len += len;
/* Did the new fragment plug a hole? */
fi2 = list_entry(lh->prev, struct fragment_info, list);
if((fi2->offset + fi2->len) == fi->offset) {
/* glue fragments together */
fi2->len += fi->len;
list_del(lh);
kfree(fi); fi = NULL;
}
return 0;
} else if(offset > (fi->offset + fi->len)) {
break;
} else if ((offset + len) < fi->offset) {
lh = lh->prev;
break;
}
}
new = kmalloc(sizeof(struct fragment_info), GFP_ATOMIC);
if(!new)
return -ENOMEM;
new->offset = offset;
new->len = len;
list_add(&new->list, lh);
return 0;
}
static inline int new_partial_datagram(struct net_device *dev,
struct list_head *pdgl, int dgl,
int dg_size, char *frag_buf,
int frag_off, int frag_len)
{
struct partial_datagram *new;
new = kmalloc(sizeof(struct partial_datagram), GFP_ATOMIC);
if(!new)
return -ENOMEM;
INIT_LIST_HEAD(&new->frag_info);
if(new_fragment(&new->frag_info, frag_off, frag_len) < 0) {
kfree(new); new = NULL;
return -ENOMEM;
}
new->dgl = dgl;
new->dg_size = dg_size;
new->skb = dev_alloc_skb(dg_size + dev->hard_header_len + 15);
if(!new->skb) {
struct fragment_info *fi = list_entry(new->frag_info.next,
struct fragment_info,
list);
kfree(fi); fi = NULL;
kfree(new); new = NULL;
return -ENOMEM;
}
skb_reserve(new->skb, (dev->hard_header_len + 15) & ~15);
new->pbuf = skb_put(new->skb, dg_size);
memcpy(new->pbuf + frag_off, frag_buf, frag_len);
list_add(&new->list, pdgl);
return 0;
}
static inline int update_partial_datagram(struct list_head *pdgl, struct list_head *lh,
char *frag_buf, int frag_off, int frag_len)
{
struct partial_datagram *pd = list_entry(lh, struct partial_datagram, list);
if(new_fragment(&pd->frag_info, frag_off, frag_len) < 0) {
return -ENOMEM;
}
memcpy(pd->pbuf + frag_off, frag_buf, frag_len);
/* Move list entry to beginnig of list so that oldest partial
* datagrams percolate to the end of the list */
list_del(lh);
list_add(lh, pdgl);
return 0;
}
static inline void purge_partial_datagram(struct list_head *old)
{
struct partial_datagram *pd = list_entry(old, struct partial_datagram, list);
struct list_head *lh, *n;
list_for_each_safe(lh, n, &pd->frag_info) {
struct fragment_info *fi = list_entry(lh, struct fragment_info, list);
list_del(lh);
kfree(fi); fi = NULL;
}
list_del(old);
kfree_skb(pd->skb); pd->skb = NULL;
kfree(pd); pd = NULL;
}
static inline int is_datagram_complete(struct list_head *lh, int dg_size)
{
struct partial_datagram *pd = list_entry(lh, struct partial_datagram, list);
struct fragment_info *fi = list_entry(pd->frag_info.next,
struct fragment_info, list);
return (fi->len == dg_size);
}
/* Packet reception. We convert the IP1394 encapsulation header to an /* Packet reception. We convert the IP1394 encapsulation header to an
* ethernet header, and fill it with some of our other fields. This is * ethernet header, and fill it with some of our other fields. This is
* an incoming packet from the 1394 bus. */ * an incoming packet from the 1394 bus. */
static int ether1394_write (struct hpsb_host *host, int srcid, int destid, static int ether1394_data_handler(struct net_device *dev, int srcid, int destid,
quadlet_t *data, u64 addr, unsigned int len, u16 fl) char *buf, int len)
{ {
struct sk_buff *skb; struct sk_buff *skb;
char *buf = (char *)data;
unsigned long flags; unsigned long flags;
struct host_info *hi = hpsb_get_hostinfo(&eth1394_highlevel, host);
struct net_device *dev;
struct eth1394_priv *priv; struct eth1394_priv *priv;
union eth1394_hdr *hdr = (union eth1394_hdr *)buf;
u16 ether_type = 0; /* initialized to clear warning */
int hdr_len;
if (hi == NULL) { priv = (struct eth1394_priv *)dev->priv;
ETH1394_PRINT_G (KERN_ERR, "Could not find net device for host %p\n",
host);
return RCODE_ADDRESS_ERROR;
}
dev = hi->dev; /* First, did we receive a fragmented or unfragmented datagram? */
hdr->words.word1 = ntohs(hdr->words.word1);
priv = (struct eth1394_priv *)dev->priv; hdr_len = hdr_type_len[hdr->common.lf];
/* A packet has been received by the ieee1394 bus. Build an skbuff if(hdr->common.lf == ETH1394_HDR_LF_UF) {
* around it so we can pass it to the high level network layer. */ /* An unfragmented datagram has been received by the ieee1394
* bus. Build an skbuff around it so we can pass it to the
* high level network layer. */
skb = dev_alloc_skb (len + dev->hard_header_len + 15); skb = dev_alloc_skb(len + dev->hard_header_len + 15);
if (!skb) { if (!skb) {
HPSB_PRINT (KERN_ERR, "ether1394 rx: low on mem\n"); HPSB_PRINT (KERN_ERR, "ether1394 rx: low on mem\n");
priv->stats.rx_dropped++; priv->stats.rx_dropped++;
return RCODE_ADDRESS_ERROR; return -1;
} }
skb_reserve(skb, (dev->hard_header_len + 15) & ~15); skb_reserve(skb, (dev->hard_header_len + 15) & ~15);
memcpy(skb_put(skb, len - hdr_len), buf + hdr_len, len - hdr_len);
ether_type = hdr->uf.ether_type;
} else {
#if 0
return 0;
}
if(0) {
#endif
/* A datagram fragment has been received, now the fun begins. */
struct list_head *pdgl, *lh;
struct partial_datagram *pd;
int fg_off;
int fg_len = len - hdr_len;
int dg_size;
int dgl;
int retval;
int sid = NODEID_TO_NODE(srcid);
struct pdg_list *pdg = &(priv->pdg[sid]);
hdr->words.word3 = ntohs(hdr->words.word3);
/* The 4th header word is reserved so no need to do ntohs() */
if(hdr->common.lf == ETH1394_HDR_LF_FF) {
ether_type = hdr->ff.ether_type;
dgl = hdr->ff.dgl;
dg_size = hdr->ff.dg_size;
fg_off = 0;
} else {
hdr->words.word2 = ntohs(hdr->words.word2);
dgl = hdr->sf.dgl;
dg_size = hdr->sf.dg_size;
fg_off = hdr->sf.fg_off;
}
spin_lock_irqsave(&pdg->lock, flags);
pdgl = &(pdg->list);
lh = find_partial_datagram(pdgl, dgl);
if(lh == NULL) {
if(pdg->sz == max_partial_datagrams) {
/* remove the oldest */
purge_partial_datagram(pdgl->prev);
pdg->sz--;
}
retval = new_partial_datagram(dev, pdgl, dgl, dg_size,
buf + hdr_len, fg_off,
fg_len);
if(retval < 0) {
spin_unlock_irqrestore(&pdg->lock, flags);
goto bad_proto;
}
pdg->sz++;
lh = find_partial_datagram(pdgl, dgl);
} else {
struct partial_datagram *pd;
pd = list_entry(lh, struct partial_datagram, list);
if(fragment_overlap(&pd->frag_info, fg_off, fg_len)) {
/* Overlapping fragments, obliterate old
* datagram and start new one. */
purge_partial_datagram(lh);
retval = new_partial_datagram(dev, pdgl, dgl,
dg_size,
buf + hdr_len,
fg_off, fg_len);
if(retval < 0) {
pdg->sz--;
spin_unlock_irqrestore(&pdg->lock, flags);
goto bad_proto;
}
} else {
retval = update_partial_datagram(pdgl, lh,
buf + hdr_len,
fg_off, fg_len);
if(retval < 0) {
/* Couldn't save off fragment anyway
* so might as well obliterate the
* datagram now. */
purge_partial_datagram(lh);
pdg->sz--;
spin_unlock_irqrestore(&pdg->lock, flags);
goto bad_proto;
}
} /* fragment overlap */
} /* new datagram or add to existing one */
pd = list_entry(lh, struct partial_datagram, list);
if(hdr->common.lf == ETH1394_HDR_LF_FF) {
pd->ether_type = ether_type;
}
memcpy (skb_put (skb, len), buf, len); if(is_datagram_complete(lh, dg_size)) {
ether_type = pd->ether_type;
pdg->sz--;
skb = skb_get(pd->skb);
purge_partial_datagram(lh);
spin_unlock_irqrestore(&pdg->lock, flags);
} else {
/* Datagram is not complete, we're done for the
* moment. */
spin_unlock_irqrestore(&pdg->lock, flags);
return 0;
}
} /* unframgented datagram or fragmented one */
/* Write metadata, and then pass to the receive level */ /* Write metadata, and then pass to the receive level */
skb->dev = dev; skb->dev = dev;
...@@ -555,18 +920,19 @@ static int ether1394_write (struct hpsb_host *host, int srcid, int destid, ...@@ -555,18 +920,19 @@ static int ether1394_write (struct hpsb_host *host, int srcid, int destid,
* converting to an ethernet frame header, aswell as arp * converting to an ethernet frame header, aswell as arp
* conversion if needed. ARP conversion is easier in this * conversion if needed. ARP conversion is easier in this
* direction, since we are using ethernet as our backend. */ * direction, since we are using ethernet as our backend. */
skb->protocol = ether1394_parse_encap (skb, dev, srcid, destid); skb->protocol = ether1394_parse_encap(skb, dev, srcid, destid,
ether_type);
spin_lock_irqsave (&priv->lock, flags);
if (!skb->protocol) { spin_lock_irqsave(&priv->lock, flags);
if(!skb->protocol) {
priv->stats.rx_errors++; priv->stats.rx_errors++;
priv->stats.rx_dropped++; priv->stats.rx_dropped++;
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
goto bad_proto; goto bad_proto;
} }
netif_stop_queue(dev); if(netif_rx(skb) == NET_RX_DROP) {
if (netif_rx (skb) == NET_RX_DROP) {
priv->stats.rx_errors++; priv->stats.rx_errors++;
priv->stats.rx_dropped++; priv->stats.rx_dropped++;
goto bad_proto; goto bad_proto;
...@@ -577,20 +943,36 @@ static int ether1394_write (struct hpsb_host *host, int srcid, int destid, ...@@ -577,20 +943,36 @@ static int ether1394_write (struct hpsb_host *host, int srcid, int destid,
priv->stats.rx_bytes += skb->len; priv->stats.rx_bytes += skb->len;
bad_proto: bad_proto:
netif_start_queue(dev); if(netif_queue_stopped(dev))
spin_unlock_irqrestore (&priv->lock, flags); netif_wake_queue(dev);
spin_unlock_irqrestore(&priv->lock, flags);
dev->last_rx = jiffies; dev->last_rx = jiffies;
return 0;
}
static int ether1394_write(struct hpsb_host *host, int srcid, int destid,
quadlet_t *data, u64 addr, unsigned int len, u16 flags)
{
struct host_info *hi = hpsb_get_hostinfo(&eth1394_highlevel, host);
if(hi == NULL) {
ETH1394_PRINT_G(KERN_ERR, "Could not find net device for host %s\n",
host->driver->name);
return RCODE_ADDRESS_ERROR;
}
if(ether1394_data_handler(hi->dev, srcid, destid, (char*)data, len))
return RCODE_ADDRESS_ERROR;
else
return RCODE_COMPLETE; return RCODE_COMPLETE;
} }
static void ether1394_iso(struct hpsb_iso *iso) static void ether1394_iso(struct hpsb_iso *iso)
{ {
struct sk_buff *skb;
quadlet_t *data; quadlet_t *data;
char *buf; char *buf;
unsigned long flags;
struct host_info *hi = hpsb_get_hostinfo(&eth1394_highlevel, iso->host); struct host_info *hi = hpsb_get_hostinfo(&eth1394_highlevel, iso->host);
struct net_device *dev; struct net_device *dev;
struct eth1394_priv *priv; struct eth1394_priv *priv;
...@@ -600,8 +982,8 @@ static void ether1394_iso(struct hpsb_iso *iso) ...@@ -600,8 +982,8 @@ static void ether1394_iso(struct hpsb_iso *iso)
int i; int i;
int nready; int nready;
if (hi == NULL) { if(hi == NULL) {
ETH1394_PRINT_G (KERN_ERR, "Could not find net device for host %s\n", ETH1394_PRINT_G(KERN_ERR, "Could not find net device for host %s\n",
iso->host->driver->name); iso->host->driver->name);
return; return;
} }
...@@ -623,186 +1005,289 @@ static void ether1394_iso(struct hpsb_iso *iso) ...@@ -623,186 +1005,289 @@ static void ether1394_iso(struct hpsb_iso *iso)
priv = (struct eth1394_priv *)dev->priv; priv = (struct eth1394_priv *)dev->priv;
if (info->channel != priv->broadcast_channel || if(info->channel != (iso->host->csr.broadcast_channel & 0x3f) ||
specifier_id != ETHER1394_GASP_SPECIFIER_ID) { specifier_id != ETHER1394_GASP_SPECIFIER_ID) {
/* This packet is not for us */ /* This packet is not for us */
continue; continue;
} }
ether1394_data_handler(dev, source_id, iso->host->node_id, buf, len);
}
/* A packet has been received by the ieee1394 bus. Build an skbuff hpsb_iso_recv_release_packets(iso, i);
* around it so we can pass it to the high level network layer. */
skb = dev_alloc_skb (len + dev->hard_header_len + 15); dev->last_rx = jiffies;
if (!skb) { }
HPSB_PRINT (KERN_ERR, "ether1394 rx: low on mem\n");
priv->stats.rx_dropped++; /******************************************
break; * Datagram transmission code
******************************************/
/* We need to encapsulate the standard header with our own. We use the
* ethernet header's proto for our own. */
static inline unsigned int ether1394_encapsulate_prep(unsigned int max_payload,
int proto,
union eth1394_hdr *hdr,
u16 dg_size, u16 dgl)
{
unsigned int adj_max_payload = max_payload - hdr_type_len[ETH1394_HDR_LF_UF];
/* Does it all fit in one packet? */
if(dg_size <= adj_max_payload) {
hdr->uf.lf = ETH1394_HDR_LF_UF;
hdr->uf.ether_type = proto;
} else {
hdr->ff.lf = ETH1394_HDR_LF_FF;
hdr->ff.ether_type = proto;
hdr->ff.dg_size = dg_size;
hdr->ff.dgl = dgl;
adj_max_payload = max_payload - hdr_type_len[ETH1394_HDR_LF_FF];
} }
skb_reserve(skb, (dev->hard_header_len + 15) & ~15); return((dg_size + (adj_max_payload - 1)) / adj_max_payload);
}
memcpy (skb_put (skb, len), buf, len); static inline unsigned int ether1394_encapsulate(struct sk_buff *skb,
unsigned int max_payload,
union eth1394_hdr *hdr)
{
union eth1394_hdr *bufhdr;
int ftype = hdr->common.lf;
int hdrsz = hdr_type_len[ftype];
unsigned int adj_max_payload = max_payload - hdrsz;
switch(ftype) {
case ETH1394_HDR_LF_UF:
bufhdr = (union eth1394_hdr *)skb_push(skb, hdrsz);
bufhdr->words.word1 = htons(hdr->words.word1);
bufhdr->words.word2 = hdr->words.word2;
break;
/* Write metadata, and then pass to the receive level */ case ETH1394_HDR_LF_FF:
skb->dev = dev; bufhdr = (union eth1394_hdr *)skb_push(skb, hdrsz);
skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */ bufhdr->words.word1 = htons(hdr->words.word1);
bufhdr->words.word2 = hdr->words.word2;
bufhdr->words.word3 = htons(hdr->words.word3);
bufhdr->words.word4 = 0;
/* Parse the encapsulation header. This actually does the job of /* Set frag type here for future interior fragments */
* converting to an ethernet frame header, aswell as arp hdr->common.lf = ETH1394_HDR_LF_IF;
* conversion if needed. ARP conversion is easier in this hdr->sf.fg_off = 0;
* direction, since we are using ethernet as our backend. */ break;
skb->protocol = ether1394_parse_encap (skb, dev, source_id,
LOCAL_BUS | ALL_NODES);
spin_lock_irqsave (&priv->lock, flags); default:
if (!skb->protocol) { hdr->sf.fg_off += adj_max_payload;
priv->stats.rx_errors++; bufhdr = (union eth1394_hdr *)skb_pull(skb, adj_max_payload);
priv->stats.rx_dropped++; if(max_payload >= skb->len)
dev_kfree_skb_any(skb); hdr->common.lf = ETH1394_HDR_LF_LF;
goto bad_proto; bufhdr->words.word1 = htons(hdr->words.word1);
bufhdr->words.word2 = htons(hdr->words.word2);
bufhdr->words.word3 = htons(hdr->words.word3);
bufhdr->words.word4 = 0;
} }
netif_stop_queue(dev); return min(max_payload, skb->len);
if (netif_rx (skb) == NET_RX_DROP) { }
priv->stats.rx_errors++;
priv->stats.rx_dropped++; static inline struct hpsb_packet *ether1394_alloc_common_packet(struct hpsb_host *host)
goto bad_proto; {
struct hpsb_packet *p;
p = alloc_hpsb_packet(0);
if(p) {
p->host = host;
p->data = NULL;
p->generation = get_hpsb_generation(host);
p->type = hpsb_async;
} }
return p;
}
/* Statistics */ static inline int ether1394_prep_write_packet(struct hpsb_packet *p,
priv->stats.rx_packets++; struct hpsb_host *host,
priv->stats.rx_bytes += skb->len; nodeid_t node, u64 addr,
void * data, int tx_len)
{
p->node_id = node;
p->data = NULL;
bad_proto: p->tcode = TCODE_WRITEB;
spin_unlock_irqrestore (&priv->lock, flags); p->header[1] = (host->node_id << 16) | (addr >> 32);
p->header[2] = addr & 0xffffffff;
p->header_size = 16;
p->expect_response = 1;
if(hpsb_get_tlabel(p, !in_interrupt())) {
ETH1394_PRINT_G(KERN_ERR, "No more tlabels left");
return -1;
} }
p->header[0] = (p->node_id << 16) | (p->tlabel << 10)
| (1 << 8) | (TCODE_WRITEB << 4);
hpsb_iso_recv_release_packets(iso, i); p->header[3] = tx_len << 16;
p->data_size = tx_len + (tx_len % 4 ? 4 - (tx_len % 4) : 0);
p->data = (quadlet_t*)data;
netif_start_queue(dev); return 0;
}
dev->last_rx = jiffies; static inline void ether1394_prep_gasp_packet(struct hpsb_packet *p,
struct hpsb_host *host,
struct sk_buff *skb, int length)
{
p->header_size = 4;
p->tcode = TCODE_STREAM_DATA;
p->header[0] = (length << 16) | (3 << 14)
| ((host->csr.broadcast_channel & 0x3f) << 8)
| (TCODE_STREAM_DATA << 4);
p->data_size = length;
p->data = (quadlet_t*)skb_push(skb, 2 * sizeof(quadlet_t));
p->data[0] = cpu_to_be32((host->node_id << 16) |
ETHER1394_GASP_SPECIFIER_ID_HI);
p->data[1] = cpu_to_be32((ETHER1394_GASP_SPECIFIER_ID_LO << 24) |
ETHER1394_GASP_VERSION);
}
return; static inline void ether1394_free_packet(struct hpsb_packet *packet)
{
packet->data = NULL;
free_hpsb_packet(packet); packet = NULL;
}
static void ether1394_complete_cb(void *__ptask);
static int ether1394_send_packet(struct packet_task *ptask, unsigned int tx_len)
{
struct eth1394_priv *priv = ptask->priv;
struct hpsb_packet *packet;
packet = ether1394_alloc_common_packet(priv->host);
if(!packet)
return -1;
if(ptask->tx_type == ETH1394_GASP) {
int length = tx_len + (2 * sizeof(quadlet_t));
ether1394_prep_gasp_packet(packet, priv->host,
ptask->skb, length);
} else {
if(ether1394_prep_write_packet(packet, priv->host,
ptask->dest_node,
ptask->addr, ptask->skb->data,
tx_len))
goto fail;
}
ptask->packet = packet;
hpsb_set_packet_complete_task(ptask->packet, ether1394_complete_cb,
ptask);
if(hpsb_send_packet(packet)) {
return 0;
}
fail:
return -1;
} }
/* This function is our scheduled write */ /* Task function to be run when a datagram transmission is completed */
static void hpsb_write_sched (void *__ptask) static inline void ether1394_dg_complete(struct packet_task *ptask, int fail)
{ {
struct packet_task *ptask = (struct packet_task *)__ptask;
struct sk_buff *skb = ptask->skb; struct sk_buff *skb = ptask->skb;
struct net_device *dev = ptask->skb->dev; struct net_device *dev = skb->dev;
struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv; struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;
unsigned long flags; unsigned long flags;
int status;
if (ptask->tx_type == ETH1394_GASP) { /* Statistics */
status = hpsb_send_gasp(priv->host, priv->broadcast_channel, if(fail) {
get_hpsb_generation(priv->host), spin_lock_irqsave(&priv->lock, flags);
(quadlet_t *)skb->data, skb->len, priv->stats.tx_dropped++;
ETHER1394_GASP_SPECIFIER_ID, priv->stats.tx_errors++;
ETHER1394_GASP_VERSION); spin_unlock_irqrestore(&priv->lock, flags);
} else { } else {
status = hpsb_write(priv->host, ptask->dest_node, spin_lock_irqsave(&priv->lock, flags);
get_hpsb_generation(priv->host), priv->stats.tx_bytes += skb->len;
ptask->addr, (quadlet_t *)skb->data, priv->stats.tx_packets++;
skb->len); spin_unlock_irqrestore(&priv->lock, flags);
} }
dev_kfree_skb_any(skb); skb = NULL;
kmem_cache_free(packet_task_cache, ptask); ptask = NULL;
}
/* Statistics */
spin_lock_irqsave (&priv->lock, flags); /* Callback for when a packet has been sent and the status of that packet is
if (!status) { * known */
priv->stats.tx_bytes += skb->len; static void ether1394_complete_cb(void *__ptask)
priv->stats.tx_packets++; {
} else { struct packet_task *ptask = (struct packet_task *)__ptask;
//printk("Failed in hpsb_write_sched\n"); struct hpsb_packet *packet = ptask->packet;
priv->stats.tx_dropped++; int fail = 0;
priv->stats.tx_errors++;
if (netif_queue_stopped (dev)) if(packet->tcode != TCODE_STREAM_DATA) {
netif_wake_queue (dev); fail = hpsb_packet_success(packet);
hpsb_free_tlabel(packet);
} }
spin_unlock_irqrestore (&priv->lock, flags);
dev->trans_start = jiffies; ether1394_free_packet(packet); packet = ptask->packet = NULL;
dev_kfree_skb(skb);
kmem_cache_free(packet_task_cache, ptask);
return; ptask->outstanding_pkts--;
if(ptask->outstanding_pkts > 0 && !fail)
{
int tx_len;
/* Add the encapsulation header to the fragment */
tx_len = ether1394_encapsulate(ptask->skb, ptask->max_payload,
&ptask->hdr);
if(ether1394_send_packet(ptask, tx_len))
ether1394_dg_complete(ptask, 1);
} else {
ether1394_dg_complete(ptask, fail);
}
} }
/* Transmit a packet (called by kernel) */ /* Transmit a packet (called by kernel) */
static int ether1394_tx (struct sk_buff *skb, struct net_device *dev) static int ether1394_tx (struct sk_buff *skb, struct net_device *dev)
{ {
int kmflags = in_interrupt () ? GFP_ATOMIC : GFP_KERNEL; int kmflags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
struct ethhdr *eth; struct ethhdr *eth;
struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv; struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;
int proto; int proto;
unsigned long flags; unsigned long flags;
nodeid_t dest_node; nodeid_t dest_node;
u64 addr; eth1394_tx_type tx_type;
struct packet_task *ptask = NULL;
int ret = 0; int ret = 0;
unsigned int tx_len;
unsigned int max_payload;
u16 dg_size;
u16 dgl;
struct packet_task *ptask;
spin_lock_irqsave (&priv->lock, flags); ptask = kmem_cache_alloc(packet_task_cache, kmflags);
if (priv->bc_state == ETHER1394_BC_CLOSED) { if(ptask == NULL) {
ETH1394_PRINT(KERN_ERR, dev->name, ret = -ENOMEM;
"Cannot send packet, no broadcast channel available.");
ret = -EAGAIN;
goto fail; goto fail;
} }
/* First time sending? Need a broadcast channel for ARP and for spin_lock_irqsave (&priv->lock, flags);
* listening on */ if (priv->bc_state == ETHER1394_BC_CLOSED) {
if (priv->bc_state == ETHER1394_BC_CHECK) { ETH1394_PRINT(KERN_ERR, dev->name,
quadlet_t bc; "Cannot send packet, no broadcast channel available.\n");
/* Get the local copy of the broadcast channel and check its
* validity (the IRM should validate it for us) */
bc = priv->host->csr.broadcast_channel;
if ((bc & 0xc0000000) != 0xc0000000) {
/* broadcast channel not validated yet */
ETH1394_PRINT(KERN_WARNING, dev->name,
"Error BROADCAST_CHANNEL register valid "
"bit not set, can't send IP traffic\n");
hpsb_iso_shutdown(priv->iso);
priv->bc_state = ETHER1394_BC_CLOSED;
ret = -EAGAIN; ret = -EAGAIN;
spin_unlock_irqrestore (&priv->lock, flags); spin_unlock_irqrestore (&priv->lock, flags);
goto fail; goto fail;
} }
if (priv->broadcast_channel != (bc & 0x3f)) {
/* This really shouldn't be possible, but just in case
* the IEEE 1394 spec changes regarding broadcast
* channels in the future. */
hpsb_iso_shutdown(priv->iso);
priv->broadcast_channel = bc & 0x3f; if (priv->bc_state == ETHER1394_BC_CHECK) {
ETH1394_PRINT(KERN_WARNING, dev->name, if(ether1394_init_bc(dev)) {
"Changing to broadcast channel %d...\n",
priv->broadcast_channel);
priv->iso = hpsb_iso_recv_init(priv->host, 8 * 4096,
8, priv->broadcast_channel,
1, ether1394_iso);
if (priv->iso == NULL) {
ret = -EAGAIN;
goto fail;
}
}
if (hpsb_iso_recv_start(priv->iso, -1, (1 << 3), -1) < 0) {
ETH1394_PRINT(KERN_ERR, dev->name,
"Could not start async reception\n");
hpsb_iso_shutdown(priv->iso);
priv->bc_state = ETHER1394_BC_CLOSED;
ret = -EAGAIN;
spin_unlock_irqrestore (&priv->lock, flags); spin_unlock_irqrestore (&priv->lock, flags);
goto fail; goto fail;
} }
priv->bc_state = ETHER1394_BC_OPENED;
} }
spin_unlock_irqrestore (&priv->lock, flags); spin_unlock_irqrestore (&priv->lock, flags);
if ((skb = skb_share_check (skb, kmflags)) == NULL) { if ((skb = skb_share_check (skb, kmflags)) == NULL) {
...@@ -823,54 +1308,83 @@ static int ether1394_tx (struct sk_buff *skb, struct net_device *dev) ...@@ -823,54 +1308,83 @@ static int ether1394_tx (struct sk_buff *skb, struct net_device *dev)
if (proto == __constant_htons (ETH_P_ARP)) if (proto == __constant_htons (ETH_P_ARP))
ether1394_arp_to_1394arp (skb, dev); ether1394_arp_to_1394arp (skb, dev);
ptask = kmem_cache_alloc(packet_task_cache, kmflags); max_payload = 1 << (min(priv->max_rec[NODEID_TO_NODE(priv->host->node_id)],
if (ptask == NULL) { priv->max_rec[NODEID_TO_NODE(dest_node)]) + 1);
ret = -ENOMEM;
goto fail;
}
/* Now add our encapsulation header */ if(max_payload < 512)
ether1394_encapsulate (skb, dev, proto, ptask); max_payload = 512;
/* TODO: The above encapsulate function needs to recognize when a /* Set the transmission type for the packet. Right now only ARP
* packet needs to be split for a specified node. It should create * packets are sent via GASP. IP broadcast and IP multicast are not
* a list of skb's that we could then iterate over for the below * yet supported properly, they too should use GASP. */
* call to schedule our writes. */ switch(proto) {
case __constant_htons(ETH_P_ARP):
tx_type = ETH1394_GASP;
max_payload -= ETHER1394_OVERHEAD;
break;
default:
tx_type = ETH1394_WRREQ;
}
/* XXX: Right now we accept that we don't exactly follow RFC. When dg_size = skb->len;
* we do, we will send ARP requests via GASP format, and so we won't
* need this hack. */
spin_lock_irqsave (&priv->lock, flags); spin_lock_irqsave (&priv->lock, flags);
addr = (u64)priv->fifo_hi[NODEID_TO_NODE(dest_node)] << 32 | dgl = priv->dgl[NODEID_TO_NODE(dest_node)];
priv->fifo_lo[NODEID_TO_NODE(dest_node)]; if(max_payload < dg_size + hdr_type_len[ETH1394_HDR_LF_UF])
priv->dgl[NODEID_TO_NODE(dest_node)]++;
spin_unlock_irqrestore (&priv->lock, flags); spin_unlock_irqrestore (&priv->lock, flags);
if (!addr) ptask->hdr.words.word1 = 0;
addr = ETHER1394_REGION_ADDR; ptask->hdr.words.word2 = 0;
ptask->hdr.words.word3 = 0;
ptask->hdr.words.word4 = 0;
ptask->skb = skb; ptask->skb = skb;
ptask->priv = priv;
ptask->tx_type = tx_type;
if(tx_type != ETH1394_GASP) {
u64 addr;
spin_lock_irqsave(&priv->lock, flags);
addr = (u64)priv->fifo_hi[NODEID_TO_NODE(dest_node)] << 32 |
priv->fifo_lo[NODEID_TO_NODE(dest_node)];
spin_unlock_irqrestore(&priv->lock, flags);
ptask->addr = addr; ptask->addr = addr;
ptask->dest_node = dest_node; ptask->dest_node = dest_node;
/* TODO: When 2.4 is out of the way, give each of our ethernet }
* dev's a workqueue to handle these. */
INIT_WORK(&ptask->tq, hpsb_write_sched, ptask); ptask->tx_type = tx_type;
schedule_work(&ptask->tq); ptask->max_payload = max_payload;
ptask->outstanding_pkts = ether1394_encapsulate_prep(max_payload, proto,
&ptask->hdr, dg_size,
dgl);
/* Add the encapsulation header to the fragment */
tx_len = ether1394_encapsulate(skb, max_payload, &ptask->hdr);
dev->trans_start = jiffies;
if(ether1394_send_packet(ptask, tx_len))
goto fail;
netif_wake_queue(dev);
return 0; return 0;
fail: fail:
printk("Failed in ether1394_tx\n"); if(ptask->packet)
ether1394_free_packet(ptask->packet); ptask->packet = NULL;
if (skb != NULL) if(ptask)
dev_kfree_skb (skb); kmem_cache_free(packet_task_cache, ptask); ptask = NULL;
if(skb != NULL) {
dev_kfree_skb(skb); skb = NULL;
}
spin_lock_irqsave (&priv->lock, flags); spin_lock_irqsave (&priv->lock, flags);
priv->stats.tx_dropped++; priv->stats.tx_dropped++;
priv->stats.tx_errors++; priv->stats.tx_errors++;
if (netif_queue_stopped (dev))
netif_wake_queue (dev);
spin_unlock_irqrestore (&priv->lock, flags); spin_unlock_irqrestore (&priv->lock, flags);
if (netif_queue_stopped(dev))
netif_wake_queue(dev);
return 0; /* returning non-zero causes serious problems */ return 0; /* returning non-zero causes serious problems */
} }
......
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
#ifndef __ETH1394_H #ifndef __ETH1394_H
#define __ETH1394_H #define __ETH1394_H
#include "ieee1394.h"
/* Register for incoming packets. This is 8192 bytes, which supports up to /* Register for incoming packets. This is 8192 bytes, which supports up to
* 1600mbs. We'll need to change this if that ever becomes "small" :) */ * 1600mbs. We'll need to change this if that ever becomes "small" :) */
#define ETHER1394_REGION_ADDR_LEN 8192 #define ETHER1394_REGION_ADDR_LEN 8192
...@@ -32,14 +34,24 @@ ...@@ -32,14 +34,24 @@
/* GASP identifier numbers for IPv4 over IEEE 1394 */ /* GASP identifier numbers for IPv4 over IEEE 1394 */
#define ETHER1394_GASP_SPECIFIER_ID 0x00005E #define ETHER1394_GASP_SPECIFIER_ID 0x00005E
#define ETHER1394_GASP_SPECIFIER_ID_HI ((ETHER1394_GASP_SPECIFIER_ID >> 8) & 0xffff)
#define ETHER1394_GASP_SPECIFIER_ID_LO (ETHER1394_GASP_SPECIFIER_ID & 0xff)
#define ETHER1394_GASP_VERSION 1 #define ETHER1394_GASP_VERSION 1
#define ETHER1394_OVERHEAD (2 * sizeof(quadlet_t)) /* GASP header overhead */
/* Node set == 64 */ /* Node set == 64 */
#define NODE_SET (ALL_NODES + 1) #define NODE_SET (ALL_NODES + 1)
enum eth1394_bc_states { ETHER1394_BC_CLOSED, ETHER1394_BC_OPENED, enum eth1394_bc_states { ETHER1394_BC_CLOSED, ETHER1394_BC_OPENED,
ETHER1394_BC_CHECK }; ETHER1394_BC_CHECK };
struct pdg_list {
struct list_head list; /* partial datagram list per node */
unsigned int sz; /* partial datagram list size per node */
spinlock_t lock; /* partial datagram lock */
};
/* Private structure for our ethernet driver */ /* Private structure for our ethernet driver */
struct eth1394_priv { struct eth1394_priv {
struct net_device_stats stats; /* Device stats */ struct net_device_stats stats; /* Device stats */
...@@ -53,6 +65,8 @@ struct eth1394_priv { ...@@ -53,6 +65,8 @@ struct eth1394_priv {
int broadcast_channel; /* Async stream Broadcast Channel */ int broadcast_channel; /* Async stream Broadcast Channel */
enum eth1394_bc_states bc_state; /* broadcast channel state */ enum eth1394_bc_states bc_state; /* broadcast channel state */
struct hpsb_iso *iso; /* Async stream recv handle */ struct hpsb_iso *iso; /* Async stream recv handle */
struct pdg_list pdg[ALL_NODES]; /* partial RX datagram lists */
int dgl[NODE_SET]; /* Outgoing datagram label per node */
}; };
struct host_info { struct host_info {
...@@ -62,29 +76,20 @@ struct host_info { ...@@ -62,29 +76,20 @@ struct host_info {
typedef enum {ETH1394_GASP, ETH1394_WRREQ} eth1394_tx_type; typedef enum {ETH1394_GASP, ETH1394_WRREQ} eth1394_tx_type;
/* This is our task struct. It's used for the packet complete callback. */
struct packet_task {
struct sk_buff *skb; /* Socket buffer we are sending */
nodeid_t dest_node; /* Destination of the packet */
u64 addr; /* Address */
struct work_struct tq; /* The task */
eth1394_tx_type tx_type; /* Send data via GASP or Write Req. */
};
/* IP1394 headers */ /* IP1394 headers */
#include <asm/byteorder.h> #include <asm/byteorder.h>
/* Unfragmented */ /* Unfragmented */
#if defined __BIG_ENDIAN_BITFIELD #if defined __BIG_ENDIAN_BITFIELD
struct eth1394_uf_hdr { struct eth1394_uf_hdr {
u8 lf:2; u16 lf:2;
u16 res:14; u16 res:14;
u16 ether_type; /* Ethernet packet type */ u16 ether_type; /* Ethernet packet type */
} __attribute__((packed)); } __attribute__((packed));
#elif defined __LITTLE_ENDIAN_BITFIELD #elif defined __LITTLE_ENDIAN_BITFIELD
struct eth1394_uf_hdr { struct eth1394_uf_hdr {
u16 res:14; u16 res:14;
u8 lf:2; u16 lf:2;
u16 ether_type; u16 ether_type;
} __attribute__((packed)); } __attribute__((packed));
#else #else
...@@ -94,8 +99,8 @@ struct eth1394_uf_hdr { ...@@ -94,8 +99,8 @@ struct eth1394_uf_hdr {
/* First fragment */ /* First fragment */
#if defined __BIG_ENDIAN_BITFIELD #if defined __BIG_ENDIAN_BITFIELD
struct eth1394_ff_hdr { struct eth1394_ff_hdr {
u8 lf:2; u16 lf:2;
u8 res1:2; u16 res1:2;
u16 dg_size:12; /* Datagram size */ u16 dg_size:12; /* Datagram size */
u16 ether_type; /* Ethernet packet type */ u16 ether_type; /* Ethernet packet type */
u16 dgl; /* Datagram label */ u16 dgl; /* Datagram label */
...@@ -104,8 +109,8 @@ struct eth1394_ff_hdr { ...@@ -104,8 +109,8 @@ struct eth1394_ff_hdr {
#elif defined __LITTLE_ENDIAN_BITFIELD #elif defined __LITTLE_ENDIAN_BITFIELD
struct eth1394_ff_hdr { struct eth1394_ff_hdr {
u16 dg_size:12; u16 dg_size:12;
u8 res1:2; u16 res1:2;
u8 lf:2; u16 lf:2;
u16 ether_type; u16 ether_type;
u16 dgl; u16 dgl;
u16 res2; u16 res2;
...@@ -117,21 +122,21 @@ struct eth1394_ff_hdr { ...@@ -117,21 +122,21 @@ struct eth1394_ff_hdr {
/* XXX: Subsequent fragments, including last */ /* XXX: Subsequent fragments, including last */
#if defined __BIG_ENDIAN_BITFIELD #if defined __BIG_ENDIAN_BITFIELD
struct eth1394_sf_hdr { struct eth1394_sf_hdr {
u8 lf:2; u16 lf:2;
u8 res1:2; u16 res1:2;
u16 dg_size:12; /* Datagram size */ u16 dg_size:12; /* Datagram size */
u8 res2:6; u16 res2:4;
u16 fg_off:10; /* Fragment offset */ u16 fg_off:12; /* Fragment offset */
u16 dgl; /* Datagram label */ u16 dgl; /* Datagram label */
u16 res3; u16 res3;
} __attribute__((packed)); } __attribute__((packed));
#elif defined __LITTLE_ENDIAN_BITFIELD #elif defined __LITTLE_ENDIAN_BITFIELD
struct eth1394_sf_hdr { struct eth1394_sf_hdr {
u16 dg_size:12; u16 dg_size:12;
u8 res1:2; u16 res1:2;
u8 lf:2; u16 lf:2;
u16 fg_off:10; u16 fg_off:12;
u8 res2:6; u16 res2:4;
u16 dgl; u16 dgl;
u16 res3; u16 res3;
} __attribute__((packed)); } __attribute__((packed));
...@@ -141,13 +146,13 @@ struct eth1394_sf_hdr { ...@@ -141,13 +146,13 @@ struct eth1394_sf_hdr {
#if defined __BIG_ENDIAN_BITFIELD #if defined __BIG_ENDIAN_BITFIELD
struct eth1394_common_hdr { struct eth1394_common_hdr {
u8 lf:2; u16 lf:2;
u16 pad1:14; u16 pad1:14;
} __attribute__((packed)); } __attribute__((packed));
#elif defined __LITTLE_ENDIAN_BITFIELD #elif defined __LITTLE_ENDIAN_BITFIELD
struct eth1394_common_hdr { struct eth1394_common_hdr {
u16 pad1:14; u16 pad1:14;
u8 lf:2; u16 lf:2;
} __attribute__((packed)); } __attribute__((packed));
#else #else
#error Unknown bit field type #error Unknown bit field type
...@@ -199,4 +204,17 @@ struct eth1394_arp { ...@@ -199,4 +204,17 @@ struct eth1394_arp {
/* Network timeout */ /* Network timeout */
#define ETHER1394_TIMEOUT 100000 #define ETHER1394_TIMEOUT 100000
/* This is our task struct. It's used for the packet complete callback. */
struct packet_task {
struct sk_buff *skb;
int outstanding_pkts;
eth1394_tx_type tx_type;
int max_payload;
struct hpsb_packet *packet;
struct eth1394_priv *priv;
union eth1394_hdr hdr;
u64 addr;
u16 dest_node;
};
#endif /* __ETH1394_H */ #endif /* __ETH1394_H */
...@@ -80,9 +80,12 @@ static void dump_packet(const char *text, quadlet_t *data, int size) ...@@ -80,9 +80,12 @@ static void dump_packet(const char *text, quadlet_t *data, int size)
static void run_packet_complete(struct hpsb_packet *packet) static void run_packet_complete(struct hpsb_packet *packet)
{ {
if (packet->complete_routine != NULL) { if (packet->complete_routine != NULL) {
packet->complete_routine(packet->complete_data); void (*complete_routine)(void*) = packet->complete_routine;
void *complete_data = packet->complete_data;
packet->complete_routine = NULL; packet->complete_routine = NULL;
packet->complete_data = NULL; packet->complete_data = NULL;
complete_routine(complete_data);
} }
return; return;
} }
...@@ -938,7 +941,7 @@ void abort_requests(struct hpsb_host *host) ...@@ -938,7 +941,7 @@ void abort_requests(struct hpsb_host *host)
{ {
unsigned long flags; unsigned long flags;
struct hpsb_packet *packet; struct hpsb_packet *packet;
struct list_head *lh; struct list_head *lh, *tlh;
LIST_HEAD(llist); LIST_HEAD(llist);
host->driver->devctl(host, CANCEL_REQUESTS, 0); host->driver->devctl(host, CANCEL_REQUESTS, 0);
...@@ -948,8 +951,9 @@ void abort_requests(struct hpsb_host *host) ...@@ -948,8 +951,9 @@ void abort_requests(struct hpsb_host *host)
INIT_LIST_HEAD(&host->pending_packets); INIT_LIST_HEAD(&host->pending_packets);
spin_unlock_irqrestore(&host->pending_pkt_lock, flags); spin_unlock_irqrestore(&host->pending_pkt_lock, flags);
list_for_each(lh, &llist) { list_for_each_safe(lh, tlh, &llist) {
packet = list_entry(lh, struct hpsb_packet, list); packet = list_entry(lh, struct hpsb_packet, list);
list_del(&packet->list);
packet->state = hpsb_complete; packet->state = hpsb_complete;
packet->ack_code = ACKX_ABORTED; packet->ack_code = ACKX_ABORTED;
up(&packet->state_change); up(&packet->state_change);
...@@ -962,7 +966,7 @@ void abort_timedouts(struct hpsb_host *host) ...@@ -962,7 +966,7 @@ void abort_timedouts(struct hpsb_host *host)
unsigned long flags; unsigned long flags;
struct hpsb_packet *packet; struct hpsb_packet *packet;
unsigned long expire; unsigned long expire;
struct list_head *lh, *next; struct list_head *lh, *next, *tlh;
LIST_HEAD(expiredlist); LIST_HEAD(expiredlist);
spin_lock_irqsave(&host->csr.lock, flags); spin_lock_irqsave(&host->csr.lock, flags);
...@@ -990,8 +994,9 @@ void abort_timedouts(struct hpsb_host *host) ...@@ -990,8 +994,9 @@ void abort_timedouts(struct hpsb_host *host)
spin_unlock_irqrestore(&host->pending_pkt_lock, flags); spin_unlock_irqrestore(&host->pending_pkt_lock, flags);
list_for_each(lh, &expiredlist) { list_for_each_safe(lh, tlh, &expiredlist) {
packet = list_entry(lh, struct hpsb_packet, list); packet = list_entry(lh, struct hpsb_packet, list);
list_del(&packet->list);
packet->state = hpsb_complete; packet->state = hpsb_complete;
packet->ack_code = ACKX_TIMEOUT; packet->ack_code = ACKX_TIMEOUT;
up(&packet->state_change); up(&packet->state_change);
......
...@@ -147,6 +147,8 @@ int hpsb_get_tlabel(struct hpsb_packet *packet, int wait) ...@@ -147,6 +147,8 @@ int hpsb_get_tlabel(struct hpsb_packet *packet, int wait)
spin_lock_irqsave(&tp->lock, flags); spin_lock_irqsave(&tp->lock, flags);
packet->tlabel = find_next_zero_bit(tp->pool, 64, tp->next); packet->tlabel = find_next_zero_bit(tp->pool, 64, tp->next);
if(packet->tlabel > 63)
packet->tlabel = find_first_zero_bit(tp->pool, 64);
tp->next = (packet->tlabel + 1) % 64; tp->next = (packet->tlabel + 1) % 64;
/* Should _never_ happen */ /* Should _never_ happen */
BUG_ON(test_and_set_bit(packet->tlabel, tp->pool)); BUG_ON(test_and_set_bit(packet->tlabel, tp->pool));
...@@ -573,10 +575,6 @@ int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation, ...@@ -573,10 +575,6 @@ int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation,
quadlet_t *buffer, size_t length, u32 specifier_id, quadlet_t *buffer, size_t length, u32 specifier_id,
unsigned int version) unsigned int version)
{ {
#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
int i;
#endif
struct hpsb_packet *packet; struct hpsb_packet *packet;
int retval = 0; int retval = 0;
u16 specifier_id_hi = (specifier_id & 0x00ffff00) >> 8; u16 specifier_id_hi = (specifier_id & 0x00ffff00) >> 8;
...@@ -604,14 +602,6 @@ int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation, ...@@ -604,14 +602,6 @@ int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation,
memcpy(&(packet->data[2]), buffer, length - 4); memcpy(&(packet->data[2]), buffer, length - 4);
#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
HPSB_DEBUG("GASP: packet->header_size = %d", packet->header_size);
HPSB_DEBUG("GASP: packet->data_size = %d", packet->data_size);
for(i=0; i<(packet->data_size/4); i++)
HPSB_DEBUG("GASP: data[%d]: 0x%08x", i*4, be32_to_cpu(packet->data[i]));
#endif
packet->generation = generation; packet->generation = generation;
packet->no_waiter = 1; packet->no_waiter = 1;
......
...@@ -164,7 +164,7 @@ printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args) ...@@ -164,7 +164,7 @@ printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args)
printk(level "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args) printk(level "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
static char version[] __devinitdata = static char version[] __devinitdata =
"$Rev: 931 $ Ben Collins <bcollins@debian.org>"; "$Rev: 938 $ Ben Collins <bcollins@debian.org>";
/* Module Parameters */ /* Module Parameters */
static int phys_dma = 1; static int phys_dma = 1;
...@@ -3165,7 +3165,7 @@ static void ohci_init_config_rom(struct ti_ohci *ohci) ...@@ -3165,7 +3165,7 @@ static void ohci_init_config_rom(struct ti_ohci *ohci)
struct config_rom_ptr cr; struct config_rom_ptr cr;
memset(&cr, 0, sizeof(cr)); memset(&cr, 0, sizeof(cr));
memset(ohci->csr_config_rom_cpu, 0, sizeof(*ohci->csr_config_rom_cpu)); memset(ohci->csr_config_rom_cpu, 0, OHCI_CONFIG_ROM_LEN);
cr.data = ohci->csr_config_rom_cpu; cr.data = ohci->csr_config_rom_cpu;
...@@ -3530,6 +3530,16 @@ static void ohci1394_pci_remove(struct pci_dev *pdev) ...@@ -3530,6 +3530,16 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
} }
} }
#ifdef CONFIG_PM
static int ohci1394_pci_resume (struct pci_dev *dev)
{
pci_enable_device(dev);
return 0;
}
#endif
#define PCI_CLASS_FIREWIRE_OHCI ((PCI_CLASS_SERIAL_FIREWIRE << 8) | 0x10) #define PCI_CLASS_FIREWIRE_OHCI ((PCI_CLASS_SERIAL_FIREWIRE << 8) | 0x10)
static struct pci_device_id ohci1394_pci_tbl[] __devinitdata = { static struct pci_device_id ohci1394_pci_tbl[] __devinitdata = {
...@@ -3551,6 +3561,10 @@ static struct pci_driver ohci1394_pci_driver = { ...@@ -3551,6 +3561,10 @@ static struct pci_driver ohci1394_pci_driver = {
.id_table = ohci1394_pci_tbl, .id_table = ohci1394_pci_tbl,
.probe = ohci1394_pci_probe, .probe = ohci1394_pci_probe,
.remove = ohci1394_pci_remove, .remove = ohci1394_pci_remove,
#ifdef CONFIG_PM
.resume = ohci1394_pci_resume,
#endif /* PM */
}; };
......
...@@ -79,7 +79,7 @@ ...@@ -79,7 +79,7 @@
#include "sbp2.h" #include "sbp2.h"
static char version[] __devinitdata = static char version[] __devinitdata =
"$Rev: 931 $ Ben Collins <bcollins@debian.org>"; "$Rev: 938 $ Ben Collins <bcollins@debian.org>";
/* /*
* Module load parameter definitions * Module load parameter definitions
......
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