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
This diff is collapsed.
...@@ -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