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 @@
*
* Copyright (C) 2001 Ben Collins <bcollins@debian.org>
* 2000 Bonin Franck <boninf@free.fr>
* 2003 Steve Kinneberg <kinnebergsteve@acmsystems.com>
*
* Mainly based on work by Emanuel Pirker and Andreas E. Bombe
*
......@@ -21,22 +22,28 @@
* 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
* 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
* packet formats, as per the RFC for ARP requests.
* - Does not yet support fragmented packets.
* - Relies on hardware address being equal to the nodeid for some things.
* - Does not support multicast
* - Hardcoded address for sending packets, instead of using discovery
* (ARP, see first item)
* Non-RFC 2734 related:
* - Move generic GASP reception to core 1394 code
* - Convert kmalloc/kfree for link fragments to use kmem_cache_* instead
* - Stability improvements
* - Performance enhancements
* - Change hardcoded 1394 bus address region to a dynamic memory space allocation
* - Consider garbage collecting old partial datagrams after X amount of time
*/
#include <linux/module.h>
#include <linux/sched.h>
......@@ -56,7 +63,6 @@
#include <linux/tcp.h>
#include <linux/skbuff.h>
#include <linux/bitops.h>
#include <linux/workqueue.h>
#include <asm/delay.h>
#include <asm/semaphore.h>
#include <net/arp.h>
......@@ -76,10 +82,27 @@
printk(level ETHER1394_DRIVER_NAME": %s: " fmt, dev_name, ## 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 =
"$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 */
#define ETHER1394_DRIVER_NAME "ether1394"
......@@ -89,7 +112,7 @@ static kmem_cache_t *packet_task_cache;
static struct hpsb_highlevel eth1394_highlevel;
/* 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_ff_hdr),
sizeof (struct eth1394_sf_hdr),
......@@ -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_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 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" */
static int ether1394_open (struct net_device *dev)
{
struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;
unsigned long flags;
int ret;
/* Set the spinlock before grabbing IRQ! */
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);
return 0;
......@@ -140,34 +258,6 @@ static void ether1394_tx_timeout (struct net_device *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
* 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,
unsigned char sspd, u64 eui, u16 fifo_hi,
u32 fifo_lo, struct eth1394_priv *priv)
{
int i;
if (nodeid < 0 || nodeid >= ALL_NODES) {
ETH1394_PRINT_G (KERN_ERR, "Cannot register invalid nodeid %d\n", nodeid);
return;
......@@ -236,20 +324,8 @@ static inline void ether1394_register_limits (int nodeid, unsigned char max_rec,
priv->fifo_lo[nodeid] = fifo_lo;
priv->eui[nodeid] = eui;
/* 63 is used for broadcasts to all hosts. It is equal to the
* minimum of all registered nodes. A registered node is one with
* 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;
priv->max_rec[ALL_NODES] = min(priv->max_rec[ALL_NODES], max_rec);
priv->sspd[ALL_NODES] = min(priv->sspd[ALL_NODES], sspd);
return;
}
......@@ -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)
{
unsigned long flags;
int i;
struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;
int phy_id = NODEID_TO_NODE(priv->host->node_id);
struct hpsb_host *host = priv->host;
......@@ -264,7 +341,7 @@ static void ether1394_reset_priv (struct net_device *dev, int set_mtu)
spin_lock_irqsave (&priv->lock, flags);
/* 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->fifo_hi, 0, sizeof (priv->fifo_hi));
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)
/* We'll use our max_rec as the default mtu */
if (set_mtu)
dev->mtu = (1 << (priv->max_rec[phy_id] + 1)) - /* mtu = max_rec - */
(sizeof (union eth1394_hdr) + 8); /* (hdr + GASP) */
dev->mtu = (1 << (priv->max_rec[phy_id] + 1)) -
(sizeof (union eth1394_hdr) + ETHER1394_OVERHEAD);
/* Set our hardware address while we're at it */
*(nodeid_t *)dev->dev_addr = htons (host->node_id);
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 */
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)
{
int i;
struct host_info *hi = NULL;
struct net_device *dev = NULL;
struct eth1394_priv *priv;
......@@ -343,6 +433,12 @@ static void ether1394_add_host (struct hpsb_host *host)
priv->host = host;
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));
if (hi == NULL)
......@@ -360,10 +456,10 @@ static void ether1394_add_host (struct hpsb_host *host)
hi->dev = dev;
/* 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->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);
if (priv->iso == NULL) {
priv->bc_state = ETHER1394_BC_CLOSED;
......@@ -372,7 +468,7 @@ static void ether1394_add_host (struct hpsb_host *host)
out:
if (dev != NULL)
kfree (dev);
kfree (dev); dev = NULL;
if (hi)
hpsb_destroy_hostinfo(&eth1394_highlevel, host);
......@@ -393,7 +489,7 @@ static void ether1394_remove_host (struct hpsb_host *host)
unregister_netdev (hi->dev);
hpsb_iso_shutdown(priv->iso);
kfree (hi->dev);
kfree (hi->dev); hi->dev = NULL;
}
return;
......@@ -417,6 +513,11 @@ static void ether1394_host_reset (struct hpsb_host *host)
netif_wake_queue (dev);
}
/******************************************
* Datagram reception code
******************************************/
/* Copied from net/ethernet/eth.c */
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
/* Parse an encapsulated IP1394 header into an ethernet frame packet.
* We also perform ARP translation here, if need be. */
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 short ret = 0;
......@@ -462,14 +562,10 @@ static inline unsigned short ether1394_parse_encap (struct sk_buff *skb, struct
*(u16 *)dest_hw = htons(destid);
*(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
* use of some of the fields, since they tell us a little bit
* 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;
u16 phy_id = NODEID_TO_NODE(srcid);
struct eth1394_priv *priv =
......@@ -503,49 +599,318 @@ static inline unsigned short ether1394_parse_encap (struct sk_buff *skb, struct
}
/* 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)
ret = ether1394_type_trans(skb, dev);
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
* ethernet header, and fill it with some of our other fields. This is
* an incoming packet from the 1394 bus. */
static int ether1394_write (struct hpsb_host *host, int srcid, int destid,
quadlet_t *data, u64 addr, unsigned int len, u16 fl)
static int ether1394_data_handler(struct net_device *dev, int srcid, int destid,
char *buf, int len)
{
struct sk_buff *skb;
char *buf = (char *)data;
unsigned long flags;
struct host_info *hi = hpsb_get_hostinfo(&eth1394_highlevel, host);
struct net_device *dev;
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) {
ETH1394_PRINT_G (KERN_ERR, "Could not find net device for host %p\n",
host);
return RCODE_ADDRESS_ERROR;
}
priv = (struct eth1394_priv *)dev->priv;
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
* around it so we can pass it to the high level network layer. */
if(hdr->common.lf == ETH1394_HDR_LF_UF) {
/* 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) {
HPSB_PRINT (KERN_ERR, "ether1394 rx: low on mem\n");
priv->stats.rx_dropped++;
return RCODE_ADDRESS_ERROR;
return -1;
}
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 */
skb->dev = dev;
......@@ -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
* conversion if needed. ARP conversion is easier in this
* 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_dropped++;
dev_kfree_skb_any(skb);
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_dropped++;
goto bad_proto;
......@@ -577,20 +943,36 @@ static int ether1394_write (struct hpsb_host *host, int srcid, int destid,
priv->stats.rx_bytes += skb->len;
bad_proto:
netif_start_queue(dev);
spin_unlock_irqrestore (&priv->lock, flags);
if(netif_queue_stopped(dev))
netif_wake_queue(dev);
spin_unlock_irqrestore(&priv->lock, flags);
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;
}
static void ether1394_iso(struct hpsb_iso *iso)
{
struct sk_buff *skb;
quadlet_t *data;
char *buf;
unsigned long flags;
struct host_info *hi = hpsb_get_hostinfo(&eth1394_highlevel, iso->host);
struct net_device *dev;
struct eth1394_priv *priv;
......@@ -600,8 +982,8 @@ static void ether1394_iso(struct hpsb_iso *iso)
int i;
int nready;
if (hi == NULL) {
ETH1394_PRINT_G (KERN_ERR, "Could not find net device for host %s\n",
if(hi == NULL) {
ETH1394_PRINT_G(KERN_ERR, "Could not find net device for host %s\n",
iso->host->driver->name);
return;
}
......@@ -623,186 +1005,289 @@ static void ether1394_iso(struct hpsb_iso *iso)
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) {
/* This packet is not for us */
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
* around it so we can pass it to the high level network layer. */
skb = dev_alloc_skb (len + dev->hard_header_len + 15);
if (!skb) {
HPSB_PRINT (KERN_ERR, "ether1394 rx: low on mem\n");
priv->stats.rx_dropped++;
break;
hpsb_iso_recv_release_packets(iso, i);
dev->last_rx = jiffies;
}
/******************************************
* 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 */
skb->dev = dev;
skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */
case ETH1394_HDR_LF_FF:
bufhdr = (union eth1394_hdr *)skb_push(skb, hdrsz);
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
* converting to an ethernet frame header, aswell as arp
* conversion if needed. ARP conversion is easier in this
* direction, since we are using ethernet as our backend. */
skb->protocol = ether1394_parse_encap (skb, dev, source_id,
LOCAL_BUS | ALL_NODES);
/* Set frag type here for future interior fragments */
hdr->common.lf = ETH1394_HDR_LF_IF;
hdr->sf.fg_off = 0;
break;
spin_lock_irqsave (&priv->lock, flags);
if (!skb->protocol) {
priv->stats.rx_errors++;
priv->stats.rx_dropped++;
dev_kfree_skb_any(skb);
goto bad_proto;
default:
hdr->sf.fg_off += adj_max_payload;
bufhdr = (union eth1394_hdr *)skb_pull(skb, adj_max_payload);
if(max_payload >= skb->len)
hdr->common.lf = ETH1394_HDR_LF_LF;
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);
if (netif_rx (skb) == NET_RX_DROP) {
priv->stats.rx_errors++;
priv->stats.rx_dropped++;
goto bad_proto;
return min(max_payload, skb->len);
}
static inline struct hpsb_packet *ether1394_alloc_common_packet(struct hpsb_host *host)
{
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 */
priv->stats.rx_packets++;
priv->stats.rx_bytes += skb->len;
static inline int ether1394_prep_write_packet(struct hpsb_packet *p,
struct hpsb_host *host,
nodeid_t node, u64 addr,
void * data, int tx_len)
{
p->node_id = node;
p->data = NULL;
bad_proto:
spin_unlock_irqrestore (&priv->lock, flags);
p->tcode = TCODE_WRITEB;
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 */
static void hpsb_write_sched (void *__ptask)
/* Task function to be run when a datagram transmission is completed */
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 net_device *dev = ptask->skb->dev;
struct net_device *dev = skb->dev;
struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;
unsigned long flags;
int status;
if (ptask->tx_type == ETH1394_GASP) {
status = hpsb_send_gasp(priv->host, priv->broadcast_channel,
get_hpsb_generation(priv->host),
(quadlet_t *)skb->data, skb->len,
ETHER1394_GASP_SPECIFIER_ID,
ETHER1394_GASP_VERSION);
/* Statistics */
if(fail) {
spin_lock_irqsave(&priv->lock, flags);
priv->stats.tx_dropped++;
priv->stats.tx_errors++;
spin_unlock_irqrestore(&priv->lock, flags);
} else {
status = hpsb_write(priv->host, ptask->dest_node,
get_hpsb_generation(priv->host),
ptask->addr, (quadlet_t *)skb->data,
skb->len);
spin_lock_irqsave(&priv->lock, flags);
priv->stats.tx_bytes += skb->len;
priv->stats.tx_packets++;
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);
if (!status) {
priv->stats.tx_bytes += skb->len;
priv->stats.tx_packets++;
} else {
//printk("Failed in hpsb_write_sched\n");
priv->stats.tx_dropped++;
priv->stats.tx_errors++;
if (netif_queue_stopped (dev))
netif_wake_queue (dev);
/* Callback for when a packet has been sent and the status of that packet is
* known */
static void ether1394_complete_cb(void *__ptask)
{
struct packet_task *ptask = (struct packet_task *)__ptask;
struct hpsb_packet *packet = ptask->packet;
int fail = 0;
if(packet->tcode != TCODE_STREAM_DATA) {
fail = hpsb_packet_success(packet);
hpsb_free_tlabel(packet);
}
spin_unlock_irqrestore (&priv->lock, flags);
dev->trans_start = jiffies;
dev_kfree_skb(skb);
kmem_cache_free(packet_task_cache, ptask);
ether1394_free_packet(packet); packet = ptask->packet = NULL;
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) */
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 eth1394_priv *priv = (struct eth1394_priv *)dev->priv;
int proto;
unsigned long flags;
nodeid_t dest_node;
u64 addr;
struct packet_task *ptask = NULL;
eth1394_tx_type tx_type;
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);
if (priv->bc_state == ETHER1394_BC_CLOSED) {
ETH1394_PRINT(KERN_ERR, dev->name,
"Cannot send packet, no broadcast channel available.");
ret = -EAGAIN;
ptask = kmem_cache_alloc(packet_task_cache, kmflags);
if(ptask == NULL) {
ret = -ENOMEM;
goto fail;
}
/* 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");
hpsb_iso_shutdown(priv->iso);
priv->bc_state = ETHER1394_BC_CLOSED;
spin_lock_irqsave (&priv->lock, flags);
if (priv->bc_state == ETHER1394_BC_CLOSED) {
ETH1394_PRINT(KERN_ERR, dev->name,
"Cannot send packet, no broadcast channel available.\n");
ret = -EAGAIN;
spin_unlock_irqrestore (&priv->lock, flags);
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;
ETH1394_PRINT(KERN_WARNING, dev->name,
"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;
if (priv->bc_state == ETHER1394_BC_CHECK) {
if(ether1394_init_bc(dev)) {
spin_unlock_irqrestore (&priv->lock, flags);
goto fail;
}
priv->bc_state = ETHER1394_BC_OPENED;
}
spin_unlock_irqrestore (&priv->lock, flags);
if ((skb = skb_share_check (skb, kmflags)) == NULL) {
......@@ -823,54 +1308,83 @@ static int ether1394_tx (struct sk_buff *skb, struct net_device *dev)
if (proto == __constant_htons (ETH_P_ARP))
ether1394_arp_to_1394arp (skb, dev);
ptask = kmem_cache_alloc(packet_task_cache, kmflags);
if (ptask == NULL) {
ret = -ENOMEM;
goto fail;
}
max_payload = 1 << (min(priv->max_rec[NODEID_TO_NODE(priv->host->node_id)],
priv->max_rec[NODEID_TO_NODE(dest_node)]) + 1);
/* Now add our encapsulation header */
ether1394_encapsulate (skb, dev, proto, ptask);
if(max_payload < 512)
max_payload = 512;
/* TODO: The above encapsulate function needs to recognize when a
* packet needs to be split for a specified node. It should create
* a list of skb's that we could then iterate over for the below
* call to schedule our writes. */
/* 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):
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
* we do, we will send ARP requests via GASP format, and so we won't
* need this hack. */
dg_size = skb->len;
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)];
dgl = priv->dgl[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);
if (!addr)
addr = ETHER1394_REGION_ADDR;
ptask->hdr.words.word1 = 0;
ptask->hdr.words.word2 = 0;
ptask->hdr.words.word3 = 0;
ptask->hdr.words.word4 = 0;
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->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);
schedule_work(&ptask->tq);
}
ptask->tx_type = tx_type;
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;
fail:
printk("Failed in ether1394_tx\n");
if (skb != NULL)
dev_kfree_skb (skb);
if(ptask->packet)
ether1394_free_packet(ptask->packet); ptask->packet = NULL;
if(ptask)
kmem_cache_free(packet_task_cache, ptask); ptask = NULL;
if(skb != NULL) {
dev_kfree_skb(skb); skb = NULL;
}
spin_lock_irqsave (&priv->lock, flags);
priv->stats.tx_dropped++;
priv->stats.tx_errors++;
if (netif_queue_stopped (dev))
netif_wake_queue (dev);
spin_unlock_irqrestore (&priv->lock, flags);
if (netif_queue_stopped(dev))
netif_wake_queue(dev);
return 0; /* returning non-zero causes serious problems */
}
......
......@@ -24,6 +24,8 @@
#ifndef __ETH1394_H
#define __ETH1394_H
#include "ieee1394.h"
/* Register for incoming packets. This is 8192 bytes, which supports up to
* 1600mbs. We'll need to change this if that ever becomes "small" :) */
#define ETHER1394_REGION_ADDR_LEN 8192
......@@ -32,14 +34,24 @@
/* GASP identifier numbers for IPv4 over IEEE 1394 */
#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_OVERHEAD (2 * sizeof(quadlet_t)) /* GASP header overhead */
/* Node set == 64 */
#define NODE_SET (ALL_NODES + 1)
enum eth1394_bc_states { ETHER1394_BC_CLOSED, ETHER1394_BC_OPENED,
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 */
struct eth1394_priv {
struct net_device_stats stats; /* Device stats */
......@@ -53,6 +65,8 @@ struct eth1394_priv {
int broadcast_channel; /* Async stream Broadcast Channel */
enum eth1394_bc_states bc_state; /* broadcast channel state */
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 {
......@@ -62,29 +76,20 @@ struct host_info {
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 */
#include <asm/byteorder.h>
/* Unfragmented */
#if defined __BIG_ENDIAN_BITFIELD
struct eth1394_uf_hdr {
u8 lf:2;
u16 lf:2;
u16 res:14;
u16 ether_type; /* Ethernet packet type */
} __attribute__((packed));
#elif defined __LITTLE_ENDIAN_BITFIELD
struct eth1394_uf_hdr {
u16 res:14;
u8 lf:2;
u16 lf:2;
u16 ether_type;
} __attribute__((packed));
#else
......@@ -94,8 +99,8 @@ struct eth1394_uf_hdr {
/* First fragment */
#if defined __BIG_ENDIAN_BITFIELD
struct eth1394_ff_hdr {
u8 lf:2;
u8 res1:2;
u16 lf:2;
u16 res1:2;
u16 dg_size:12; /* Datagram size */
u16 ether_type; /* Ethernet packet type */
u16 dgl; /* Datagram label */
......@@ -104,8 +109,8 @@ struct eth1394_ff_hdr {
#elif defined __LITTLE_ENDIAN_BITFIELD
struct eth1394_ff_hdr {
u16 dg_size:12;
u8 res1:2;
u8 lf:2;
u16 res1:2;
u16 lf:2;
u16 ether_type;
u16 dgl;
u16 res2;
......@@ -117,21 +122,21 @@ struct eth1394_ff_hdr {
/* XXX: Subsequent fragments, including last */
#if defined __BIG_ENDIAN_BITFIELD
struct eth1394_sf_hdr {
u8 lf:2;
u8 res1:2;
u16 lf:2;
u16 res1:2;
u16 dg_size:12; /* Datagram size */
u8 res2:6;
u16 fg_off:10; /* Fragment offset */
u16 res2:4;
u16 fg_off:12; /* Fragment offset */
u16 dgl; /* Datagram label */
u16 res3;
} __attribute__((packed));
#elif defined __LITTLE_ENDIAN_BITFIELD
struct eth1394_sf_hdr {
u16 dg_size:12;
u8 res1:2;
u8 lf:2;
u16 fg_off:10;
u8 res2:6;
u16 res1:2;
u16 lf:2;
u16 fg_off:12;
u16 res2:4;
u16 dgl;
u16 res3;
} __attribute__((packed));
......@@ -141,13 +146,13 @@ struct eth1394_sf_hdr {
#if defined __BIG_ENDIAN_BITFIELD
struct eth1394_common_hdr {
u8 lf:2;
u16 lf:2;
u16 pad1:14;
} __attribute__((packed));
#elif defined __LITTLE_ENDIAN_BITFIELD
struct eth1394_common_hdr {
u16 pad1:14;
u8 lf:2;
u16 lf:2;
} __attribute__((packed));
#else
#error Unknown bit field type
......@@ -199,4 +204,17 @@ struct eth1394_arp {
/* Network timeout */
#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 */
......@@ -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)
{
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_data = NULL;
complete_routine(complete_data);
}
return;
}
......@@ -938,7 +941,7 @@ void abort_requests(struct hpsb_host *host)
{
unsigned long flags;
struct hpsb_packet *packet;
struct list_head *lh;
struct list_head *lh, *tlh;
LIST_HEAD(llist);
host->driver->devctl(host, CANCEL_REQUESTS, 0);
......@@ -948,8 +951,9 @@ void abort_requests(struct hpsb_host *host)
INIT_LIST_HEAD(&host->pending_packets);
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);
list_del(&packet->list);
packet->state = hpsb_complete;
packet->ack_code = ACKX_ABORTED;
up(&packet->state_change);
......@@ -962,7 +966,7 @@ void abort_timedouts(struct hpsb_host *host)
unsigned long flags;
struct hpsb_packet *packet;
unsigned long expire;
struct list_head *lh, *next;
struct list_head *lh, *next, *tlh;
LIST_HEAD(expiredlist);
spin_lock_irqsave(&host->csr.lock, flags);
......@@ -990,8 +994,9 @@ void abort_timedouts(struct hpsb_host *host)
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);
list_del(&packet->list);
packet->state = hpsb_complete;
packet->ack_code = ACKX_TIMEOUT;
up(&packet->state_change);
......
......@@ -147,6 +147,8 @@ int hpsb_get_tlabel(struct hpsb_packet *packet, int wait)
spin_lock_irqsave(&tp->lock, flags);
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;
/* Should _never_ happen */
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,
quadlet_t *buffer, size_t length, u32 specifier_id,
unsigned int version)
{
#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
int i;
#endif
struct hpsb_packet *packet;
int retval = 0;
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,
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->no_waiter = 1;
......
......@@ -164,7 +164,7 @@ printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args)
printk(level "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
static char version[] __devinitdata =
"$Rev: 931 $ Ben Collins <bcollins@debian.org>";
"$Rev: 938 $ Ben Collins <bcollins@debian.org>";
/* Module Parameters */
static int phys_dma = 1;
......@@ -3165,7 +3165,7 @@ static void ohci_init_config_rom(struct ti_ohci *ohci)
struct config_rom_ptr 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;
......@@ -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)
static struct pci_device_id ohci1394_pci_tbl[] __devinitdata = {
......@@ -3551,6 +3561,10 @@ static struct pci_driver ohci1394_pci_driver = {
.id_table = ohci1394_pci_tbl,
.probe = ohci1394_pci_probe,
.remove = ohci1394_pci_remove,
#ifdef CONFIG_PM
.resume = ohci1394_pci_resume,
#endif /* PM */
};
......
......@@ -79,7 +79,7 @@
#include "sbp2.h"
static char version[] __devinitdata =
"$Rev: 931 $ Ben Collins <bcollins@debian.org>";
"$Rev: 938 $ Ben Collins <bcollins@debian.org>";
/*
* 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