Commit db3e9f28 authored by Paul Mackerras's avatar Paul Mackerras

Merge samba.org:/home/paulus/kernel/linux-2.5

into samba.org:/home/paulus/kernel/for-linus-ppc
parents 5d999784 9683c74d
...@@ -16,6 +16,9 @@ CONFIG_SYSVIPC=y ...@@ -16,6 +16,9 @@ CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y CONFIG_SYSCTL=y
CONFIG_LOG_BUF_SHIFT=15 CONFIG_LOG_BUF_SHIFT=15
# CONFIG_EMBEDDED is not set
CONFIG_FUTEX=y
CONFIG_EPOLL=y
# #
# Loadable module support # Loadable module support
...@@ -795,6 +798,7 @@ CONFIG_IRDA_FAST_RR=y ...@@ -795,6 +798,7 @@ CONFIG_IRDA_FAST_RR=y
# CONFIG_WINBOND_FIR is not set # CONFIG_WINBOND_FIR is not set
# CONFIG_TOSHIBA_OLD is not set # CONFIG_TOSHIBA_OLD is not set
# CONFIG_TOSHIBA_FIR is not set # CONFIG_TOSHIBA_FIR is not set
# CONFIG_SMC_IRCC_OLD is not set
# CONFIG_SMC_IRCC_FIR is not set # CONFIG_SMC_IRCC_FIR is not set
# CONFIG_ALI_FIR is not set # CONFIG_ALI_FIR is not set
# CONFIG_VLSI_FIR is not set # CONFIG_VLSI_FIR is not set
...@@ -959,6 +963,8 @@ CONFIG_VFAT_FS=m ...@@ -959,6 +963,8 @@ CONFIG_VFAT_FS=m
CONFIG_PROC_FS=y CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set # CONFIG_DEVFS_FS is not set
CONFIG_DEVPTS_FS=y CONFIG_DEVPTS_FS=y
CONFIG_DEVPTS_FS_XATTR=y
# CONFIG_DEVPTS_FS_SECURITY is not set
# CONFIG_TMPFS is not set # CONFIG_TMPFS is not set
CONFIG_RAMFS=y CONFIG_RAMFS=y
...@@ -1111,6 +1117,7 @@ CONFIG_SND_ICE1712=m ...@@ -1111,6 +1117,7 @@ CONFIG_SND_ICE1712=m
CONFIG_SND_INTEL8X0=m CONFIG_SND_INTEL8X0=m
CONFIG_SND_SONICVIBES=m CONFIG_SND_SONICVIBES=m
# CONFIG_SND_VIA82XX is not set # CONFIG_SND_VIA82XX is not set
CONFIG_SND_VX222=m
# #
# ALSA USB devices # ALSA USB devices
......
...@@ -29,12 +29,11 @@ ...@@ -29,12 +29,11 @@
* *
* TODO: * TODO:
* RFC 2734 related: * RFC 2734 related:
* - Add support for broadcast messages
* - Use EUI instead of node id in internal ARP tables
* - Add Config ROM entry * - Add Config ROM entry
* - Add MCAP and multicast * - Add MCAP and multicast
* *
* Non-RFC 2734 related: * Non-RFC 2734 related:
* - Fix bug related to fragmented broadcast datagrams
* - Move generic GASP reception to core 1394 code * - Move generic GASP reception to core 1394 code
* - Convert kmalloc/kfree for link fragments to use kmem_cache_* instead * - Convert kmalloc/kfree for link fragments to use kmem_cache_* instead
* - Stability improvements * - Stability improvements
...@@ -73,6 +72,7 @@ ...@@ -73,6 +72,7 @@
#include "ieee1394.h" #include "ieee1394.h"
#include "highlevel.h" #include "highlevel.h"
#include "iso.h" #include "iso.h"
#include "nodemgr.h"
#include "eth1394.h" #include "eth1394.h"
#define ETH1394_PRINT_G(level, fmt, args...) \ #define ETH1394_PRINT_G(level, fmt, args...) \
...@@ -86,7 +86,7 @@ ...@@ -86,7 +86,7 @@
#define TRACE() printk(KERN_ERR "eth1394:%s[%d] ---- TRACE\n", __FUNCTION__, __LINE__) #define TRACE() printk(KERN_ERR "eth1394:%s[%d] ---- TRACE\n", __FUNCTION__, __LINE__)
static char version[] __devinitdata = static char version[] __devinitdata =
"$Rev: 938 $ Ben Collins <bcollins@debian.org>"; "$Rev: 945 $ Ben Collins <bcollins@debian.org>";
struct fragment_info { struct fragment_info {
struct list_head list; struct list_head list;
...@@ -119,22 +119,39 @@ static const int hdr_type_len[] = { ...@@ -119,22 +119,39 @@ static const int hdr_type_len[] = {
sizeof (struct eth1394_sf_hdr) sizeof (struct eth1394_sf_hdr)
}; };
static const u16 eth1394_speedto_maxpayload[] = {
/* S100, S200, S400, S800, S1600, S3200 */
512, 1024, 2048, 4096, 8192, 16384
};
MODULE_AUTHOR("Ben Collins (bcollins@debian.org)"); 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 /* The max_partial_datagrams parameter is the maximum number of fragmented
* per node that eth1394 will keep in memory. Providing an upper bound allows us to * datagrams per node that eth1394 will keep in memory. Providing an upper
* limit the amount of memory that partial datagrams consume in the event that some * bound allows us to limit the amount of memory that partial datagrams
* partial datagrams are never completed. This should probably change to a sysctl * consume in the event that some partial datagrams are never completed. This
* item or the like if possible. * should probably change to a sysctl item or the like if possible.
*/ */
MODULE_PARM(max_partial_datagrams, "i"); MODULE_PARM(max_partial_datagrams, "i");
MODULE_PARM_DESC(max_partial_datagrams, MODULE_PARM_DESC(max_partial_datagrams,
"Maximum number of partially received fragmented datagrams (default = 25)."); "Maximum number of partially received fragmented datagrams "
"(default = 25).");
static int max_partial_datagrams = 25; static int max_partial_datagrams = 25;
static int ether1394_header(struct sk_buff *skb, struct net_device *dev,
unsigned short type, void *daddr, void *saddr,
unsigned len);
static int ether1394_rebuild_header(struct sk_buff *skb);
static int ether1394_header_parse(struct sk_buff *skb, unsigned char *haddr);
static int ether1394_header_cache(struct neighbour *neigh, struct hh_cache *hh);
static void ether1394_header_cache_update(struct hh_cache *hh,
struct net_device *dev,
unsigned char * haddr);
static int ether1394_mac_addr(struct net_device *dev, void *p);
static inline void purge_partial_datagram(struct list_head *old); static inline void purge_partial_datagram(struct list_head *old);
static int ether1394_tx(struct sk_buff *skb, struct net_device *dev); 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);
...@@ -258,73 +275,34 @@ static void ether1394_tx_timeout (struct net_device *dev) ...@@ -258,73 +275,34 @@ static void ether1394_tx_timeout (struct net_device *dev)
netif_wake_queue (dev); netif_wake_queue (dev);
} }
/* 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
* overlap. The rest needs to be munged a bit. The remainder of the
* arphdr is formatted based on hwaddr len and ipaddr len. We know what
* they'll be, so it's easy to judge. */
static inline void ether1394_arp_to_1394arp (struct sk_buff *skb, struct net_device *dev)
{
struct eth1394_priv *priv =
(struct eth1394_priv *)(dev->priv);
u16 phy_id = NODEID_TO_NODE(priv->host->node_id);
unsigned char *arp_ptr = (unsigned char *)skb->data;
struct eth1394_arp *arp1394 = (struct eth1394_arp *)skb->data;
unsigned char arp_data[2*(dev->addr_len+4)];
/* Copy the main data that we need */
memcpy (arp_data, arp_ptr + sizeof(struct arphdr), sizeof (arp_data));
/* Extend the buffer enough for our new header */
skb_put (skb, sizeof (struct eth1394_arp) -
(sizeof (arp_data) + sizeof (struct arphdr)));
#define PROCESS_MEMBER(ptr,val,len) \
memcpy (val, ptr, len); ptr += len
arp_ptr = arp_data + arp1394->hw_addr_len;
PROCESS_MEMBER (arp_ptr, &arp1394->sip, arp1394->ip_addr_len);
arp_ptr += arp1394->hw_addr_len;
PROCESS_MEMBER (arp_ptr, &arp1394->tip, arp1394->ip_addr_len);
#undef PROCESS_MEMBER
/* Now add our own flavor of arp header fields to the orig one */
arp1394->hw_addr_len = IP1394_HW_ADDR_LEN;
arp1394->hw_type = __constant_htons (ARPHRD_IEEE1394);
arp1394->s_uniq_id = cpu_to_le64 (priv->eui[phy_id]);
arp1394->max_rec = priv->max_rec[phy_id];
arp1394->sspd = priv->sspd[phy_id];
arp1394->fifo_hi = htons (priv->fifo_hi[phy_id]);
arp1394->fifo_lo = htonl (priv->fifo_lo[phy_id]);
return;
}
static int ether1394_change_mtu(struct net_device *dev, int new_mtu) static int ether1394_change_mtu(struct net_device *dev, int new_mtu)
{ {
if ((new_mtu < 68) || (new_mtu > ETHER1394_REGION_ADDR_LEN)) struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;
int phy_id = NODEID_TO_NODE(priv->host->node_id);
if ((new_mtu < 68) || (new_mtu > (priv->maxpayload[phy_id] -
(sizeof(union eth1394_hdr) +
ETHER1394_GASP_OVERHEAD))))
return -EINVAL; return -EINVAL;
dev->mtu = new_mtu; dev->mtu = new_mtu;
return 0; return 0;
} }
static inline void ether1394_register_limits (int nodeid, unsigned char max_rec, static inline void ether1394_register_limits(int nodeid, u16 maxpayload,
unsigned char sspd, u64 eui, u16 fifo_hi, unsigned char sspd, u64 eui, u64 fifo,
u32 fifo_lo, struct eth1394_priv *priv) struct eth1394_priv *priv)
{ {
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;
} }
priv->max_rec[nodeid] = max_rec; priv->maxpayload[nodeid] = maxpayload;
priv->sspd[nodeid] = sspd; priv->sspd[nodeid] = sspd;
priv->fifo_hi[nodeid] = fifo_hi; priv->fifo[nodeid] = fifo;
priv->fifo_lo[nodeid] = fifo_lo;
priv->eui[nodeid] = eui; priv->eui[nodeid] = eui;
priv->max_rec[ALL_NODES] = min(priv->max_rec[ALL_NODES], max_rec); priv->maxpayload[ALL_NODES] = min(priv->maxpayload[ALL_NODES], maxpayload);
priv->sspd[ALL_NODES] = min(priv->sspd[ALL_NODES], sspd); priv->sspd[ALL_NODES] = min(priv->sspd[ALL_NODES], sspd);
return; return;
...@@ -335,34 +313,44 @@ static void ether1394_reset_priv (struct net_device *dev, int set_mtu) ...@@ -335,34 +313,44 @@ static void ether1394_reset_priv (struct net_device *dev, int set_mtu)
unsigned long flags; unsigned long flags;
int i; 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);
struct hpsb_host *host = priv->host; struct hpsb_host *host = priv->host;
int phy_id = NODEID_TO_NODE(host->node_id);
u64 guid = *((u64*)&(host->csr.rom[3]));
u16 maxpayload = 1 << (((be32_to_cpu(host->csr.rom[2]) >> 12) & 0xf) + 1);
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, 8, sizeof (priv->max_rec)); memset (priv->maxpayload, 0, sizeof (priv->maxpayload));
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, 0, sizeof (priv->fifo));
memset (priv->fifo_lo, 0, sizeof (priv->fifo_lo));
#if 0
/* Compile this out to make testing of fragmented broadcast datagrams
* easier. */
priv->sspd[ALL_NODES] = SPEED_MAX;
priv->maxpayload[ALL_NODES] = eth1394_speedto_maxpayload[SPEED_MAX];
#else
priv->sspd[ALL_NODES] = SPEED_100;
priv->maxpayload[ALL_NODES] = eth1394_speedto_maxpayload[SPEED_100];
#endif
priv->bc_state = ETHER1394_BC_CHECK; priv->bc_state = ETHER1394_BC_CHECK;
/* Register our limits now */ /* Register our limits now */
ether1394_register_limits (phy_id, (be32_to_cpu(host->csr.rom[2]) >> 12) & 0xf, ether1394_register_limits(phy_id, maxpayload,
host->speed_map[(phy_id << 6) + phy_id], host->speed_map[(phy_id << 6) + phy_id],
(u64)(((u64)be32_to_cpu(host->csr.rom[3]) << 32) | guid, ETHER1394_REGION_ADDR, priv);
be32_to_cpu(host->csr.rom[4])),
ETHER1394_REGION_ADDR >> 32,
ETHER1394_REGION_ADDR & 0xffffffff, priv);
/* We'll use our max_rec as the default mtu */ /* We'll use our maxpayload as the default mtu */
if (set_mtu) if (set_mtu) {
dev->mtu = (1 << (priv->max_rec[phy_id] + 1)) - dev->mtu = priv->maxpayload[phy_id] - (sizeof(union eth1394_hdr) +
(sizeof (union eth1394_hdr) + ETHER1394_OVERHEAD); ETHER1394_GASP_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); *(u64*)dev->dev_addr = guid;
*(u64*)dev->broadcast = ~0x0ULL;
}
spin_unlock_irqrestore (&priv->lock, flags); spin_unlock_irqrestore (&priv->lock, flags);
...@@ -392,11 +380,20 @@ static int ether1394_init_dev (struct net_device *dev) ...@@ -392,11 +380,20 @@ static int ether1394_init_dev (struct net_device *dev)
dev->tx_timeout = ether1394_tx_timeout; dev->tx_timeout = ether1394_tx_timeout;
dev->change_mtu = ether1394_change_mtu; dev->change_mtu = ether1394_change_mtu;
dev->hard_header = ether1394_header;
dev->rebuild_header = ether1394_rebuild_header;
dev->hard_header_cache = ether1394_header_cache;
dev->header_cache_update= ether1394_header_cache_update;
dev->hard_header_parse = ether1394_header_parse;
dev->set_mac_address = ether1394_mac_addr;
/* Some constants */ /* Some constants */
dev->watchdog_timeo = ETHER1394_TIMEOUT; dev->watchdog_timeo = ETHER1394_TIMEOUT;
dev->flags = IFF_BROADCAST; /* TODO: Support MCAP */ dev->flags = IFF_BROADCAST; /* | IFF_MULTICAST someday */
dev->features = NETIF_F_NO_CSUM|NETIF_F_SG|NETIF_F_HIGHDMA|NETIF_F_FRAGLIST; dev->features = NETIF_F_NO_CSUM|NETIF_F_SG|NETIF_F_HIGHDMA|NETIF_F_FRAGLIST;
dev->addr_len = 2; dev->addr_len = ETH1394_ALEN;
dev->hard_header_len = ETH1394_HLEN;
dev->type = ARPHRD_IEEE1394;
ether1394_reset_priv (dev, 1); ether1394_reset_priv (dev, 1);
...@@ -419,6 +416,9 @@ static void ether1394_add_host (struct hpsb_host *host) ...@@ -419,6 +416,9 @@ static void ether1394_add_host (struct hpsb_host *host)
if (version_printed++ == 0) if (version_printed++ == 0)
ETH1394_PRINT_G (KERN_INFO, "%s\n", version); ETH1394_PRINT_G (KERN_INFO, "%s\n", version);
/* We should really have our own alloc_hpsbdev() function in
* net_init.c instead of calling the one for ethernet then hijacking
* it for ourselves. That way we'd be a real networking device. */
dev = alloc_etherdev(sizeof (struct eth1394_priv)); dev = alloc_etherdev(sizeof (struct eth1394_priv));
if (dev == NULL) if (dev == NULL)
...@@ -468,7 +468,7 @@ static void ether1394_add_host (struct hpsb_host *host) ...@@ -468,7 +468,7 @@ static void ether1394_add_host (struct hpsb_host *host)
out: out:
if (dev != NULL) if (dev != NULL)
kfree (dev); dev = NULL; kfree(dev);
if (hi) if (hi)
hpsb_destroy_hostinfo(&eth1394_highlevel, host); hpsb_destroy_hostinfo(&eth1394_highlevel, host);
...@@ -489,7 +489,7 @@ static void ether1394_remove_host (struct hpsb_host *host) ...@@ -489,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); hi->dev = NULL; kfree(hi->dev);
} }
return; return;
...@@ -513,31 +513,140 @@ static void ether1394_host_reset (struct hpsb_host *host) ...@@ -513,31 +513,140 @@ static void ether1394_host_reset (struct hpsb_host *host)
netif_wake_queue (dev); netif_wake_queue (dev);
} }
/******************************************
* HW Header net device functions
******************************************/
/* These functions have been adapted from net/ethernet/eth.c */
/* Create a fake MAC header for an arbitrary protocol layer.
* saddr=NULL means use device source address
* daddr=NULL means leave destination address (eg unresolved arp). */
static int ether1394_header(struct sk_buff *skb, struct net_device *dev,
unsigned short type, void *daddr, void *saddr,
unsigned len)
{
struct eth1394hdr *eth = (struct eth1394hdr *)skb_push(skb, ETH1394_HLEN);
eth->h_proto = htons(type);
if (dev->flags & (IFF_LOOPBACK|IFF_NOARP))
{
memset(eth->h_dest, 0, dev->addr_len);
return(dev->hard_header_len);
}
if(daddr)
{
memcpy(eth->h_dest,daddr,dev->addr_len);
return dev->hard_header_len;
}
return -dev->hard_header_len;
}
/* Rebuild the faked MAC header. This is called after an ARP
* (or in future other address resolution) has completed on this
* sk_buff. We now let ARP fill in the other fields.
*
* This routine CANNOT use cached dst->neigh!
* Really, it is used only when dst->neigh is wrong.
*/
static int ether1394_rebuild_header(struct sk_buff *skb)
{
struct eth1394hdr *eth = (struct eth1394hdr *)skb->data;
struct net_device *dev = skb->dev;
switch (eth->h_proto)
{
#ifdef CONFIG_INET
case __constant_htons(ETH_P_IP):
return arp_find((unsigned char*)&eth->h_dest, skb);
#endif
default:
printk(KERN_DEBUG
"%s: unable to resolve type %X addresses.\n",
dev->name, (int)eth->h_proto);
break;
}
return 0;
}
static int ether1394_header_parse(struct sk_buff *skb, unsigned char *haddr)
{
struct net_device *dev = skb->dev;
memcpy(haddr, dev->dev_addr, ETH1394_ALEN);
return ETH_ALEN;
}
static int ether1394_header_cache(struct neighbour *neigh, struct hh_cache *hh)
{
unsigned short type = hh->hh_type;
struct eth1394hdr *eth = (struct eth1394hdr*)(((u8*)hh->hh_data) + 6);
struct net_device *dev = neigh->dev;
if (type == __constant_htons(ETH_P_802_3)) {
return -1;
}
eth->h_proto = type;
memcpy(eth->h_dest, neigh->ha, dev->addr_len);
hh->hh_len = ETH1394_HLEN;
return 0;
}
/* Called by Address Resolution module to notify changes in address. */
static void ether1394_header_cache_update(struct hh_cache *hh,
struct net_device *dev,
unsigned char * haddr)
{
memcpy(((u8*)hh->hh_data) + 6, haddr, dev->addr_len);
}
static int ether1394_mac_addr(struct net_device *dev, void *p)
{
if (netif_running(dev))
return -EBUSY;
/* Not going to allow setting the MAC address, we really need to use
* the real one suppliled by the hardware */
return -EINVAL;
}
/****************************************** /******************************************
* Datagram reception code * 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 u16 ether1394_type_trans(struct sk_buff *skb,
struct net_device *dev)
{ {
struct ethhdr *eth; struct eth1394hdr *eth;
unsigned char *rawp; unsigned char *rawp;
skb->mac.raw = skb->data; skb->mac.raw = skb->data;
skb_pull (skb, ETH_HLEN); skb_pull (skb, ETH1394_HLEN);
eth = skb->mac.ethernet; eth = (struct eth1394hdr*)skb->mac.raw;
#if 0
if(*eth->h_dest & 1) { if(*eth->h_dest & 1) {
if(memcmp(eth->h_dest, dev->broadcast, dev->addr_len)==0) if(memcmp(eth->h_dest, dev->broadcast, dev->addr_len)==0)
skb->pkt_type = PACKET_BROADCAST; skb->pkt_type = PACKET_BROADCAST;
#if 0
else else
skb->pkt_type = PACKET_MULTICAST; skb->pkt_type = PACKET_MULTICAST;
#endif
} else { } else {
if(memcmp(eth->h_dest, dev->dev_addr, dev->addr_len)) if(memcmp(eth->h_dest, dev->dev_addr, dev->addr_len))
skb->pkt_type = PACKET_OTHERHOST; skb->pkt_type = PACKET_OTHERHOST;
} }
#endif
if (ntohs (eth->h_proto) >= 1536) if (ntohs (eth->h_proto) >= 1536)
return eth->h_proto; return eth->h_proto;
...@@ -551,56 +660,72 @@ static inline unsigned short ether1394_type_trans(struct sk_buff *skb, struct ne ...@@ -551,56 +660,72 @@ 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 u16 ether1394_parse_encap(struct sk_buff *skb,
nodeid_t srcid, nodeid_t destid, u16 ether_type) struct net_device *dev,
nodeid_t srcid, nodeid_t destid,
u16 ether_type)
{ {
unsigned char src_hw[ETH_ALEN], dest_hw[ETH_ALEN]; struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;
u64 dest_hw;
unsigned short ret = 0; unsigned short ret = 0;
/* Setup our hw addresses. We use these to build the /* Setup our hw addresses. We use these to build the
* ethernet header. */ * ethernet header. */
*(u16 *)dest_hw = htons(destid); if(destid == (LOCAL_BUS | ALL_NODES))
*(u16 *)src_hw = htons(srcid); dest_hw = ~0ULL; /* broadcast */
else
dest_hw = priv->eui[NODEID_TO_NODE(destid)];
/* 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 (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); struct eth1394_arp *arp1394 = (struct eth1394_arp*)skb->data;
struct eth1394_priv *priv =
(struct eth1394_priv *)dev->priv;
struct eth1394_arp arp1394;
struct arphdr *arp = (struct arphdr *)skb->data; struct arphdr *arp = (struct arphdr *)skb->data;
unsigned char *arp_ptr = (unsigned char *)(arp + 1); unsigned char *arp_ptr = (unsigned char *)(arp + 1);
u64 fifo_addr = (u64)ntohs(arp1394->fifo_hi) << 32 |
ntohl(arp1394->fifo_lo);
u8 host_max_rec = (be32_to_cpu(priv->host->csr.rom[2]) >>
12) & 0xf;
u8 max_rec = min(host_max_rec, (u8)(arp1394->max_rec));
u16 maxpayload = min(eth1394_speedto_maxpayload[arp1394->sspd],
(u16)(1 << (max_rec + 1)));
memcpy (&arp1394, arp, sizeof (struct eth1394_arp));
/* Update our speed/payload/fifo_offset table */ /* Update our speed/payload/fifo_offset table */
spin_lock_irqsave (&priv->lock, flags); spin_lock_irqsave (&priv->lock, flags);
ether1394_register_limits (phy_id, arp1394.max_rec, arp1394.sspd, ether1394_register_limits(NODEID_TO_NODE(srcid), maxpayload,
le64_to_cpu (arp1394.s_uniq_id), arp1394->sspd, arp1394->s_uniq_id,
ntohs (arp1394.fifo_hi), fifo_addr, priv);
ntohl (arp1394.fifo_lo), priv);
spin_unlock_irqrestore (&priv->lock, flags); spin_unlock_irqrestore (&priv->lock, flags);
#define PROCESS_MEMBER(ptr,val,len) \ /* Now that we're done with the 1394 specific stuff, we'll
memcpy (ptr, val, len); ptr += len * need to alter some of the data. Believe it or not, all
PROCESS_MEMBER (arp_ptr, src_hw, dev->addr_len); * that needs to be done is sender_IP_address needs to be
PROCESS_MEMBER (arp_ptr, &arp1394.sip, 4); * moved, the destination hardware address get stuffed
PROCESS_MEMBER (arp_ptr, dest_hw, dev->addr_len); * in and the hardware address length set to 8.
PROCESS_MEMBER (arp_ptr, &arp1394.tip, 4); *
#undef PROCESS_MEMBER * IMPORTANT: The code below overwrites 1394 specific data
* needed above data so keep the call to
arp->ar_hln = dev->addr_len; * ether1394_register_limits() before munging the data for the
arp->ar_hrd = __constant_htons (ARPHRD_ETHER); * higher level IP stack. */
skb_trim (skb, sizeof (struct arphdr) + 2*(dev->addr_len+4)); arp->ar_hln = 8;
arp_ptr += arp->ar_hln; /* skip over sender unique id */
*(u32*)arp_ptr = arp1394->sip; /* move sender IP addr */
arp_ptr += arp->ar_pln; /* skip over sender IP addr */
if(arp->ar_op == 1)
/* just set ARP req target unique ID to 0 */
memset(arp_ptr, 0, ETH1394_ALEN);
else
memcpy(arp_ptr, dev->dev_addr, ETH1394_ALEN);
} }
/* Now add the ethernet header. */ /* Now add the ethernet header. */
if (dev->hard_header (skb, dev, __constant_ntohs (ether_type), if (dev->hard_header (skb, dev, __constant_ntohs (ether_type),
dest_hw, src_hw, skb->len) >= 0) &dest_hw, NULL, skb->len) >= 0)
ret = ether1394_type_trans(skb, dev); ret = ether1394_type_trans(skb, dev);
return ret; return ret;
...@@ -651,7 +776,7 @@ static inline int new_fragment(struct list_head *frag_info, int offset, int len) ...@@ -651,7 +776,7 @@ static inline int new_fragment(struct list_head *frag_info, int offset, int len)
/* glue fragments together */ /* glue fragments together */
fi->len += fi2->len; fi->len += fi2->len;
list_del(lh->next); list_del(lh->next);
kfree(fi2); fi2 = NULL; kfree(fi2);
} }
return 0; return 0;
} else if((offset + len) == fi->offset) { } else if((offset + len) == fi->offset) {
...@@ -664,7 +789,7 @@ static inline int new_fragment(struct list_head *frag_info, int offset, int len) ...@@ -664,7 +789,7 @@ static inline int new_fragment(struct list_head *frag_info, int offset, int len)
/* glue fragments together */ /* glue fragments together */
fi2->len += fi->len; fi2->len += fi->len;
list_del(lh); list_del(lh);
kfree(fi); fi = NULL; kfree(fi);
} }
return 0; return 0;
} else if(offset > (fi->offset + fi->len)) { } else if(offset > (fi->offset + fi->len)) {
...@@ -701,7 +826,7 @@ static inline int new_partial_datagram(struct net_device *dev, ...@@ -701,7 +826,7 @@ static inline int new_partial_datagram(struct net_device *dev,
INIT_LIST_HEAD(&new->frag_info); INIT_LIST_HEAD(&new->frag_info);
if(new_fragment(&new->frag_info, frag_off, frag_len) < 0) { if(new_fragment(&new->frag_info, frag_off, frag_len) < 0) {
kfree(new); new = NULL; kfree(new);
return -ENOMEM; return -ENOMEM;
} }
...@@ -713,8 +838,8 @@ static inline int new_partial_datagram(struct net_device *dev, ...@@ -713,8 +838,8 @@ static inline int new_partial_datagram(struct net_device *dev,
struct fragment_info *fi = list_entry(new->frag_info.next, struct fragment_info *fi = list_entry(new->frag_info.next,
struct fragment_info, struct fragment_info,
list); list);
kfree(fi); fi = NULL; kfree(fi);
kfree(new); new = NULL; kfree(new);
return -ENOMEM; return -ENOMEM;
} }
...@@ -754,11 +879,11 @@ static inline void purge_partial_datagram(struct list_head *old) ...@@ -754,11 +879,11 @@ static inline void purge_partial_datagram(struct list_head *old)
list_for_each_safe(lh, n, &pd->frag_info) { list_for_each_safe(lh, n, &pd->frag_info) {
struct fragment_info *fi = list_entry(lh, struct fragment_info, list); struct fragment_info *fi = list_entry(lh, struct fragment_info, list);
list_del(lh); list_del(lh);
kfree(fi); fi = NULL; kfree(fi);
} }
list_del(old); list_del(old);
kfree_skb(pd->skb); pd->skb = NULL; kfree_skb(pd->skb);
kfree(pd); pd = NULL; kfree(pd);
} }
static inline int is_datagram_complete(struct list_head *lh, int dg_size) static inline int is_datagram_complete(struct list_head *lh, int dg_size)
...@@ -805,11 +930,6 @@ static int ether1394_data_handler(struct net_device *dev, int srcid, int destid, ...@@ -805,11 +930,6 @@ static int ether1394_data_handler(struct net_device *dev, int srcid, int destid,
memcpy(skb_put(skb, len - hdr_len), buf + hdr_len, len - hdr_len); memcpy(skb_put(skb, len - hdr_len), buf + hdr_len, len - hdr_len);
ether_type = hdr->uf.ether_type; ether_type = hdr->uf.ether_type;
} else { } else {
#if 0
return 0;
}
if(0) {
#endif
/* A datagram fragment has been received, now the fun begins. */ /* A datagram fragment has been received, now the fun begins. */
struct list_head *pdgl, *lh; struct list_head *pdgl, *lh;
...@@ -836,7 +956,6 @@ static int ether1394_data_handler(struct net_device *dev, int srcid, int destid, ...@@ -836,7 +956,6 @@ static int ether1394_data_handler(struct net_device *dev, int srcid, int destid,
dg_size = hdr->sf.dg_size; dg_size = hdr->sf.dg_size;
fg_off = hdr->sf.fg_off; fg_off = hdr->sf.fg_off;
} }
spin_lock_irqsave(&pdg->lock, flags); spin_lock_irqsave(&pdg->lock, flags);
pdgl = &(pdg->list); pdgl = &(pdg->list);
...@@ -1010,7 +1129,8 @@ static void ether1394_iso(struct hpsb_iso *iso) ...@@ -1010,7 +1129,8 @@ static void ether1394_iso(struct hpsb_iso *iso)
/* 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); ether1394_data_handler(dev, source_id, LOCAL_BUS | ALL_NODES,
buf, len);
} }
hpsb_iso_recv_release_packets(iso, i); hpsb_iso_recv_release_packets(iso, i);
...@@ -1022,6 +1142,39 @@ static void ether1394_iso(struct hpsb_iso *iso) ...@@ -1022,6 +1142,39 @@ static void ether1394_iso(struct hpsb_iso *iso)
* Datagram transmission code * Datagram transmission code
******************************************/ ******************************************/
/* 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 overlap. The rest
* needs to be munged a bit. The remainder of the arphdr is formatted based
* on hwaddr len and ipaddr len. We know what they'll be, so it's easy to
* judge.
*
* Now that the EUI is used for the hardware address all we need to do to make
* this work for 1394 is to insert 2 quadlets that contain max_rec size,
* speed, and unicast FIFO address information between the sender_unique_id
* and the IP addresses.
*/
static inline void ether1394_arp_to_1394arp(struct sk_buff *skb,
struct net_device *dev)
{
struct eth1394_priv *priv = (struct eth1394_priv *)(dev->priv);
u16 phy_id = NODEID_TO_NODE(priv->host->node_id);
struct arphdr *arp = (struct arphdr *)skb->data;
unsigned char *arp_ptr = (unsigned char *)(arp + 1);
struct eth1394_arp *arp1394 = (struct eth1394_arp *)skb->data;
/* Believe it or not, all that need to happen is sender IP get moved
* and set hw_addr_len, max_rec, sspd, fifo_hi and fifo_lo. */
arp1394->hw_addr_len = 16;
arp1394->sip = *(u32*)(arp_ptr + ETH1394_ALEN);
arp1394->max_rec = (be32_to_cpu(priv->host->csr.rom[2]) >> 12) & 0xf;
arp1394->sspd = priv->sspd[phy_id];
arp1394->fifo_hi = htons (priv->fifo[phy_id] >> 32);
arp1394->fifo_lo = htonl (priv->fifo[phy_id] & ~0x0);
return;
}
/* We need to encapsulate the standard header with our own. We use the /* We need to encapsulate the standard header with our own. We use the
* ethernet header's proto for our own. */ * ethernet header's proto for our own. */
static inline unsigned int ether1394_encapsulate_prep(unsigned int max_payload, static inline unsigned int ether1394_encapsulate_prep(unsigned int max_payload,
...@@ -1042,7 +1195,6 @@ static inline unsigned int ether1394_encapsulate_prep(unsigned int max_payload, ...@@ -1042,7 +1195,6 @@ static inline unsigned int ether1394_encapsulate_prep(unsigned int max_payload,
hdr->ff.dgl = dgl; hdr->ff.dgl = dgl;
adj_max_payload = max_payload - hdr_type_len[ETH1394_HDR_LF_FF]; adj_max_payload = max_payload - hdr_type_len[ETH1394_HDR_LF_FF];
} }
return((dg_size + (adj_max_payload - 1)) / adj_max_payload); return((dg_size + (adj_max_payload - 1)) / adj_max_payload);
} }
...@@ -1132,27 +1284,33 @@ static inline int ether1394_prep_write_packet(struct hpsb_packet *p, ...@@ -1132,27 +1284,33 @@ static inline int ether1394_prep_write_packet(struct hpsb_packet *p,
} }
static inline void ether1394_prep_gasp_packet(struct hpsb_packet *p, static inline void ether1394_prep_gasp_packet(struct hpsb_packet *p,
struct hpsb_host *host, struct eth1394_priv *priv,
struct sk_buff *skb, int length) struct sk_buff *skb, int length)
{ {
p->header_size = 4; p->header_size = 4;
p->tcode = TCODE_STREAM_DATA; p->tcode = TCODE_STREAM_DATA;
p->header[0] = (length << 16) | (3 << 14) p->header[0] = (length << 16) | (3 << 14)
| ((host->csr.broadcast_channel & 0x3f) << 8) | ((priv->broadcast_channel) << 8)
| (TCODE_STREAM_DATA << 4); | (TCODE_STREAM_DATA << 4);
p->data_size = length; p->data_size = length;
p->data = (quadlet_t*)skb_push(skb, 2 * sizeof(quadlet_t)); p->data = ((quadlet_t*)skb->data) - 2;
p->data[0] = cpu_to_be32((host->node_id << 16) | p->data[0] = cpu_to_be32((priv->host->node_id << 16) |
ETHER1394_GASP_SPECIFIER_ID_HI); ETHER1394_GASP_SPECIFIER_ID_HI);
p->data[1] = cpu_to_be32((ETHER1394_GASP_SPECIFIER_ID_LO << 24) | p->data[1] = cpu_to_be32((ETHER1394_GASP_SPECIFIER_ID_LO << 24) |
ETHER1394_GASP_VERSION); ETHER1394_GASP_VERSION);
/* Setting the node id to ALL_NODES (not LOCAL_BUS | ALL_NODES)
* prevents hpsb_send_packet() from setting the speed to an arbitrary
* value based on packet->node_id if packet->node_id is not set. */
p->node_id = ALL_NODES;
p->speed_code = priv->sspd[ALL_NODES];
} }
static inline void ether1394_free_packet(struct hpsb_packet *packet) static inline void ether1394_free_packet(struct hpsb_packet *packet)
{ {
packet->data = NULL; packet->data = NULL;
free_hpsb_packet(packet); packet = NULL; free_hpsb_packet(packet);
} }
static void ether1394_complete_cb(void *__ptask); static void ether1394_complete_cb(void *__ptask);
...@@ -1168,8 +1326,7 @@ static int ether1394_send_packet(struct packet_task *ptask, unsigned int tx_len) ...@@ -1168,8 +1326,7 @@ static int ether1394_send_packet(struct packet_task *ptask, unsigned int tx_len)
if(ptask->tx_type == ETH1394_GASP) { if(ptask->tx_type == ETH1394_GASP) {
int length = tx_len + (2 * sizeof(quadlet_t)); int length = tx_len + (2 * sizeof(quadlet_t));
ether1394_prep_gasp_packet(packet, priv->host, ether1394_prep_gasp_packet(packet, priv, ptask->skb, length);
ptask->skb, length);
} else { } else {
if(ether1394_prep_write_packet(packet, priv->host, if(ether1394_prep_write_packet(packet, priv->host,
...@@ -1212,8 +1369,8 @@ static inline void ether1394_dg_complete(struct packet_task *ptask, int fail) ...@@ -1212,8 +1369,8 @@ static inline void ether1394_dg_complete(struct packet_task *ptask, int fail)
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
} }
dev_kfree_skb_any(skb); skb = NULL; dev_kfree_skb_any(skb);
kmem_cache_free(packet_task_cache, ptask); ptask = NULL; kmem_cache_free(packet_task_cache, ptask);
} }
...@@ -1230,7 +1387,7 @@ static void ether1394_complete_cb(void *__ptask) ...@@ -1230,7 +1387,7 @@ static void ether1394_complete_cb(void *__ptask)
hpsb_free_tlabel(packet); hpsb_free_tlabel(packet);
} }
ether1394_free_packet(packet); packet = ptask->packet = NULL; ether1394_free_packet(packet);
ptask->outstanding_pkts--; ptask->outstanding_pkts--;
if(ptask->outstanding_pkts > 0 && !fail) if(ptask->outstanding_pkts > 0 && !fail)
...@@ -1253,7 +1410,7 @@ static void ether1394_complete_cb(void *__ptask) ...@@ -1253,7 +1410,7 @@ static void ether1394_complete_cb(void *__ptask)
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 eth1394hdr *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;
...@@ -1265,6 +1422,7 @@ static int ether1394_tx (struct sk_buff *skb, struct net_device *dev) ...@@ -1265,6 +1422,7 @@ static int ether1394_tx (struct sk_buff *skb, struct net_device *dev)
u16 dg_size; u16 dg_size;
u16 dgl; u16 dgl;
struct packet_task *ptask; struct packet_task *ptask;
struct node_entry *ne;
ptask = kmem_cache_alloc(packet_task_cache, kmflags); ptask = kmem_cache_alloc(packet_task_cache, kmflags);
if(ptask == NULL) { if(ptask == NULL) {
...@@ -1295,34 +1453,44 @@ static int ether1394_tx (struct sk_buff *skb, struct net_device *dev) ...@@ -1295,34 +1453,44 @@ static int ether1394_tx (struct sk_buff *skb, struct net_device *dev)
goto fail; goto fail;
} }
/* Get rid of the ethernet header, but save a pointer */ /* Get rid of the fake eth1394 header, but save a pointer */
eth = (struct ethhdr *)skb->data; eth = (struct eth1394hdr*)skb->data;
skb_pull (skb, ETH_HLEN); skb_pull(skb, ETH1394_HLEN);
ne = hpsb_guid_get_entry(be64_to_cpu(*(u64*)eth->h_dest));
if(!ne)
dest_node = LOCAL_BUS | ALL_NODES;
else
dest_node = ne->nodeid;
/* Save the destination id, and proto for our encapsulation, then
* toss the ethernet header aside like the cheap whore it is. */
dest_node = ntohs (*(nodeid_t *)(eth->h_dest));
proto = eth->h_proto; proto = eth->h_proto;
/* If this is an ARP packet, convert it */ /* If this is an ARP packet, convert it */
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);
max_payload = 1 << (min(priv->max_rec[NODEID_TO_NODE(priv->host->node_id)], max_payload = priv->maxpayload[NODEID_TO_NODE(dest_node)];
priv->max_rec[NODEID_TO_NODE(dest_node)]) + 1);
if(max_payload < 512) /* This check should be unnecessary, but we'll keep it for safety for
* a while longer. */
if(max_payload < 512) {
ETH1394_PRINT(KERN_WARNING, dev->name,
"max_payload too small: %d (setting to 512)\n",
max_payload);
max_payload = 512; max_payload = 512;
}
/* Set the transmission type for the packet. Right now only ARP /* Set the transmission type for the packet. ARP packets and IP
* packets are sent via GASP. IP broadcast and IP multicast are not * broadcast packets are sent via GASP, however, we cheat a little bit
* yet supported properly, they too should use GASP. */ * when detecting IP broadcast packets. This will need to change when
switch(proto) { * we switch from using node id for the hardware address to the EUI
case __constant_htons(ETH_P_ARP): * which we should be using instead. IP multicast is not yet
* supported. */
if((memcmp(eth->h_dest, dev->broadcast, ETH1394_ALEN) == 0) ||
(proto == __constant_htons(ETH_P_ARP))) {
tx_type = ETH1394_GASP; tx_type = ETH1394_GASP;
max_payload -= ETHER1394_OVERHEAD; max_payload -= ETHER1394_GASP_OVERHEAD;
break; } else {
default:
tx_type = ETH1394_WRREQ; tx_type = ETH1394_WRREQ;
} }
...@@ -1345,9 +1513,17 @@ static int ether1394_tx (struct sk_buff *skb, struct net_device *dev) ...@@ -1345,9 +1513,17 @@ static int ether1394_tx (struct sk_buff *skb, struct net_device *dev)
if(tx_type != ETH1394_GASP) { if(tx_type != ETH1394_GASP) {
u64 addr; u64 addr;
/* This test is just temporary until ConfigROM support has
* been added to eth1394. Until then, we need an ARP packet
* after a bus reset from the current destination node so that
* we can get FIFO information. */
if(priv->fifo[NODEID_TO_NODE(dest_node)] == 0ULL) {
ret = -EAGAIN;
goto fail;
}
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
addr = (u64)priv->fifo_hi[NODEID_TO_NODE(dest_node)] << 32 | addr = priv->fifo[NODEID_TO_NODE(dest_node)];
priv->fifo_lo[NODEID_TO_NODE(dest_node)];
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
ptask->addr = addr; ptask->addr = addr;
...@@ -1370,11 +1546,11 @@ static int ether1394_tx (struct sk_buff *skb, struct net_device *dev) ...@@ -1370,11 +1546,11 @@ static int ether1394_tx (struct sk_buff *skb, struct net_device *dev)
return 0; return 0;
fail: fail:
if(ptask->packet) if(ptask->packet)
ether1394_free_packet(ptask->packet); ptask->packet = NULL; ether1394_free_packet(ptask->packet);
if(ptask) if(ptask)
kmem_cache_free(packet_task_cache, ptask); ptask = NULL; kmem_cache_free(packet_task_cache, ptask);
if(skb != NULL) { if(skb != NULL) {
dev_kfree_skb(skb); skb = NULL; dev_kfree_skb(skb);
} }
spin_lock_irqsave (&priv->lock, flags); spin_lock_irqsave (&priv->lock, flags);
......
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
#define ETHER1394_GASP_SPECIFIER_ID_LO (ETHER1394_GASP_SPECIFIER_ID & 0xff) #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 */ #define ETHER1394_GASP_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)
...@@ -56,10 +56,9 @@ struct pdg_list { ...@@ -56,10 +56,9 @@ struct pdg_list {
struct eth1394_priv { struct eth1394_priv {
struct net_device_stats stats; /* Device stats */ struct net_device_stats stats; /* Device stats */
struct hpsb_host *host; /* The card for this dev */ struct hpsb_host *host; /* The card for this dev */
unsigned char max_rec[NODE_SET];/* Max payload per node */ u16 maxpayload[NODE_SET]; /* Max payload per node */
unsigned char sspd[NODE_SET]; /* Max speed per node */ unsigned char sspd[NODE_SET]; /* Max speed per node */
u16 fifo_hi[ALL_NODES]; /* 16bit hi fifo offset per node */ u64 fifo[ALL_NODES]; /* FIFO offset per node */
u32 fifo_lo[ALL_NODES]; /* 32bit lo fifo offset per node */
u64 eui[ALL_NODES]; /* EUI-64 per node */ u64 eui[ALL_NODES]; /* EUI-64 per node */
spinlock_t lock; /* Private lock */ spinlock_t lock; /* Private lock */
int broadcast_channel; /* Async stream Broadcast Channel */ int broadcast_channel; /* Async stream Broadcast Channel */
...@@ -74,6 +73,21 @@ struct host_info { ...@@ -74,6 +73,21 @@ struct host_info {
struct net_device *dev; struct net_device *dev;
}; };
/* Define a fake hardware header format for the networking core. Note that
* header size cannot exceed 16 bytes as that is the size of the header cache.
* Also, we do not need the source address in the header so we omit it and
* keep the header to under 16 bytes */
#define ETH1394_ALEN (8)
#define ETH1394_HLEN (10)
struct eth1394hdr {
unsigned char h_dest[ETH1394_ALEN]; /* destination eth1394 addr */
unsigned short h_proto; /* packet type ID field */
} __attribute__((packed));
typedef enum {ETH1394_GASP, ETH1394_WRREQ} eth1394_tx_type; typedef enum {ETH1394_GASP, ETH1394_WRREQ} eth1394_tx_type;
/* IP1394 headers */ /* IP1394 headers */
......
...@@ -57,7 +57,6 @@ ...@@ -57,7 +57,6 @@
/* Maps speed values above to a string representation */ /* Maps speed values above to a string representation */
extern const char *hpsb_speedto_str[]; extern const char *hpsb_speedto_str[];
extern const u8 hpsb_speedto_maxrec[];
#define SELFID_PWRCL_NO_POWER 0x0 #define SELFID_PWRCL_NO_POWER 0x0
......
...@@ -61,7 +61,6 @@ static kmem_cache_t *hpsb_packet_cache; ...@@ -61,7 +61,6 @@ static kmem_cache_t *hpsb_packet_cache;
/* Some globals used */ /* Some globals used */
const char *hpsb_speedto_str[] = { "S100", "S200", "S400", "S800", "S1600", "S3200" }; const char *hpsb_speedto_str[] = { "S100", "S200", "S400", "S800", "S1600", "S3200" };
const u8 hpsb_speedto_maxrec[] = { 0x7, 0x8, 0x9, 0x10, 0x11, 0x12 };
static void dump_packet(const char *text, quadlet_t *data, int size) static void dump_packet(const char *text, quadlet_t *data, int size)
{ {
...@@ -1246,7 +1245,6 @@ EXPORT_SYMBOL(hpsb_unref_host); ...@@ -1246,7 +1245,6 @@ EXPORT_SYMBOL(hpsb_unref_host);
/** ieee1394_core.c **/ /** ieee1394_core.c **/
EXPORT_SYMBOL(hpsb_speedto_str); EXPORT_SYMBOL(hpsb_speedto_str);
EXPORT_SYMBOL(hpsb_speedto_maxrec);
EXPORT_SYMBOL(hpsb_set_packet_complete_task); EXPORT_SYMBOL(hpsb_set_packet_complete_task);
EXPORT_SYMBOL(alloc_hpsb_packet); EXPORT_SYMBOL(alloc_hpsb_packet);
EXPORT_SYMBOL(free_hpsb_packet); EXPORT_SYMBOL(free_hpsb_packet);
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
*/ */
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/sched.h>
#include "iso.h" #include "iso.h"
void hpsb_iso_stop(struct hpsb_iso *iso) void hpsb_iso_stop(struct hpsb_iso *iso)
......
...@@ -79,7 +79,7 @@ ...@@ -79,7 +79,7 @@
#include "sbp2.h" #include "sbp2.h"
static char version[] __devinitdata = static char version[] __devinitdata =
"$Rev: 938 $ Ben Collins <bcollins@debian.org>"; "$Rev: 942 $ Ben Collins <bcollins@debian.org>";
/* /*
* Module load parameter definitions * Module load parameter definitions
...@@ -230,6 +230,8 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id, ...@@ -230,6 +230,8 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
static Scsi_Host_Template scsi_driver_template; static Scsi_Host_Template scsi_driver_template;
const u8 sbp2_speedto_max_payload[] = { 0x7, 0x8, 0x9, 0xA, 0xB, 0xC };
static struct hpsb_highlevel sbp2_highlevel = { static struct hpsb_highlevel sbp2_highlevel = {
.name = SBP2_DEVICE_NAME, .name = SBP2_DEVICE_NAME,
.remove_host = sbp2_remove_host, .remove_host = sbp2_remove_host,
...@@ -779,7 +781,7 @@ static int sbp2_start_ud(struct sbp2scsi_host_info *hi, struct unit_directory *u ...@@ -779,7 +781,7 @@ static int sbp2_start_ud(struct sbp2scsi_host_info *hi, struct unit_directory *u
scsi_id->ne = ud->ne; scsi_id->ne = ud->ne;
scsi_id->hi = hi; scsi_id->hi = hi;
scsi_id->speed_code = SPEED_100; scsi_id->speed_code = SPEED_100;
scsi_id->max_payload_size = hpsb_speedto_maxrec[SPEED_100]; scsi_id->max_payload_size = sbp2_speedto_max_payload[SPEED_100];
atomic_set(&scsi_id->sbp2_login_complete, 0); atomic_set(&scsi_id->sbp2_login_complete, 0);
INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_inuse); INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_inuse);
INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed); INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed);
...@@ -1690,7 +1692,7 @@ static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id) ...@@ -1690,7 +1692,7 @@ static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id)
/* Payload size is the lesser of what our speed supports and what /* Payload size is the lesser of what our speed supports and what
* our host supports. */ * our host supports. */
scsi_id->max_payload_size = min(hpsb_speedto_maxrec[scsi_id->speed_code], scsi_id->max_payload_size = min(sbp2_speedto_max_payload[scsi_id->speed_code],
(u8)(((be32_to_cpu(hi->host->csr.rom[2]) >> 12) & 0xf) - 1)); (u8)(((be32_to_cpu(hi->host->csr.rom[2]) >> 12) & 0xf) - 1));
SBP2_ERR("Node[" NODE_BUS_FMT "]: Max speed [%s] - Max payload [%u]", SBP2_ERR("Node[" NODE_BUS_FMT "]: Max speed [%s] - Max payload [%u]",
......
...@@ -150,6 +150,14 @@ struct eventpoll { ...@@ -150,6 +150,14 @@ struct eventpoll {
/* Protect the this structure access */ /* Protect the this structure access */
rwlock_t lock; rwlock_t lock;
/*
* This semaphore is used to ensure that files are not removed
* while epoll is using them. This is read-held during the event
* collection loop and it is write-held during the file cleanup
* path, the epoll file exit code and the ctl operations.
*/
struct rw_semaphore sem;
/* Wait queue used by sys_epoll_wait() */ /* Wait queue used by sys_epoll_wait() */
wait_queue_head_t wq; wait_queue_head_t wq;
...@@ -279,16 +287,6 @@ static struct super_block *eventpollfs_get_sb(struct file_system_type *fs_type, ...@@ -279,16 +287,6 @@ static struct super_block *eventpollfs_get_sb(struct file_system_type *fs_type,
/* Safe wake up implementation */ /* Safe wake up implementation */
static struct poll_safewake psw; static struct poll_safewake psw;
/*
* This semaphore is used to ensure that files are not removed
* while epoll is using them. Namely the f_op->poll(), since
* it has to be called from outside the lock, must be protected.
* This is read-held during the event transfer loop to userspace
* and it is write-held during the file cleanup path and the epoll
* file exit code.
*/
static struct rw_semaphore epsem;
/* Slab cache used to allocate "struct epitem" */ /* Slab cache used to allocate "struct epitem" */
static kmem_cache_t *epi_cache; static kmem_cache_t *epi_cache;
...@@ -357,8 +355,8 @@ static void ep_poll_safewake(struct poll_safewake *psw, wait_queue_head_t *wq) ...@@ -357,8 +355,8 @@ static void ep_poll_safewake(struct poll_safewake *psw, wait_queue_head_t *wq)
list_for_each(lnk, lsthead) { list_for_each(lnk, lsthead) {
tncur = list_entry(lnk, struct wake_task_node, llink); tncur = list_entry(lnk, struct wake_task_node, llink);
if (tncur->task == this_task) { if (tncur->wq == wq ||
if (tncur->wq == wq || ++wake_nests > EP_MAX_POLLWAKE_NESTS) { (tncur->task == this_task && ++wake_nests > EP_MAX_POLLWAKE_NESTS)) {
/* /*
* Ops ... loop detected or maximum nest level reached. * Ops ... loop detected or maximum nest level reached.
* We abort this wake by breaking the cycle itself. * We abort this wake by breaking the cycle itself.
...@@ -367,7 +365,6 @@ static void ep_poll_safewake(struct poll_safewake *psw, wait_queue_head_t *wq) ...@@ -367,7 +365,6 @@ static void ep_poll_safewake(struct poll_safewake *psw, wait_queue_head_t *wq)
return; return;
} }
} }
}
/* Add the current task to the list */ /* Add the current task to the list */
tnode.task = this_task; tnode.task = this_task;
...@@ -437,14 +434,15 @@ void eventpoll_release(struct file *file) ...@@ -437,14 +434,15 @@ void eventpoll_release(struct file *file)
* The only hit might come from ep_free() but by holding the semaphore * The only hit might come from ep_free() but by holding the semaphore
* will correctly serialize the operation. * will correctly serialize the operation.
*/ */
down_write(&epsem);
while (!list_empty(lsthead)) { while (!list_empty(lsthead)) {
epi = list_entry(lsthead->next, struct epitem, fllink); epi = list_entry(lsthead->next, struct epitem, fllink);
EP_LIST_DEL(&epi->fllink); EP_LIST_DEL(&epi->fllink);
down_write(&epi->ep->sem);
ep_remove(epi->ep, epi); ep_remove(epi->ep, epi);
up_write(&epi->ep->sem);
} }
up_write(&epsem);
} }
...@@ -568,9 +566,18 @@ asmlinkage long sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event *even ...@@ -568,9 +566,18 @@ asmlinkage long sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event *even
error = -EEXIST; error = -EEXIST;
break; break;
case EPOLL_CTL_DEL: case EPOLL_CTL_DEL:
if (epi) if (epi) {
/*
* We need to protect the remove operation because another
* thread might be doing an epoll_wait() and using the
* target file.
*/
down_write(&ep->sem);
error = ep_remove(ep, epi); error = ep_remove(ep, epi);
else
up_write(&ep->sem);
} else
error = -ENOENT; error = -ENOENT;
break; break;
case EPOLL_CTL_MOD: case EPOLL_CTL_MOD:
...@@ -703,10 +710,6 @@ static int ep_getfd(int *efd, struct inode **einode, struct file **efile) ...@@ -703,10 +710,6 @@ static int ep_getfd(int *efd, struct inode **einode, struct file **efile)
file->f_vfsmnt = mntget(eventpoll_mnt); file->f_vfsmnt = mntget(eventpoll_mnt);
file->f_dentry = dget(dentry); file->f_dentry = dget(dentry);
/*
* Initialize the file as read/write because it could be used
* with write() to add/remove/change interest sets.
*/
file->f_pos = 0; file->f_pos = 0;
file->f_flags = O_RDONLY; file->f_flags = O_RDONLY;
file->f_op = &eventpoll_fops; file->f_op = &eventpoll_fops;
...@@ -815,6 +818,7 @@ static int ep_init(struct eventpoll *ep, unsigned int hashbits) ...@@ -815,6 +818,7 @@ static int ep_init(struct eventpoll *ep, unsigned int hashbits)
unsigned int i, hsize; unsigned int i, hsize;
rwlock_init(&ep->lock); rwlock_init(&ep->lock);
init_rwsem(&ep->sem);
init_waitqueue_head(&ep->wq); init_waitqueue_head(&ep->wq);
init_waitqueue_head(&ep->poll_wait); init_waitqueue_head(&ep->poll_wait);
INIT_LIST_HEAD(&ep->rdllist); INIT_LIST_HEAD(&ep->rdllist);
...@@ -841,11 +845,15 @@ static void ep_free(struct eventpoll *ep) ...@@ -841,11 +845,15 @@ static void ep_free(struct eventpoll *ep)
struct list_head *lsthead, *lnk; struct list_head *lsthead, *lnk;
struct epitem *epi; struct epitem *epi;
/* We need to release all tasks waiting for these file */
if (waitqueue_active(&ep->poll_wait))
ep_poll_safewake(&psw, &ep->poll_wait);
/* /*
* We need to lock this because we could be hit by * We need to lock this because we could be hit by
* eventpoll_release() while we're freeing the "struct eventpoll". * eventpoll_release() while we're freeing the "struct eventpoll".
*/ */
down_write(&epsem); down_write(&ep->sem);
/* /*
* Walks through the whole hash by unregistering poll callbacks. * Walks through the whole hash by unregistering poll callbacks.
...@@ -863,7 +871,7 @@ static void ep_free(struct eventpoll *ep) ...@@ -863,7 +871,7 @@ static void ep_free(struct eventpoll *ep)
/* /*
* Walks through the whole hash by freeing each "struct epitem". At this * Walks through the whole hash by freeing each "struct epitem". At this
* point we are sure no poll callbacks will be lingering around, and also by * point we are sure no poll callbacks will be lingering around, and also by
* write-holding "epsem" we can be sure that no file cleanup code will hit * write-holding "sem" we can be sure that no file cleanup code will hit
* us during this operation. So we can avoid the lock on "ep->lock". * us during this operation. So we can avoid the lock on "ep->lock".
*/ */
for (i = 0, hsize = 1 << ep->hashbits; i < hsize; i++) { for (i = 0, hsize = 1 << ep->hashbits; i < hsize; i++) {
...@@ -876,7 +884,7 @@ static void ep_free(struct eventpoll *ep) ...@@ -876,7 +884,7 @@ static void ep_free(struct eventpoll *ep)
} }
} }
up_write(&epsem); up_write(&ep->sem);
/* Free hash pages */ /* Free hash pages */
ep_free_pages(ep->hpages, EP_HASH_PAGES(ep->hashbits)); ep_free_pages(ep->hpages, EP_HASH_PAGES(ep->hashbits));
...@@ -1337,20 +1345,6 @@ static int ep_collect_ready_items(struct eventpoll *ep, struct list_head *txlist ...@@ -1337,20 +1345,6 @@ static int ep_collect_ready_items(struct eventpoll *ep, struct list_head *txlist
/* If this file is already in the ready list we exit soon */ /* If this file is already in the ready list we exit soon */
if (!EP_IS_LINKED(&epi->txlink)) { if (!EP_IS_LINKED(&epi->txlink)) {
/*
* We need to increase the usage count of the "struct epitem" because
* another thread might call EPOLL_CTL_DEL on this target and make the
* object to vanish underneath our nose.
*/
ep_use_epitem(epi);
/*
* We need to increase the usage count of the "struct file" because
* another thread might call close() on this target and make the file
* to vanish before we will be able to call f_op->poll().
*/
get_file(epi->file);
/* /*
* This is initialized in this way so that the default * This is initialized in this way so that the default
* behaviour of the reinjecting code will be to push back * behaviour of the reinjecting code will be to push back
...@@ -1389,19 +1383,21 @@ static int ep_send_events(struct eventpoll *ep, struct list_head *txlist, ...@@ -1389,19 +1383,21 @@ static int ep_send_events(struct eventpoll *ep, struct list_head *txlist,
struct epitem *epi; struct epitem *epi;
struct epoll_event event[EP_MAX_BUF_EVENTS]; struct epoll_event event[EP_MAX_BUF_EVENTS];
/*
* We can loop without lock because this is a task private list.
* The test done during the collection loop will guarantee us that
* another task will not try to collect this file. Also, items
* cannot vanish during the loop because we are holding "sem".
*/
list_for_each(lnk, txlist) { list_for_each(lnk, txlist) {
epi = list_entry(lnk, struct epitem, txlink); epi = list_entry(lnk, struct epitem, txlink);
/* Get the ready file event set */
revents = epi->file->f_op->poll(epi->file, NULL);
/* /*
* Release the file usage before checking the event mask. * Get the ready file event set. We can safely use the file
* In case this call will lead to the file removal, its * because we are holding the "sem" in read and this will
* ->event.events member has been already set to zero and * guarantee that both the file and the item will not vanish.
* this will make the event to be dropped.
*/ */
fput(epi->file); revents = epi->file->f_op->poll(epi->file, NULL);
/* /*
* Set the return event set for the current file descriptor. * Set the return event set for the current file descriptor.
...@@ -1416,17 +1412,8 @@ static int ep_send_events(struct eventpoll *ep, struct list_head *txlist, ...@@ -1416,17 +1412,8 @@ static int ep_send_events(struct eventpoll *ep, struct list_head *txlist,
eventbuf++; eventbuf++;
if (eventbuf == EP_MAX_BUF_EVENTS) { if (eventbuf == EP_MAX_BUF_EVENTS) {
if (__copy_to_user(&events[eventcnt], event, if (__copy_to_user(&events[eventcnt], event,
eventbuf * sizeof(struct epoll_event))) { eventbuf * sizeof(struct epoll_event)))
/*
* We need to complete the loop to decrement the file
* usage before returning from this function.
*/
for (lnk = lnk->next; lnk != txlist; lnk = lnk->next) {
epi = list_entry(lnk, struct epitem, txlink);
fput(epi->file);
}
return -EFAULT; return -EFAULT;
}
eventcnt += eventbuf; eventcnt += eventbuf;
eventbuf = 0; eventbuf = 0;
} }
...@@ -1447,7 +1434,8 @@ static int ep_send_events(struct eventpoll *ep, struct list_head *txlist, ...@@ -1447,7 +1434,8 @@ static int ep_send_events(struct eventpoll *ep, struct list_head *txlist,
/* /*
* Walk through the transfer list we collected with ep_collect_ready_items() * Walk through the transfer list we collected with ep_collect_ready_items()
* and, if 1) the item is still "alive" 2) its event set is not empty 3) it's * and, if 1) the item is still "alive" 2) its event set is not empty 3) it's
* not already linked, links it to the ready list. * not already linked, links it to the ready list. Same as above, we are holding
* "sem" so items cannot vanish underneath our nose.
*/ */
static void ep_reinject_items(struct eventpoll *ep, struct list_head *txlist) static void ep_reinject_items(struct eventpoll *ep, struct list_head *txlist)
{ {
...@@ -1475,8 +1463,6 @@ static void ep_reinject_items(struct eventpoll *ep, struct list_head *txlist) ...@@ -1475,8 +1463,6 @@ static void ep_reinject_items(struct eventpoll *ep, struct list_head *txlist)
list_add_tail(&epi->rdllink, &ep->rdllist); list_add_tail(&epi->rdllink, &ep->rdllist);
ricnt++; ricnt++;
} }
ep_release_epitem(epi);
} }
if (ricnt) { if (ricnt) {
...@@ -1510,17 +1496,12 @@ static int ep_events_transfer(struct eventpoll *ep, struct epoll_event *events, ...@@ -1510,17 +1496,12 @@ static int ep_events_transfer(struct eventpoll *ep, struct epoll_event *events,
/* /*
* We need to lock this because we could be hit by * We need to lock this because we could be hit by
* eventpoll_release() while we're transfering * eventpoll_release() and epoll_ctl(EPOLL_CTL_DEL).
* events to userspace. Read-holding "epsem" will lock
* out eventpoll_release() during the whole
* transfer loop and this will garantie us that the
* file will not vanish underneath our nose when
* we will call f_op->poll() from ep_send_events().
*/ */
down_read(&epsem); down_read(&ep->sem);
/* Collect/extract ready items */ /* Collect/extract ready items */
if (ep_collect_ready_items(ep, &txlist, maxevents)) { if (ep_collect_ready_items(ep, &txlist, maxevents) > 0) {
/* Build result set in userspace */ /* Build result set in userspace */
eventcnt = ep_send_events(ep, &txlist, events); eventcnt = ep_send_events(ep, &txlist, events);
...@@ -1528,7 +1509,7 @@ static int ep_events_transfer(struct eventpoll *ep, struct epoll_event *events, ...@@ -1528,7 +1509,7 @@ static int ep_events_transfer(struct eventpoll *ep, struct epoll_event *events,
ep_reinject_items(ep, &txlist); ep_reinject_items(ep, &txlist);
} }
up_read(&epsem); up_read(&ep->sem);
return eventcnt; return eventcnt;
} }
...@@ -1652,9 +1633,6 @@ static int __init eventpoll_init(void) ...@@ -1652,9 +1633,6 @@ static int __init eventpoll_init(void)
{ {
int error; int error;
/* Initialize the semaphore used to syncronize the file cleanup code */
init_rwsem(&epsem);
/* Initialize the structure used to perform safe poll wait head wake ups */ /* Initialize the structure used to perform safe poll wait head wake ups */
ep_poll_safewake_init(&psw); ep_poll_safewake_init(&psw);
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <sound/driver.h> #include <sound/driver.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/compat.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/pcm.h> #include <sound/pcm.h>
#include "ioctl32.h" #include "ioctl32.h"
...@@ -136,15 +137,10 @@ struct sndrv_pcm_channel_info32 { ...@@ -136,15 +137,10 @@ struct sndrv_pcm_channel_info32 {
COPY(step);\ COPY(step);\
} }
struct timeval32 {
s32 tv_sec;
s32 tv_usec;
} __attribute__((packed));
struct sndrv_pcm_status32 { struct sndrv_pcm_status32 {
s32 state; s32 state;
struct timeval32 trigger_tstamp; struct compat_timespec trigger_tstamp;
struct timeval32 tstamp; struct compat_timespec tstamp;
u32 appl_ptr; u32 appl_ptr;
u32 hw_ptr; u32 hw_ptr;
s32 delay; s32 delay;
...@@ -159,9 +155,9 @@ struct sndrv_pcm_status32 { ...@@ -159,9 +155,9 @@ struct sndrv_pcm_status32 {
{\ {\
COPY(state);\ COPY(state);\
COPY(trigger_tstamp.tv_sec);\ COPY(trigger_tstamp.tv_sec);\
COPY(trigger_tstamp.tv_usec);\ COPY(trigger_tstamp.tv_nsec);\
COPY(tstamp.tv_sec);\ COPY(tstamp.tv_sec);\
COPY(tstamp.tv_usec);\ COPY(tstamp.tv_nsec);\
COPY(appl_ptr);\ COPY(appl_ptr);\
COPY(hw_ptr);\ COPY(hw_ptr);\
COPY(delay);\ COPY(delay);\
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <sound/driver.h> #include <sound/driver.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/compat.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/rawmidi.h> #include <sound/rawmidi.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -42,14 +43,9 @@ struct sndrv_rawmidi_params32 { ...@@ -42,14 +43,9 @@ struct sndrv_rawmidi_params32 {
COPY(no_active_sensing);\ COPY(no_active_sensing);\
} }
struct timeval32 {
s32 tv_sec;
s32 tv_usec;
} __attribute__((packed));
struct sndrv_rawmidi_status32 { struct sndrv_rawmidi_status32 {
s32 stream; s32 stream;
struct timeval32 tstamp; struct compat_timespec tstamp;
u32 avail; u32 avail;
u32 xruns; u32 xruns;
unsigned char reserved[16]; unsigned char reserved[16];
...@@ -59,7 +55,7 @@ struct sndrv_rawmidi_status32 { ...@@ -59,7 +55,7 @@ struct sndrv_rawmidi_status32 {
{\ {\
COPY(stream);\ COPY(stream);\
COPY(tstamp.tv_sec);\ COPY(tstamp.tv_sec);\
COPY(tstamp.tv_usec);\ COPY(tstamp.tv_nsec);\
COPY(avail);\ COPY(avail);\
COPY(xruns);\ COPY(xruns);\
} }
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <sound/driver.h> #include <sound/driver.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/compat.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/timer.h> #include <sound/timer.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -31,7 +32,7 @@ struct sndrv_timer_info32 { ...@@ -31,7 +32,7 @@ struct sndrv_timer_info32 {
s32 card; s32 card;
unsigned char id[64]; unsigned char id[64];
unsigned char name[80]; unsigned char name[80];
u32 ticks; u32 reserved0;
u32 resolution; u32 resolution;
unsigned char reserved[64]; unsigned char reserved[64];
}; };
...@@ -42,17 +43,11 @@ struct sndrv_timer_info32 { ...@@ -42,17 +43,11 @@ struct sndrv_timer_info32 {
COPY(card);\ COPY(card);\
memcpy(dst->id, src->id, sizeof(src->id));\ memcpy(dst->id, src->id, sizeof(src->id));\
memcpy(dst->name, src->name, sizeof(src->name));\ memcpy(dst->name, src->name, sizeof(src->name));\
COPY(ticks);\
COPY(resolution);\ COPY(resolution);\
} }
struct timeval32 {
s32 tv_sec;
s32 tv_usec;
};
struct sndrv_timer_status32 { struct sndrv_timer_status32 {
struct timeval32 tstamp; struct compat_timespec tstamp;
u32 resolution; u32 resolution;
u32 lost; u32 lost;
u32 overrun; u32 overrun;
...@@ -63,7 +58,7 @@ struct sndrv_timer_status32 { ...@@ -63,7 +58,7 @@ struct sndrv_timer_status32 {
#define CVT_sndrv_timer_status()\ #define CVT_sndrv_timer_status()\
{\ {\
COPY(tstamp.tv_sec);\ COPY(tstamp.tv_sec);\
COPY(tstamp.tv_usec);\ COPY(tstamp.tv_nsec);\
COPY(resolution);\ COPY(resolution);\
COPY(lost);\ COPY(lost);\
COPY(overrun);\ COPY(overrun);\
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/init.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/pcm.h> #include <sound/pcm.h>
#include <sound/asoundef.h> #include <sound/asoundef.h>
......
...@@ -716,10 +716,12 @@ static int snd_cs4231_trigger(snd_pcm_substream_t *substream, int cmd) ...@@ -716,10 +716,12 @@ static int snd_cs4231_trigger(snd_pcm_substream_t *substream, int cmd)
case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_STOP:
{ {
unsigned int what = 0; unsigned int what = 0;
snd_pcm_substream_t *s = substream; snd_pcm_substream_t *s;
struct list_head *pos;
unsigned long flags; unsigned long flags;
do { snd_pcm_group_for_each(pos, substream) {
s = snd_pcm_group_substream_entry(pos);
if (s == chip->playback_substream) { if (s == chip->playback_substream) {
what |= CS4231_PLAYBACK_ENABLE; what |= CS4231_PLAYBACK_ENABLE;
snd_pcm_trigger_done(s, substream); snd_pcm_trigger_done(s, substream);
...@@ -727,8 +729,7 @@ static int snd_cs4231_trigger(snd_pcm_substream_t *substream, int cmd) ...@@ -727,8 +729,7 @@ static int snd_cs4231_trigger(snd_pcm_substream_t *substream, int cmd)
what |= CS4231_RECORD_ENABLE; what |= CS4231_RECORD_ENABLE;
snd_pcm_trigger_done(s, substream); snd_pcm_trigger_done(s, substream);
} }
s = s->link_next; }
} while (s != substream);
#if 0 #if 0
printk("TRIGGER: what[%x] on(%d)\n", printk("TRIGGER: what[%x] on(%d)\n",
......
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