* Re: masquerading failure for at least icmp and tcp+sack on amd64
From: David S. Miller @ 2005-09-14 3:41 UTC (permalink / raw)
To: kaber; +Cc: akpm, netdev, netfilter-devel, schmorp, shemminger
In-Reply-To: <43277943.8050700@trash.net>
From: Patrick McHardy <kaber@trash.net>
Date: Wed, 14 Sep 2005 03:13:39 +0200
> David S. Miller wrote:
> > I personally think netfilter should do so.
>
> I agree. One thing I've planned for some silent moment is
> to clean up the entire netfilter checksumming code (there's
> lots of small duplicated chunks). Probably at least some
> of it will also be applicable for the remaining stack.
There is another thing I thought about today, and that is
to automatically handle this CHECKSUM_HW stuff when the
skb->data area is COW'd via pskb_expand_head() or similar.
I don't know how well that would work, but if it did then
we could consolidate all of this stuff into one spot which
is always nice.
^ permalink raw reply
* [PATCH 2.6.13] IPv4/IPv6: USO Scatter-gather approac
From: ravinandan.arakali @ 2005-09-14 6:55 UTC (permalink / raw)
To: jgarzik, netdev
Cc: raghavendra.koushik, ravinandan.arakali, leonid.grossman,
rapuru.sriram, ananda.raju
Hi,
Attached below is kernel patch with UPD large send offload which address the
sendfile() syscall also. This patch uses scatter-gather support of skb to
generate large UDP datagram.
Below is a "how-to" on changes required in network drivers to use the USO
interface.
UDP Large Send Offload (USO) Interface:
--------------------------------------
USO is a feature wherein the Linux kernel network stack will offload the IP
fragmentation functionality of large UDP datagram to hardware. This will reduce
the overhead of stack in fragmenting the large UDP datagram to MTU sized packets
1) Drivers indicate their capability of USO using
dev->features |= NETIF_F_USO | NETIF_F_HW_CSUM | NETIF_F_SG
NETIF_F_HW_CSUM is required for USO over ipv6.
2) USO packet will be submitted for transmission using driver xmit routine.
USO packet will have a non-zero value for
"skb_shinfo(skb)->uso_size"
skb_shinfo(skb)->uso_size will indicate the length of data part in each IP
fragment going out of the adapter after IP fragmentation by hardware.
skb->data will contain MAC/IP/UDP header and skb_shinfo(skb)->frags[]
contains the data payload. The skb->ip_summed will be set to CHECKSUM_HW
indicating that hardware has to do checksum calculation. Hardware should
compute the UDP checksum of complete datagram and also ip header checksum of
each fragmented IP packet.
For IPV6 the USO provides the fragment identification-id in
skb_shinfo(skb)->ip6_frag_id. The adapter should use this ID for generating
IPv6 fragments.
Signed-off-by: Ananda Raju <ananda.raju@neterion.com>
---
diff -uNr linux-2.6.13/include/linux/ethtool.h linux-2.6.13_uso/include/linux/ethtool.h
--- linux-2.6.13/include/linux/ethtool.h 2005-09-07 06:36:15.000000000 -0700
+++ linux-2.6.13_uso/include/linux/ethtool.h 2005-09-07 06:32:29.000000000 -0700
@@ -261,6 +261,8 @@
int ethtool_op_set_sg(struct net_device *dev, u32 data);
u32 ethtool_op_get_tso(struct net_device *dev);
int ethtool_op_set_tso(struct net_device *dev, u32 data);
+u32 ethtool_op_get_uso(struct net_device *dev);
+int ethtool_op_set_uso(struct net_device *dev, u32 data);
/**
* ðtool_ops - Alter and report network device settings
@@ -290,6 +292,8 @@
* set_sg: Turn scatter-gather on or off
* get_tso: Report whether TCP segmentation offload is enabled
* set_tso: Turn TCP segmentation offload on or off
+ * get_uso: Report whether UDP large send offload is enabled
+ * set_uso: Turn UDP large send offload on or off
* self_test: Run specified self-tests
* get_strings: Return a set of strings that describe the requested objects
* phys_id: Identify the device
@@ -354,6 +358,8 @@
void (*get_ethtool_stats)(struct net_device *, struct ethtool_stats *, u64 *);
int (*begin)(struct net_device *);
void (*complete)(struct net_device *);
+ u32 (*get_uso)(struct net_device *);
+ int (*set_uso)(struct net_device *, u32);
};
/* CMDs currently supported */
@@ -389,6 +395,8 @@
#define ETHTOOL_GSTATS 0x0000001d /* get NIC-specific statistics */
#define ETHTOOL_GTSO 0x0000001e /* Get TSO enable (ethtool_value) */
#define ETHTOOL_STSO 0x0000001f /* Set TSO enable (ethtool_value) */
+#define ETHTOOL_GUSO 0x00000020 /* Get USO enable (ethtool_value) */
+#define ETHTOOL_SUSO 0x00000021 /* Set USO enable (ethtool_value) */
/* compatibility with older code */
#define SPARC_ETH_GSET ETHTOOL_GSET
diff -uNr linux-2.6.13/include/linux/netdevice.h linux-2.6.13_uso/include/linux/netdevice.h
--- linux-2.6.13/include/linux/netdevice.h 2005-09-07 04:20:51.000000000 -0700
+++ linux-2.6.13_uso/include/linux/netdevice.h 2005-09-07 04:22:51.000000000 -0700
@@ -408,6 +408,7 @@
#define NETIF_F_VLAN_CHALLENGED 1024 /* Device cannot handle VLAN packets */
#define NETIF_F_TSO 2048 /* Can offload TCP/IP segmentation */
#define NETIF_F_LLTX 4096 /* LockLess TX */
+#define NETIF_F_USO 8192 /* Can offload UDP Large Send*/
/* Called after device is detached from network. */
void (*uninit)(struct net_device *dev);
diff -uNr linux-2.6.13/include/linux/skbuff.h linux-2.6.13_uso/include/linux/skbuff.h
--- linux-2.6.13/include/linux/skbuff.h 2005-09-07 04:20:56.000000000 -0700
+++ linux-2.6.13_uso/include/linux/skbuff.h 2005-09-07 04:22:58.000000000 -0700
@@ -137,6 +137,8 @@
unsigned int nr_frags;
unsigned short tso_size;
unsigned short tso_segs;
+ unsigned short uso_size;
+ unsigned int ip6_frag_id;
struct sk_buff *frag_list;
skb_frag_t frags[MAX_SKB_FRAGS];
};
@@ -327,6 +329,11 @@
extern void skb_under_panic(struct sk_buff *skb, int len,
void *here);
+extern int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
+ int getfrag(void *from, char *to, int offset,
+ int len,int odd, struct sk_buff *skb),
+ void *from, int length);
+
struct skb_seq_state
{
__u32 lower_offset;
diff -uNr linux-2.6.13/net/core/dev.c linux-2.6.13_uso/net/core/dev.c
--- linux-2.6.13/net/core/dev.c 2005-09-07 06:36:25.000000000 -0700
+++ linux-2.6.13_uso/net/core/dev.c 2005-09-07 06:32:02.000000000 -0700
@@ -2706,6 +2706,25 @@
dev->name);
dev->features &= ~NETIF_F_TSO;
}
+ /* TSO requires that SG is present as well. */
+ if ((dev->features & NETIF_F_TSO) &&
+ !(dev->features & NETIF_F_SG)) {
+ printk("%s: Dropping NETIF_F_TSO since no SG feature.\n",
+ dev->name);
+ dev->features &= ~NETIF_F_TSO;
+ }
+ if (dev->features & NETIF_F_USO) {
+ if (!(dev->features & NETIF_F_HW_CSUM)) {
+ printk("%s: Dropping NETIF_F_USO since no ", dev->name);
+ printk("NETIF_F_HW_CSUM feature.\n");
+ dev->features &= ~NETIF_F_USO;
+ }
+ if (!(dev->features & NETIF_F_SG)) {
+ printk("%s: Dropping NETIF_F_USO since no ", dev->name);
+ printk("NETIF_F_SG feature.\n");
+ dev->features &= ~NETIF_F_USO;
+ }
+ }
/*
* nil rebuild_header routine,
diff -uNr linux-2.6.13/net/core/ethtool.c linux-2.6.13_uso/net/core/ethtool.c
--- linux-2.6.13/net/core/ethtool.c 2005-09-07 06:36:34.000000000 -0700
+++ linux-2.6.13_uso/net/core/ethtool.c 2005-09-07 06:32:15.000000000 -0700
@@ -81,6 +81,20 @@
return 0;
}
+u32 ethtool_op_get_uso(struct net_device *dev)
+{
+ return (dev->features & NETIF_F_USO) != 0;
+}
+
+int ethtool_op_set_uso(struct net_device *dev, u32 data)
+{
+ if (data)
+ dev->features |= NETIF_F_USO;
+ else
+ dev->features &= ~NETIF_F_USO;
+ return 0;
+}
+
/* Handlers for each ethtool command */
static int ethtool_get_settings(struct net_device *dev, void __user *useraddr)
@@ -469,6 +483,9 @@
err = dev->ethtool_ops->set_tso(dev, 0);
if (err)
return err;
+ err = dev->ethtool_ops->set_uso(dev, 0);
+ if (err)
+ return err;
}
return dev->ethtool_ops->set_sg(dev, data);
@@ -557,6 +574,32 @@
return dev->ethtool_ops->set_tso(dev, edata.data);
}
+static int ethtool_get_uso(struct net_device *dev, char __user *useraddr)
+{
+ struct ethtool_value edata = { ETHTOOL_GTSO };
+
+ if (!dev->ethtool_ops->get_uso)
+ return -EOPNOTSUPP;
+ edata.data = dev->ethtool_ops->get_uso(dev);
+ if (copy_to_user(useraddr, &edata, sizeof(edata)))
+ return -EFAULT;
+ return 0;
+}
+static int ethtool_set_uso(struct net_device *dev, char __user *useraddr)
+{
+ struct ethtool_value edata;
+
+ if (!dev->ethtool_ops->set_uso)
+ return -EOPNOTSUPP;
+ if (copy_from_user(&edata, useraddr, sizeof(edata)))
+ return -EFAULT;
+ if (edata.data && !(dev->features & NETIF_F_SG))
+ return -EINVAL;
+ if (edata.data && !(dev->features & NETIF_F_HW_CSUM))
+ return -EINVAL;
+ return dev->ethtool_ops->set_uso(dev, edata.data);
+}
+
static int ethtool_self_test(struct net_device *dev, char __user *useraddr)
{
struct ethtool_test test;
@@ -806,6 +849,12 @@
case ETHTOOL_GSTATS:
rc = ethtool_get_stats(dev, useraddr);
break;
+ case ETHTOOL_GUSO:
+ rc = ethtool_get_uso(dev, useraddr);
+ break;
+ case ETHTOOL_SUSO:
+ rc = ethtool_set_uso(dev, useraddr);
+ break;
default:
rc = -EOPNOTSUPP;
}
@@ -833,3 +882,5 @@
EXPORT_SYMBOL(ethtool_op_set_tso);
EXPORT_SYMBOL(ethtool_op_set_tx_csum);
EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum);
+EXPORT_SYMBOL(ethtool_op_set_uso);
+EXPORT_SYMBOL(ethtool_op_get_uso);
diff -uNr linux-2.6.13/net/core/skbuff.c linux-2.6.13_uso/net/core/skbuff.c
--- linux-2.6.13/net/core/skbuff.c 2005-09-07 04:21:30.000000000 -0700
+++ linux-2.6.13_uso/net/core/skbuff.c 2005-09-07 06:38:57.000000000 -0700
@@ -159,6 +159,8 @@
skb_shinfo(skb)->tso_size = 0;
skb_shinfo(skb)->tso_segs = 0;
skb_shinfo(skb)->frag_list = NULL;
+ skb_shinfo(skb)->uso_size = 0;
+ skb_shinfo(skb)->ip6_frag_id = 0;
out:
return skb;
nodata:
@@ -1654,6 +1656,64 @@
return textsearch_find(config, state);
}
+/*
+ * skb_append_datato_frags - append the user data to a skb,
+ * sk - sock structure which contains skbs for transmission
+ * getfrag - The function to be called to get the data from the user.
+ * from - pointer to user message iov
+ * length - length of the iov message
+ *
+ * This procedure will allocate a skb enough to hold protocol headers and
+ * append the user data in the fragment part of the skb and add the skb to
+ * socket write queue
+ */
+int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
+ int getfrag(void *from, char *to, int offset,
+ int len,int odd, struct sk_buff *skb),
+ void *from, int length)
+{
+ int frg_cnt = 0;
+ skb_frag_t *frag = NULL;
+ struct page *page = NULL;
+ int copy, left;
+ int offset = 0;
+ do {
+ frg_cnt = skb_shinfo(skb)->nr_frags;
+ if (frg_cnt >= MAX_SKB_FRAGS) {
+ kfree_skb(skb);
+ return -EFAULT;
+ }
+ page = alloc_pages(sk->sk_allocation, 0);
+ if (page == NULL) {
+ kfree_skb(skb);
+ return -ENOMEM;
+ }
+ sk->sk_sndmsg_page = page;
+ sk->sk_sndmsg_off = 0;
+ skb_fill_page_desc(skb, frg_cnt, page, 0, 0);
+ frg_cnt = skb_shinfo(skb)->nr_frags;
+ atomic_add(PAGE_SIZE, &sk->sk_wmem_alloc);
+ skb->truesize += PAGE_SIZE;
+ frag = &skb_shinfo(skb)->frags[frg_cnt - 1];
+ left = PAGE_SIZE - frag->page_offset;
+ copy = (length > left)? left : length;
+ if (getfrag(from, page_address(frag->page) +
+ frag->page_offset+frag->size,
+ offset, copy, 0, skb) < 0) {
+ kfree_skb(skb);
+ return -EFAULT;
+ }
+ sk->sk_sndmsg_off += copy;
+ frag->size += copy;
+ skb->len += copy;
+ skb->data_len += copy;
+ offset += copy;
+ length -= copy;
+ page = NULL;
+ } while (length > 0);
+ return 0;
+}
+
void __init skb_init(void)
{
skbuff_head_cache = kmem_cache_create("skbuff_head_cache",
@@ -1696,3 +1756,4 @@
EXPORT_SYMBOL(skb_seq_read);
EXPORT_SYMBOL(skb_abort_seq_read);
EXPORT_SYMBOL(skb_find_text);
+EXPORT_SYMBOL(skb_append_datato_frags);
diff -uNr linux-2.6.13/net/ipv4/ip_output.c linux-2.6.13_uso/net/ipv4/ip_output.c
--- linux-2.6.13/net/ipv4/ip_output.c 2005-09-07 04:21:46.000000000 -0700
+++ linux-2.6.13_uso/net/ipv4/ip_output.c 2005-09-13 07:12:05.000000000 -0700
@@ -280,7 +280,8 @@
{
IP_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
- if (skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->tso_size)
+ if (skb->len > dst_mtu(skb->dst) &&
+ !(skb_shinfo(skb)->uso_size || skb_shinfo(skb)->tso_size))
return ip_fragment(skb, ip_finish_output);
else
return ip_finish_output(skb);
@@ -781,6 +782,46 @@
csummode = CHECKSUM_HW;
inet->cork.length += length;
+ if (((length > mtu) && (sk->sk_protocol == IPPROTO_UDP)) &&
+ (rt->u.dst.dev->features & NETIF_F_USO)) {
+ /* There is support for UDP large send offload by network
+ * device, so create one single skb packet containing complete
+ * udp datagram
+ */
+ if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) {
+ skb = sock_alloc_send_skb(sk,
+ hh_len + fragheaderlen + transhdrlen + 20,
+ (flags & MSG_DONTWAIT), &err);
+ if (skb == NULL)
+ goto error;
+ /* reserve space for Hardware header */
+ skb_reserve(skb, hh_len);
+ /* create space for UDP/IP header */
+ skb_put(skb,fragheaderlen + transhdrlen);
+ /* initialize network header pointer */
+ skb->nh.raw = skb->data;
+ /* initialize protocol header pointer */
+ skb->h.raw = skb->data + fragheaderlen;
+ skb->ip_summed = CHECKSUM_HW;
+ skb->csum = 0;
+ sk->sk_sndmsg_off = 0;
+ }
+ err = skb_append_datato_frags(sk,skb, getfrag, from,
+ (length - transhdrlen));
+ if (!err) {
+ /* specify the length of each IP datagram fragment*/
+ skb_shinfo(skb)->uso_size = (mtu - fragheaderlen);
+ __skb_queue_tail(&sk->sk_write_queue, skb);
+ return 0;
+ } else {
+ /* There is not enough support do UPD LSO,
+ * so follow normal path
+ */
+ kfree_skb(skb);
+ goto error;
+ }
+ }
+
/* So, what's going on in the loop below?
*
@@ -1012,14 +1053,23 @@
return -EINVAL;
inet->cork.length += size;
+ if ((sk->sk_protocol == IPPROTO_UDP) &&
+ (rt->u.dst.dev->features & NETIF_F_USO))
+ skb_shinfo(skb)->uso_size = (mtu - fragheaderlen);
+
while (size > 0) {
int i;
- /* Check if the remaining data fits into current packet. */
- len = mtu - skb->len;
- if (len < size)
- len = maxfraglen - skb->len;
+ if (skb_shinfo(skb)->uso_size) {
+ len = size;
+ } else {
+
+ /* Check if the remaining data fits into current packet. */
+ len = mtu - skb->len;
+ if (len < size)
+ len = maxfraglen - skb->len;
+ }
if (len <= 0) {
struct sk_buff *skb_prev;
char *data;
diff -uNr linux-2.6.13/net/ipv6/ip6_output.c linux-2.6.13_uso/net/ipv6/ip6_output.c
--- linux-2.6.13/net/ipv6/ip6_output.c 2005-09-07 04:21:57.000000000 -0700
+++ linux-2.6.13_uso/net/ipv6/ip6_output.c 2005-09-13 07:11:10.000000000 -0700
@@ -147,7 +147,8 @@
int ip6_output(struct sk_buff *skb)
{
- if (skb->len > dst_mtu(skb->dst) || dst_allfrag(skb->dst))
+ if ((skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->uso_size) ||
+ dst_allfrag(skb->dst))
return ip6_fragment(skb, ip6_output2);
else
return ip6_output2(skb);
@@ -893,6 +894,50 @@
*/
inet->cork.length += length;
+ if (((length > mtu) && (sk->sk_protocol == IPPROTO_UDP)) &&
+ (rt->u.dst.dev->features & NETIF_F_USO)) {
+ /* There is support for UDP large send offload by network
+ * device, so create one single skb packet containing complete
+ * udp datagram
+ */
+ if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) {
+ skb = sock_alloc_send_skb(sk,
+ hh_len + fragheaderlen + transhdrlen + 20,
+ (flags & MSG_DONTWAIT), &err);
+ if (skb == NULL)
+ goto error;
+ /* reserve space for Hardware header */
+ skb_reserve(skb, hh_len);
+ /* create space for UDP/IP header */
+ skb_put(skb,fragheaderlen + transhdrlen);
+ /* initialize network header pointer */
+ skb->nh.raw = skb->data;
+ /* initialize protocol header pointer */
+ skb->h.raw = skb->data + fragheaderlen;
+ skb->ip_summed = CHECKSUM_HW;
+ skb->csum = 0;
+ sk->sk_sndmsg_off = 0;
+ }
+ err = skb_append_datato_frags(sk,skb, getfrag, from,
+ (length - transhdrlen));
+ if (!err) {
+ struct frag_hdr fhdr;
+
+ /* specify the length of each IP datagram fragment*/
+ skb_shinfo(skb)->uso_size = (mtu - fragheaderlen) -
+ sizeof(struct frag_hdr);
+ ipv6_select_ident(skb, &fhdr);
+ skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
+ __skb_queue_tail(&sk->sk_write_queue, skb);
+ return 0;
+ } else {
+ /* There is not enough support do UPD LSO,
+ * so follow normal path
+ */
+ kfree_skb(skb);
+ goto error;
+ }
+ }
if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL)
goto alloc_new_skb;
^ permalink raw reply
* [PATCH 2.6.13] IPv4/IPv6: USO Scatter-gather approac
From: ananda.raju @ 2005-09-14 6:56 UTC (permalink / raw)
To: jgarzik, netdev
Cc: raghavendra.koushik, ravinandan.arakali, leonid.grossman,
rapuru.sriram, ananda.raju
Hi,
Attached below is kernel patch with UPD large send offload which address the
sendfile() syscall also. This patch uses scatter-gather support of skb to
generate large UDP datagram.
Below is a "how-to" on changes required in network drivers to use the USO
interface.
UDP Large Send Offload (USO) Interface:
--------------------------------------
USO is a feature wherein the Linux kernel network stack will offload the IP
fragmentation functionality of large UDP datagram to hardware. This will reduce
the overhead of stack in fragmenting the large UDP datagram to MTU sized packets
1) Drivers indicate their capability of USO using
dev->features |= NETIF_F_USO | NETIF_F_HW_CSUM | NETIF_F_SG
NETIF_F_HW_CSUM is required for USO over ipv6.
2) USO packet will be submitted for transmission using driver xmit routine.
USO packet will have a non-zero value for
"skb_shinfo(skb)->uso_size"
skb_shinfo(skb)->uso_size will indicate the length of data part in each IP
fragment going out of the adapter after IP fragmentation by hardware.
skb->data will contain MAC/IP/UDP header and skb_shinfo(skb)->frags[]
contains the data payload. The skb->ip_summed will be set to CHECKSUM_HW
indicating that hardware has to do checksum calculation. Hardware should
compute the UDP checksum of complete datagram and also ip header checksum of
each fragmented IP packet.
For IPV6 the USO provides the fragment identification-id in
skb_shinfo(skb)->ip6_frag_id. The adapter should use this ID for generating
IPv6 fragments.
Signed-off-by: Ananda Raju <ananda.raju@neterion.com>
---
diff -uNr linux-2.6.13/include/linux/ethtool.h linux-2.6.13_uso/include/linux/ethtool.h
--- linux-2.6.13/include/linux/ethtool.h 2005-09-07 06:36:15.000000000 -0700
+++ linux-2.6.13_uso/include/linux/ethtool.h 2005-09-07 06:32:29.000000000 -0700
@@ -261,6 +261,8 @@
int ethtool_op_set_sg(struct net_device *dev, u32 data);
u32 ethtool_op_get_tso(struct net_device *dev);
int ethtool_op_set_tso(struct net_device *dev, u32 data);
+u32 ethtool_op_get_uso(struct net_device *dev);
+int ethtool_op_set_uso(struct net_device *dev, u32 data);
/**
* ðtool_ops - Alter and report network device settings
@@ -290,6 +292,8 @@
* set_sg: Turn scatter-gather on or off
* get_tso: Report whether TCP segmentation offload is enabled
* set_tso: Turn TCP segmentation offload on or off
+ * get_uso: Report whether UDP large send offload is enabled
+ * set_uso: Turn UDP large send offload on or off
* self_test: Run specified self-tests
* get_strings: Return a set of strings that describe the requested objects
* phys_id: Identify the device
@@ -354,6 +358,8 @@
void (*get_ethtool_stats)(struct net_device *, struct ethtool_stats *, u64 *);
int (*begin)(struct net_device *);
void (*complete)(struct net_device *);
+ u32 (*get_uso)(struct net_device *);
+ int (*set_uso)(struct net_device *, u32);
};
/* CMDs currently supported */
@@ -389,6 +395,8 @@
#define ETHTOOL_GSTATS 0x0000001d /* get NIC-specific statistics */
#define ETHTOOL_GTSO 0x0000001e /* Get TSO enable (ethtool_value) */
#define ETHTOOL_STSO 0x0000001f /* Set TSO enable (ethtool_value) */
+#define ETHTOOL_GUSO 0x00000020 /* Get USO enable (ethtool_value) */
+#define ETHTOOL_SUSO 0x00000021 /* Set USO enable (ethtool_value) */
/* compatibility with older code */
#define SPARC_ETH_GSET ETHTOOL_GSET
diff -uNr linux-2.6.13/include/linux/netdevice.h linux-2.6.13_uso/include/linux/netdevice.h
--- linux-2.6.13/include/linux/netdevice.h 2005-09-07 04:20:51.000000000 -0700
+++ linux-2.6.13_uso/include/linux/netdevice.h 2005-09-07 04:22:51.000000000 -0700
@@ -408,6 +408,7 @@
#define NETIF_F_VLAN_CHALLENGED 1024 /* Device cannot handle VLAN packets */
#define NETIF_F_TSO 2048 /* Can offload TCP/IP segmentation */
#define NETIF_F_LLTX 4096 /* LockLess TX */
+#define NETIF_F_USO 8192 /* Can offload UDP Large Send*/
/* Called after device is detached from network. */
void (*uninit)(struct net_device *dev);
diff -uNr linux-2.6.13/include/linux/skbuff.h linux-2.6.13_uso/include/linux/skbuff.h
--- linux-2.6.13/include/linux/skbuff.h 2005-09-07 04:20:56.000000000 -0700
+++ linux-2.6.13_uso/include/linux/skbuff.h 2005-09-07 04:22:58.000000000 -0700
@@ -137,6 +137,8 @@
unsigned int nr_frags;
unsigned short tso_size;
unsigned short tso_segs;
+ unsigned short uso_size;
+ unsigned int ip6_frag_id;
struct sk_buff *frag_list;
skb_frag_t frags[MAX_SKB_FRAGS];
};
@@ -327,6 +329,11 @@
extern void skb_under_panic(struct sk_buff *skb, int len,
void *here);
+extern int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
+ int getfrag(void *from, char *to, int offset,
+ int len,int odd, struct sk_buff *skb),
+ void *from, int length);
+
struct skb_seq_state
{
__u32 lower_offset;
diff -uNr linux-2.6.13/net/core/dev.c linux-2.6.13_uso/net/core/dev.c
--- linux-2.6.13/net/core/dev.c 2005-09-07 06:36:25.000000000 -0700
+++ linux-2.6.13_uso/net/core/dev.c 2005-09-07 06:32:02.000000000 -0700
@@ -2706,6 +2706,25 @@
dev->name);
dev->features &= ~NETIF_F_TSO;
}
+ /* TSO requires that SG is present as well. */
+ if ((dev->features & NETIF_F_TSO) &&
+ !(dev->features & NETIF_F_SG)) {
+ printk("%s: Dropping NETIF_F_TSO since no SG feature.\n",
+ dev->name);
+ dev->features &= ~NETIF_F_TSO;
+ }
+ if (dev->features & NETIF_F_USO) {
+ if (!(dev->features & NETIF_F_HW_CSUM)) {
+ printk("%s: Dropping NETIF_F_USO since no ", dev->name);
+ printk("NETIF_F_HW_CSUM feature.\n");
+ dev->features &= ~NETIF_F_USO;
+ }
+ if (!(dev->features & NETIF_F_SG)) {
+ printk("%s: Dropping NETIF_F_USO since no ", dev->name);
+ printk("NETIF_F_SG feature.\n");
+ dev->features &= ~NETIF_F_USO;
+ }
+ }
/*
* nil rebuild_header routine,
diff -uNr linux-2.6.13/net/core/ethtool.c linux-2.6.13_uso/net/core/ethtool.c
--- linux-2.6.13/net/core/ethtool.c 2005-09-07 06:36:34.000000000 -0700
+++ linux-2.6.13_uso/net/core/ethtool.c 2005-09-07 06:32:15.000000000 -0700
@@ -81,6 +81,20 @@
return 0;
}
+u32 ethtool_op_get_uso(struct net_device *dev)
+{
+ return (dev->features & NETIF_F_USO) != 0;
+}
+
+int ethtool_op_set_uso(struct net_device *dev, u32 data)
+{
+ if (data)
+ dev->features |= NETIF_F_USO;
+ else
+ dev->features &= ~NETIF_F_USO;
+ return 0;
+}
+
/* Handlers for each ethtool command */
static int ethtool_get_settings(struct net_device *dev, void __user *useraddr)
@@ -469,6 +483,9 @@
err = dev->ethtool_ops->set_tso(dev, 0);
if (err)
return err;
+ err = dev->ethtool_ops->set_uso(dev, 0);
+ if (err)
+ return err;
}
return dev->ethtool_ops->set_sg(dev, data);
@@ -557,6 +574,32 @@
return dev->ethtool_ops->set_tso(dev, edata.data);
}
+static int ethtool_get_uso(struct net_device *dev, char __user *useraddr)
+{
+ struct ethtool_value edata = { ETHTOOL_GTSO };
+
+ if (!dev->ethtool_ops->get_uso)
+ return -EOPNOTSUPP;
+ edata.data = dev->ethtool_ops->get_uso(dev);
+ if (copy_to_user(useraddr, &edata, sizeof(edata)))
+ return -EFAULT;
+ return 0;
+}
+static int ethtool_set_uso(struct net_device *dev, char __user *useraddr)
+{
+ struct ethtool_value edata;
+
+ if (!dev->ethtool_ops->set_uso)
+ return -EOPNOTSUPP;
+ if (copy_from_user(&edata, useraddr, sizeof(edata)))
+ return -EFAULT;
+ if (edata.data && !(dev->features & NETIF_F_SG))
+ return -EINVAL;
+ if (edata.data && !(dev->features & NETIF_F_HW_CSUM))
+ return -EINVAL;
+ return dev->ethtool_ops->set_uso(dev, edata.data);
+}
+
static int ethtool_self_test(struct net_device *dev, char __user *useraddr)
{
struct ethtool_test test;
@@ -806,6 +849,12 @@
case ETHTOOL_GSTATS:
rc = ethtool_get_stats(dev, useraddr);
break;
+ case ETHTOOL_GUSO:
+ rc = ethtool_get_uso(dev, useraddr);
+ break;
+ case ETHTOOL_SUSO:
+ rc = ethtool_set_uso(dev, useraddr);
+ break;
default:
rc = -EOPNOTSUPP;
}
@@ -833,3 +882,5 @@
EXPORT_SYMBOL(ethtool_op_set_tso);
EXPORT_SYMBOL(ethtool_op_set_tx_csum);
EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum);
+EXPORT_SYMBOL(ethtool_op_set_uso);
+EXPORT_SYMBOL(ethtool_op_get_uso);
diff -uNr linux-2.6.13/net/core/skbuff.c linux-2.6.13_uso/net/core/skbuff.c
--- linux-2.6.13/net/core/skbuff.c 2005-09-07 04:21:30.000000000 -0700
+++ linux-2.6.13_uso/net/core/skbuff.c 2005-09-07 06:38:57.000000000 -0700
@@ -159,6 +159,8 @@
skb_shinfo(skb)->tso_size = 0;
skb_shinfo(skb)->tso_segs = 0;
skb_shinfo(skb)->frag_list = NULL;
+ skb_shinfo(skb)->uso_size = 0;
+ skb_shinfo(skb)->ip6_frag_id = 0;
out:
return skb;
nodata:
@@ -1654,6 +1656,64 @@
return textsearch_find(config, state);
}
+/*
+ * skb_append_datato_frags - append the user data to a skb,
+ * sk - sock structure which contains skbs for transmission
+ * getfrag - The function to be called to get the data from the user.
+ * from - pointer to user message iov
+ * length - length of the iov message
+ *
+ * This procedure will allocate a skb enough to hold protocol headers and
+ * append the user data in the fragment part of the skb and add the skb to
+ * socket write queue
+ */
+int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
+ int getfrag(void *from, char *to, int offset,
+ int len,int odd, struct sk_buff *skb),
+ void *from, int length)
+{
+ int frg_cnt = 0;
+ skb_frag_t *frag = NULL;
+ struct page *page = NULL;
+ int copy, left;
+ int offset = 0;
+ do {
+ frg_cnt = skb_shinfo(skb)->nr_frags;
+ if (frg_cnt >= MAX_SKB_FRAGS) {
+ kfree_skb(skb);
+ return -EFAULT;
+ }
+ page = alloc_pages(sk->sk_allocation, 0);
+ if (page == NULL) {
+ kfree_skb(skb);
+ return -ENOMEM;
+ }
+ sk->sk_sndmsg_page = page;
+ sk->sk_sndmsg_off = 0;
+ skb_fill_page_desc(skb, frg_cnt, page, 0, 0);
+ frg_cnt = skb_shinfo(skb)->nr_frags;
+ atomic_add(PAGE_SIZE, &sk->sk_wmem_alloc);
+ skb->truesize += PAGE_SIZE;
+ frag = &skb_shinfo(skb)->frags[frg_cnt - 1];
+ left = PAGE_SIZE - frag->page_offset;
+ copy = (length > left)? left : length;
+ if (getfrag(from, page_address(frag->page) +
+ frag->page_offset+frag->size,
+ offset, copy, 0, skb) < 0) {
+ kfree_skb(skb);
+ return -EFAULT;
+ }
+ sk->sk_sndmsg_off += copy;
+ frag->size += copy;
+ skb->len += copy;
+ skb->data_len += copy;
+ offset += copy;
+ length -= copy;
+ page = NULL;
+ } while (length > 0);
+ return 0;
+}
+
void __init skb_init(void)
{
skbuff_head_cache = kmem_cache_create("skbuff_head_cache",
@@ -1696,3 +1756,4 @@
EXPORT_SYMBOL(skb_seq_read);
EXPORT_SYMBOL(skb_abort_seq_read);
EXPORT_SYMBOL(skb_find_text);
+EXPORT_SYMBOL(skb_append_datato_frags);
diff -uNr linux-2.6.13/net/ipv4/ip_output.c linux-2.6.13_uso/net/ipv4/ip_output.c
--- linux-2.6.13/net/ipv4/ip_output.c 2005-09-07 04:21:46.000000000 -0700
+++ linux-2.6.13_uso/net/ipv4/ip_output.c 2005-09-13 07:12:05.000000000 -0700
@@ -280,7 +280,8 @@
{
IP_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
- if (skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->tso_size)
+ if (skb->len > dst_mtu(skb->dst) &&
+ !(skb_shinfo(skb)->uso_size || skb_shinfo(skb)->tso_size))
return ip_fragment(skb, ip_finish_output);
else
return ip_finish_output(skb);
@@ -781,6 +782,46 @@
csummode = CHECKSUM_HW;
inet->cork.length += length;
+ if (((length > mtu) && (sk->sk_protocol == IPPROTO_UDP)) &&
+ (rt->u.dst.dev->features & NETIF_F_USO)) {
+ /* There is support for UDP large send offload by network
+ * device, so create one single skb packet containing complete
+ * udp datagram
+ */
+ if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) {
+ skb = sock_alloc_send_skb(sk,
+ hh_len + fragheaderlen + transhdrlen + 20,
+ (flags & MSG_DONTWAIT), &err);
+ if (skb == NULL)
+ goto error;
+ /* reserve space for Hardware header */
+ skb_reserve(skb, hh_len);
+ /* create space for UDP/IP header */
+ skb_put(skb,fragheaderlen + transhdrlen);
+ /* initialize network header pointer */
+ skb->nh.raw = skb->data;
+ /* initialize protocol header pointer */
+ skb->h.raw = skb->data + fragheaderlen;
+ skb->ip_summed = CHECKSUM_HW;
+ skb->csum = 0;
+ sk->sk_sndmsg_off = 0;
+ }
+ err = skb_append_datato_frags(sk,skb, getfrag, from,
+ (length - transhdrlen));
+ if (!err) {
+ /* specify the length of each IP datagram fragment*/
+ skb_shinfo(skb)->uso_size = (mtu - fragheaderlen);
+ __skb_queue_tail(&sk->sk_write_queue, skb);
+ return 0;
+ } else {
+ /* There is not enough support do UPD LSO,
+ * so follow normal path
+ */
+ kfree_skb(skb);
+ goto error;
+ }
+ }
+
/* So, what's going on in the loop below?
*
@@ -1012,14 +1053,23 @@
return -EINVAL;
inet->cork.length += size;
+ if ((sk->sk_protocol == IPPROTO_UDP) &&
+ (rt->u.dst.dev->features & NETIF_F_USO))
+ skb_shinfo(skb)->uso_size = (mtu - fragheaderlen);
+
while (size > 0) {
int i;
- /* Check if the remaining data fits into current packet. */
- len = mtu - skb->len;
- if (len < size)
- len = maxfraglen - skb->len;
+ if (skb_shinfo(skb)->uso_size) {
+ len = size;
+ } else {
+
+ /* Check if the remaining data fits into current packet. */
+ len = mtu - skb->len;
+ if (len < size)
+ len = maxfraglen - skb->len;
+ }
if (len <= 0) {
struct sk_buff *skb_prev;
char *data;
diff -uNr linux-2.6.13/net/ipv6/ip6_output.c linux-2.6.13_uso/net/ipv6/ip6_output.c
--- linux-2.6.13/net/ipv6/ip6_output.c 2005-09-07 04:21:57.000000000 -0700
+++ linux-2.6.13_uso/net/ipv6/ip6_output.c 2005-09-13 07:11:10.000000000 -0700
@@ -147,7 +147,8 @@
int ip6_output(struct sk_buff *skb)
{
- if (skb->len > dst_mtu(skb->dst) || dst_allfrag(skb->dst))
+ if ((skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->uso_size) ||
+ dst_allfrag(skb->dst))
return ip6_fragment(skb, ip6_output2);
else
return ip6_output2(skb);
@@ -893,6 +894,50 @@
*/
inet->cork.length += length;
+ if (((length > mtu) && (sk->sk_protocol == IPPROTO_UDP)) &&
+ (rt->u.dst.dev->features & NETIF_F_USO)) {
+ /* There is support for UDP large send offload by network
+ * device, so create one single skb packet containing complete
+ * udp datagram
+ */
+ if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) {
+ skb = sock_alloc_send_skb(sk,
+ hh_len + fragheaderlen + transhdrlen + 20,
+ (flags & MSG_DONTWAIT), &err);
+ if (skb == NULL)
+ goto error;
+ /* reserve space for Hardware header */
+ skb_reserve(skb, hh_len);
+ /* create space for UDP/IP header */
+ skb_put(skb,fragheaderlen + transhdrlen);
+ /* initialize network header pointer */
+ skb->nh.raw = skb->data;
+ /* initialize protocol header pointer */
+ skb->h.raw = skb->data + fragheaderlen;
+ skb->ip_summed = CHECKSUM_HW;
+ skb->csum = 0;
+ sk->sk_sndmsg_off = 0;
+ }
+ err = skb_append_datato_frags(sk,skb, getfrag, from,
+ (length - transhdrlen));
+ if (!err) {
+ struct frag_hdr fhdr;
+
+ /* specify the length of each IP datagram fragment*/
+ skb_shinfo(skb)->uso_size = (mtu - fragheaderlen) -
+ sizeof(struct frag_hdr);
+ ipv6_select_ident(skb, &fhdr);
+ skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
+ __skb_queue_tail(&sk->sk_write_queue, skb);
+ return 0;
+ } else {
+ /* There is not enough support do UPD LSO,
+ * so follow normal path
+ */
+ kfree_skb(skb);
+ goto error;
+ }
+ }
if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL)
goto alloc_new_skb;
^ permalink raw reply
* Re: [patch 9/11] net: dst_entry.refcount, use, lastuse to use alloc_percpu
From: Rusty Russell @ 2005-09-14 7:21 UTC (permalink / raw)
To: David S. Miller
Cc: kiran, akpm, linux-kernel, dipankar, bharata, shai, netdev
In-Reply-To: <20050913.162748.86496945.davem@davemloft.net>
On Tue, 2005-09-13 at 16:27 -0700, David S. Miller wrote:
> From: Ravikiran G Thirumalai <kiran@scalex86.org>
> Date: Tue, 13 Sep 2005 16:17:17 -0700
>
> > But even 1 Million dst cache entries would be 16+4 MB additional for
> > a 4 cpu box....is that too much?
>
> Absolutely.
>
> Per-cpu counters are great for things like single instance
> statistics et al. But once you start doing them per-object
> that's out of control bloat as far as I'm concerned.
This is why my original per-cpu allocator patch was damn slow, and
GFP_KERNEL only. I wasn't convinced that high-churn objects are a good
fit for spreading across cpus.
I thought that net devices and modules (which uses a primitive
hard-coded "bigref" currently) were a fair uses for bigrefs, though I'd
like to see some stats.
Cheers,
Rusty.
--
A bad analogy is like a leaky screwdriver -- Richard Braakman
^ permalink raw reply
* Re: Route cache performance
From: Robert Olsson @ 2005-09-14 8:04 UTC (permalink / raw)
To: Simon Kirby; +Cc: Alexey Kuznetsov, Robert Olsson, Eric Dumazet, netdev
In-Reply-To: <20050913221448.GD15704@netnation.com>
Simon Kirby writes:
> Sender: 367 Mbps, 717883 pps valid src/dst, 64 byte (Ethernet) packets
>
> 2.4.27-rc1: 297 Mbps forwarded (w/idle time?!)
> 2.4.31: 296 Mbps forwarded (w/idle time?!)
> 2.6.13-rc6: 173 Mbps forwarded
> Time permitting, I'd also like to run some profiles. It's interesting
> to note that 2.6 is slower at forwarding even straight duplicate small
> packets. We should definitely get to the bottom of that.
Yes. This is single flow? Strange.
Run a fixed size shot 10Mpkts pkts or so for both 2.4 and 2.6 and save
/proc/interrupts, proc/net/softnetstat, netstat -i, tc -s qdisc to start with.
A profile on 2.6 could solve the confusion.
Cheers.
--ro
^ permalink raw reply
* Re: [PATCH 2.6.13] pcnet32: set min ring size to 4
From: Jeff Garzik @ 2005-09-14 12:28 UTC (permalink / raw)
To: Hubert WS Lin; +Cc: netdev, linux-kernel, fubar, donf, jklewis
In-Reply-To: <4325298D.1010600@tw.ibm.com>
Hubert WS Lin wrote:
> Hi,
>
> Don Fry reminded me that the pcnet32_loopback_test() asssumes the ring
> size is no less than 4. The minimum ring size was changed to 4 in
> pcnet32_set_ringparam() to allow the loopback test to work unchanged.
>
> Changelog:
> - Set minimum ring size to 4 to allow loopback test to work unchanged
> - Moved variable init_block to first field in struct pcnet32_private
>
> Signed-off-by: Hubert WS Lin <wslin@tw.ibm.com>
Patch OK, but:
Applying 'pcnet32: set min ring size to 4'
error: patch failed: drivers/net/pcnet32.c:22
error: drivers/net/pcnet32.c: patch does not apply
Please resend, without MIME attachments.
Jeff
^ permalink raw reply
* Re: [PATCH 1/3] orinoco: WE-18 support
From: Jeff Garzik @ 2005-09-14 12:31 UTC (permalink / raw)
To: Pavel Roskin
Cc: Orinoco Development List, netdev-u79uwXL29TY76Z2rM5mHXA,
Jean Tourrilhes
In-Reply-To: <1126305782.16679.5.camel@dv>
Pavel Roskin wrote:
> Author: Jean Tourrilhes <jt-sDzT885Ts8HQT0dZR+AlfA@public.gmane.org>
> Signed-off-by: Pavel Roskin <proski-mXXj517/zsQ@public.gmane.org>
>
> Use new Wireless Extension API for wireless stats.
Applied patch #1, the rest failed:
[jgarzik@pretzel netdev-2.6]$ applymbox /g/tmp/mbox ~/info/signoff.txt
Applying 'orinoco: WE-18 support'
Wrote tree 2713fbd5e71f7a7dbe94634a1bc4eb81a1ed8af5
Committed: 343c686c04eec556645f251f7d6c9b3d7335dae0
Applying 'orinoco: Update PCMCIA ID's'
error: patch failed: drivers/net/wireless/orinoco_cs.c:601
error: drivers/net/wireless/orinoco_cs.c: patch does not apply
-------------------------------------------------------
This SF.Net email is sponsored by:
Power Architecture Resource Center: Free content, downloads, discussions,
and more. http://solutions.newsforge.com/ibmarch.tmpl
^ permalink raw reply
* Re: [PATCH 1/2] New PowerPC 4xx on-chip ethernet controller driver
From: Jeff Garzik @ 2005-09-14 12:45 UTC (permalink / raw)
To: Eugene Surovegin; +Cc: netdev, linuxppc-embedded
In-Reply-To: <20050831050048.GB17017@gate.ebshome.net>
Eugene Surovegin wrote:
> Remove old PPC4xx EMAC driver
>
> Signed-off-by: Eugene Surovegin <ebs@ebshome.net>
Please post a diff, along with a description of the changes.
One huge patch to "remove emac driver" and another huge patch to "add
emac driver" is quite silly.
Jeff
^ permalink raw reply
* [git patches] net driver fixes
From: Jeff Garzik @ 2005-09-14 13:14 UTC (permalink / raw)
To: Andrew Morton, Linus Torvalds; +Cc: netdev, linux-kernel
Please pull from 'upstream-fixes' branch of
rsync://rsync.kernel.org/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git
to obtain the following fixes:
drivers/net/Kconfig | 2
drivers/net/e100.c | 4 -
drivers/net/e1000/e1000_main.c | 1
drivers/net/ixgb/ixgb_main.c | 2
drivers/net/s2io.c | 9 ++-
drivers/net/sk98lin/skge.c | 12 ++---
drivers/net/skge.c | 98 ++++++++++++++++++++++-------------------
drivers/net/skge.h | 2
drivers/net/tulip/xircom_cb.c | 2
drivers/net/wireless/airo.c | 5 +-
drivers/s390/net/ctcmain.c | 41 +++++++++--------
11 files changed, 94 insertions(+), 84 deletions(-)
Andrew Morton:
s2io warning fixes
Frank Pavlic:
s390: ctc driver fixes
John W. Linville:
e1000: correct rx_dropped counting
e100: correct rx_dropped and add rx_missed_errors
ixgb: correct rx_dropped counting
Keith Owens:
Correct xircom_cb use of CONFIG_NET_POLL_CONTROLLER
matthieu castet:
airo : fix channel number in scan
Stephen Hemminger:
sk98lin: remove PCI id info for cards for conflicting devices
skge: gmac register access errors in dual port
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1951,7 +1951,7 @@ config SKGE
---help---
This driver support the Marvell Yukon or SysKonnect SK-98xx/SK-95xx
and related Gigabit Ethernet adapters. It is a new smaller driver
- driver with better performance and more complete ethtool support.
+ with better performance and more complete ethtool support.
It does not support the link failover and network management
features that "portable" vendor supplied sk98lin driver does.
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -1387,13 +1387,13 @@ static void e100_update_stats(struct nic
ns->collisions += nic->tx_collisions;
ns->tx_errors += le32_to_cpu(s->tx_max_collisions) +
le32_to_cpu(s->tx_lost_crs);
- ns->rx_dropped += le32_to_cpu(s->rx_resource_errors);
ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) +
nic->rx_over_length_errors;
ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors);
ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors);
ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors);
ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors);
+ ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors);
ns->rx_errors += le32_to_cpu(s->rx_crc_errors) +
le32_to_cpu(s->rx_alignment_errors) +
le32_to_cpu(s->rx_short_frame_errors) +
@@ -1727,12 +1727,10 @@ static inline int e100_rx_indicate(struc
if(unlikely(!(rfd_status & cb_ok))) {
/* Don't indicate if hardware indicates errors */
- nic->net_stats.rx_dropped++;
dev_kfree_skb_any(skb);
} else if(actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) {
/* Don't indicate oversized frames */
nic->rx_over_length_errors++;
- nic->net_stats.rx_dropped++;
dev_kfree_skb_any(skb);
} else {
nic->net_stats.rx_packets++;
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -2544,7 +2544,6 @@ e1000_update_stats(struct e1000_adapter
adapter->stats.crcerrs + adapter->stats.algnerrc +
adapter->stats.rlec + adapter->stats.mpc +
adapter->stats.cexterr;
- adapter->net_stats.rx_dropped = adapter->stats.mpc;
adapter->net_stats.rx_length_errors = adapter->stats.rlec;
adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs;
adapter->net_stats.rx_frame_errors = adapter->stats.algnerrc;
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -1616,8 +1616,6 @@ ixgb_update_stats(struct ixgb_adapter *a
adapter->stats.icbc +
adapter->stats.ecbc + adapter->stats.mpc;
- adapter->net_stats.rx_dropped = adapter->stats.mpc;
-
/* see above
* adapter->net_stats.rx_length_errors = adapter->stats.rlec;
*/
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -428,7 +428,7 @@ static int init_shared_mem(struct s2io_n
DBG_PRINT(INIT_DBG,
"%s: Zero DMA address for TxDL. ", dev->name);
DBG_PRINT(INIT_DBG,
- "Virtual address %llx\n", (u64)tmp_v);
+ "Virtual address %p\n", tmp_v);
tmp_v = pci_alloc_consistent(nic->pdev,
PAGE_SIZE, &tmp_p);
if (!tmp_v) {
@@ -657,9 +657,10 @@ static void free_shared_mem(struct s2io_
mac_control->zerodma_virt_addr,
(dma_addr_t)0);
DBG_PRINT(INIT_DBG,
- "%s: Freeing TxDL with zero DMA addr. ", dev->name);
- DBG_PRINT(INIT_DBG, "Virtual address %llx\n",
- (u64)(mac_control->zerodma_virt_addr));
+ "%s: Freeing TxDL with zero DMA addr. ",
+ dev->name);
+ DBG_PRINT(INIT_DBG, "Virtual address %p\n",
+ mac_control->zerodma_virt_addr);
}
kfree(mac_control->fifos[i].list_info);
}
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
--- a/drivers/net/sk98lin/skge.c
+++ b/drivers/net/sk98lin/skge.c
@@ -5216,17 +5216,15 @@ static struct pci_device_id skge_pci_tbl
{ PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ PCI_VENDOR_ID_SYSKONNECT, 0x4300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ PCI_VENDOR_ID_SYSKONNECT, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_DLINK, 0x4c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+/* DLink card does not have valid VPD so this driver gags
+ * { PCI_VENDOR_ID_DLINK, 0x4c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ */
{ PCI_VENDOR_ID_MARVELL, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-#if 0 /* don't handle Yukon2 cards at the moment -- mlindner@syskonnect.de */
- { PCI_VENDOR_ID_MARVELL, 0x4360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_MARVELL, 0x4361, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-#endif
{ PCI_VENDOR_ID_MARVELL, 0x5005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ PCI_VENDOR_ID_CNET, 0x434e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015, },
{ PCI_VENDOR_ID_LINKSYS, 0x1064, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { 0, }
+ { 0 }
};
MODULE_DEVICE_TABLE(pci, skge_pci_tbl);
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -42,7 +42,7 @@
#include "skge.h"
#define DRV_NAME "skge"
-#define DRV_VERSION "0.9"
+#define DRV_VERSION "1.0"
#define PFX DRV_NAME " "
#define DEFAULT_TX_RING_SIZE 128
@@ -669,7 +669,7 @@ static void skge_led(struct skge_port *s
PHY_M_LED_BLINK_RT(BLINK_84MS) |
PHY_M_LEDC_TX_CTRL |
PHY_M_LEDC_DP_CTRL);
-
+
gm_phy_write(hw, port, PHY_MARV_LED_OVER,
PHY_M_LED_MO_RX(MO_LED_OFF) |
(skge->speed == SPEED_100 ?
@@ -876,7 +876,7 @@ static int skge_rx_fill(struct skge_port
static void skge_link_up(struct skge_port *skge)
{
- skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG),
+ skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG),
LED_BLK_OFF|LED_SYNC_OFF|LED_ON);
netif_carrier_on(skge->netdev);
@@ -987,6 +987,8 @@ static void genesis_reset(struct skge_hw
{
const u8 zero[8] = { 0 };
+ skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0);
+
/* reset the statistics module */
xm_write32(hw, port, XM_GP_PORT, XM_GP_RES_STAT);
xm_write16(hw, port, XM_IMSK, 0xffff); /* disable XMAC IRQs */
@@ -1021,8 +1023,6 @@ static void bcom_check_link(struct skge_
(void) xm_phy_read(hw, port, PHY_BCOM_STAT);
status = xm_phy_read(hw, port, PHY_BCOM_STAT);
- pr_debug("bcom_check_link status=0x%x\n", status);
-
if ((status & PHY_ST_LSYNC) == 0) {
u16 cmd = xm_read16(hw, port, XM_MMU_CMD);
cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX);
@@ -1106,8 +1106,6 @@ static void bcom_phy_init(struct skge_po
{ 0x17, 0x0013 }, { 0x15, 0x0A04 }, { 0x18, 0x0420 },
};
- pr_debug("bcom_phy_init\n");
-
/* read Id from external PHY (all have the same address) */
id1 = xm_phy_read(hw, port, PHY_XMAC_ID1);
@@ -1340,6 +1338,8 @@ static void genesis_stop(struct skge_por
int port = skge->port;
u32 reg;
+ genesis_reset(hw, port);
+
/* Clear Tx packet arbiter timeout IRQ */
skge_write16(hw, B3_PA_CTRL,
port == 0 ? PA_CLR_TO_TX1 : PA_CLR_TO_TX2);
@@ -1465,7 +1465,6 @@ static void genesis_link_up(struct skge_
u16 cmd;
u32 mode, msk;
- pr_debug("genesis_link_up\n");
cmd = xm_read16(hw, port, XM_MMU_CMD);
/*
@@ -1578,7 +1577,6 @@ static void yukon_init(struct skge_hw *h
struct skge_port *skge = netdev_priv(hw->dev[port]);
u16 ctrl, ct1000, adv;
- pr_debug("yukon_init\n");
if (skge->autoneg == AUTONEG_ENABLE) {
u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL);
@@ -1677,9 +1675,11 @@ static void yukon_mac_init(struct skge_h
/* WA code for COMA mode -- set PHY reset */
if (hw->chip_id == CHIP_ID_YUKON_LITE &&
- hw->chip_rev >= CHIP_REV_YU_LITE_A3)
- skge_write32(hw, B2_GP_IO,
- (skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9));
+ hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
+ reg = skge_read32(hw, B2_GP_IO);
+ reg |= GP_DIR_9 | GP_IO_9;
+ skge_write32(hw, B2_GP_IO, reg);
+ }
/* hard reset */
skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
@@ -1687,10 +1687,12 @@ static void yukon_mac_init(struct skge_h
/* WA code for COMA mode -- clear PHY reset */
if (hw->chip_id == CHIP_ID_YUKON_LITE &&
- hw->chip_rev >= CHIP_REV_YU_LITE_A3)
- skge_write32(hw, B2_GP_IO,
- (skge_read32(hw, B2_GP_IO) | GP_DIR_9)
- & ~GP_IO_9);
+ hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
+ reg = skge_read32(hw, B2_GP_IO);
+ reg |= GP_DIR_9;
+ reg &= ~GP_IO_9;
+ skge_write32(hw, B2_GP_IO, reg);
+ }
/* Set hardware config mode */
reg = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP |
@@ -1729,7 +1731,7 @@ static void yukon_mac_init(struct skge_h
}
gma_write16(hw, port, GM_GP_CTRL, reg);
- skge_read16(hw, GMAC_IRQ_SRC);
+ skge_read16(hw, SK_REG(port, GMAC_IRQ_SRC));
yukon_init(hw, port);
@@ -1801,20 +1803,26 @@ static void yukon_stop(struct skge_port
struct skge_hw *hw = skge->hw;
int port = skge->port;
- if (hw->chip_id == CHIP_ID_YUKON_LITE &&
- hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
- skge_write32(hw, B2_GP_IO,
- skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9);
- }
+ skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0);
+ yukon_reset(hw, port);
gma_write16(hw, port, GM_GP_CTRL,
gma_read16(hw, port, GM_GP_CTRL)
& ~(GM_GPCR_TX_ENA|GM_GPCR_RX_ENA));
gma_read16(hw, port, GM_GP_CTRL);
+ if (hw->chip_id == CHIP_ID_YUKON_LITE &&
+ hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
+ u32 io = skge_read32(hw, B2_GP_IO);
+
+ io |= GP_DIR_9 | GP_IO_9;
+ skge_write32(hw, B2_GP_IO, io);
+ skge_read32(hw, B2_GP_IO);
+ }
+
/* set GPHY Control reset */
- skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
- skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET);
+ skge_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
+ skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET);
}
static void yukon_get_stats(struct skge_port *skge, u64 *data)
@@ -1873,10 +1881,8 @@ static void yukon_link_up(struct skge_po
int port = skge->port;
u16 reg;
- pr_debug("yukon_link_up\n");
-
/* Enable Transmit FIFO Underrun */
- skge_write8(hw, GMAC_IRQ_MSK, GMAC_DEF_MSK);
+ skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), GMAC_DEF_MSK);
reg = gma_read16(hw, port, GM_GP_CTRL);
if (skge->duplex == DUPLEX_FULL || skge->autoneg == AUTONEG_ENABLE)
@@ -1896,7 +1902,6 @@ static void yukon_link_down(struct skge_
int port = skge->port;
u16 ctrl;
- pr_debug("yukon_link_down\n");
gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);
ctrl = gma_read16(hw, port, GM_GP_CTRL);
@@ -2112,7 +2117,6 @@ static int skge_up(struct net_device *de
skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F);
skge_led(skge, LED_MODE_ON);
- pr_debug("skge_up completed\n");
return 0;
free_rx_ring:
@@ -2135,15 +2139,20 @@ static int skge_down(struct net_device *
netif_stop_queue(dev);
+ skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
+ if (hw->chip_id == CHIP_ID_GENESIS)
+ genesis_stop(skge);
+ else
+ yukon_stop(skge);
+
+ hw->intr_mask &= ~portirqmask[skge->port];
+ skge_write32(hw, B0_IMSK, hw->intr_mask);
+
/* Stop transmitter */
skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP);
skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL),
RB_RST_SET|RB_DIS_OP_MD);
- if (hw->chip_id == CHIP_ID_GENESIS)
- genesis_stop(skge);
- else
- yukon_stop(skge);
/* Disable Force Sync bit and Enable Alloc bit */
skge_write8(hw, SK_REG(port, TXA_CTRL),
@@ -2367,8 +2376,6 @@ static void genesis_set_multicast(struct
u32 mode;
u8 filter[8];
- pr_debug("genesis_set_multicast flags=%x count=%d\n", dev->flags, dev->mc_count);
-
mode = xm_read32(hw, port, XM_MODE);
mode |= XM_MD_ENA_HASH;
if (dev->flags & IFF_PROMISC)
@@ -2530,8 +2537,6 @@ static int skge_poll(struct net_device *
unsigned int to_do = min(dev->quota, *budget);
unsigned int work_done = 0;
- pr_debug("skge_poll\n");
-
for (e = ring->to_clean; work_done < to_do; e = e->next) {
struct skge_rx_desc *rd = e->desc;
struct sk_buff *skb;
@@ -2672,9 +2677,9 @@ static void skge_error_irq(struct skge_h
if (hw->chip_id == CHIP_ID_GENESIS) {
/* clear xmac errors */
if (hwstatus & (IS_NO_STAT_M1|IS_NO_TIST_M1))
- skge_write16(hw, SK_REG(0, RX_MFF_CTRL1), MFF_CLR_INSTAT);
+ skge_write16(hw, RX_MFF_CTRL1, MFF_CLR_INSTAT);
if (hwstatus & (IS_NO_STAT_M2|IS_NO_TIST_M2))
- skge_write16(hw, SK_REG(0, RX_MFF_CTRL2), MFF_CLR_INSTAT);
+ skge_write16(hw, RX_MFF_CTRL2, MFF_CLR_INSTAT);
} else {
/* Timestamp (unused) overflow */
if (hwstatus & IS_IRQ_TIST_OV)
@@ -3000,9 +3005,6 @@ static int skge_reset(struct skge_hw *hw
skge_write32(hw, B0_IMSK, hw->intr_mask);
- if (hw->chip_id != CHIP_ID_GENESIS)
- skge_write8(hw, GMAC_IRQ_MSK, 0);
-
spin_lock_bh(&hw->phy_lock);
for (i = 0; i < hw->ports; i++) {
if (hw->chip_id == CHIP_ID_GENESIS)
@@ -3230,6 +3232,11 @@ static void __devexit skge_remove(struct
dev0 = hw->dev[0];
unregister_netdev(dev0);
+ skge_write32(hw, B0_IMSK, 0);
+ skge_write16(hw, B0_LED, LED_STAT_OFF);
+ skge_pci_clear(hw);
+ skge_write8(hw, B0_CTST, CS_RST_SET);
+
tasklet_kill(&hw->ext_tasklet);
free_irq(pdev->irq, hw);
@@ -3238,7 +3245,7 @@ static void __devexit skge_remove(struct
if (dev1)
free_netdev(dev1);
free_netdev(dev0);
- skge_write16(hw, B0_LED, LED_STAT_OFF);
+
iounmap(hw->regs);
kfree(hw);
pci_set_drvdata(pdev, NULL);
@@ -3257,7 +3264,10 @@ static int skge_suspend(struct pci_dev *
struct skge_port *skge = netdev_priv(dev);
if (netif_running(dev)) {
netif_carrier_off(dev);
- skge_down(dev);
+ if (skge->wol)
+ netif_stop_queue(dev);
+ else
+ skge_down(dev);
}
netif_device_detach(dev);
wol |= skge->wol;
diff --git a/drivers/net/skge.h b/drivers/net/skge.h
--- a/drivers/net/skge.h
+++ b/drivers/net/skge.h
@@ -2008,7 +2008,7 @@ enum {
GM_IS_RX_FF_OR = 1<<1, /* Receive FIFO Overrun */
GM_IS_RX_COMPL = 1<<0, /* Frame Reception Complete */
-#define GMAC_DEF_MSK (GM_IS_TX_CO_OV | GM_IS_RX_CO_OV | GM_IS_TX_FF_UR)
+#define GMAC_DEF_MSK (GM_IS_RX_FF_OR | GM_IS_TX_FF_UR)
/* GMAC_LINK_CTRL 16 bit GMAC Link Control Reg (YUKON only) */
/* Bits 15.. 2: reserved */
diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c
--- a/drivers/net/tulip/xircom_cb.c
+++ b/drivers/net/tulip/xircom_cb.c
@@ -117,7 +117,7 @@ static int xircom_open(struct net_device
static int xircom_close(struct net_device *dev);
static void xircom_up(struct xircom_private *card);
static struct net_device_stats *xircom_get_stats(struct net_device *dev);
-#if CONFIG_NET_POLL_CONTROLLER
+#ifdef CONFIG_NET_POLL_CONTROLLER
static void xircom_poll_controller(struct net_device *dev);
#endif
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -6852,7 +6852,10 @@ static inline char *airo_translate_scan(
/* Add frequency */
iwe.cmd = SIOCGIWFREQ;
iwe.u.freq.m = le16_to_cpu(bss->dsChannel);
- iwe.u.freq.m = frequency_list[iwe.u.freq.m] * 100000;
+ /* iwe.u.freq.m containt the channel (starting 1), our
+ * frequency_list array start at index 0...
+ */
+ iwe.u.freq.m = frequency_list[iwe.u.freq.m - 1] * 100000;
iwe.u.freq.e = 1;
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c
--- a/drivers/s390/net/ctcmain.c
+++ b/drivers/s390/net/ctcmain.c
@@ -1,5 +1,5 @@
/*
- * $Id: ctcmain.c,v 1.74 2005/03/24 09:04:17 mschwide Exp $
+ * $Id: ctcmain.c,v 1.78 2005/09/07 12:18:02 pavlic Exp $
*
* CTC / ESCON network driver
*
@@ -37,10 +37,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.74 $
+ * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.78 $
*
*/
-\f
#undef DEBUG
#include <linux/module.h>
#include <linux/init.h>
@@ -135,7 +134,7 @@ static const char *dev_event_names[] = {
"TX down",
"Restart",
};
-\f
+
/**
* Events of the channel statemachine
*/
@@ -249,7 +248,7 @@ static void
print_banner(void)
{
static int printed = 0;
- char vbuf[] = "$Revision: 1.74 $";
+ char vbuf[] = "$Revision: 1.78 $";
char *version = vbuf;
if (printed)
@@ -334,7 +333,7 @@ static const char *ch_state_names[] = {
"Restarting",
"Not operational",
};
-\f
+
#ifdef DEBUG
/**
* Dump header and first 16 bytes of an sk_buff for debugging purposes.
@@ -671,7 +670,7 @@ static void
fsm_action_nop(fsm_instance * fi, int event, void *arg)
{
}
-\f
+
/**
* Actions for channel - statemachines.
*****************************************************************************/
@@ -1514,7 +1513,6 @@ ch_action_reinit(fsm_instance *fi, int e
fsm_addtimer(&privptr->restart_timer, 1000, DEV_EVENT_RESTART, dev);
}
-\f
/**
* The statemachine for a channel.
*/
@@ -1625,7 +1623,7 @@ static const fsm_node ch_fsm[] = {
};
static const int CH_FSM_LEN = sizeof (ch_fsm) / sizeof (fsm_node);
-\f
+
/**
* Functions related to setup and device detection.
*****************************************************************************/
@@ -1976,7 +1974,7 @@ ctc_irq_handler(struct ccw_device *cdev,
fsm_event(ch->fsm, CH_EVENT_IRQ, ch);
}
-\f
+
/**
* Actions for interface - statemachine.
*****************************************************************************/
@@ -2209,13 +2207,18 @@ transmit_skb(struct channel *ch, struct
int rc = 0;
DBF_TEXT(trace, 5, __FUNCTION__);
+ /* we need to acquire the lock for testing the state
+ * otherwise we can have an IRQ changing the state to
+ * TXIDLE after the test but before acquiring the lock.
+ */
+ spin_lock_irqsave(&ch->collect_lock, saveflags);
if (fsm_getstate(ch->fsm) != CH_STATE_TXIDLE) {
int l = skb->len + LL_HEADER_LENGTH;
- spin_lock_irqsave(&ch->collect_lock, saveflags);
- if (ch->collect_len + l > ch->max_bufsize - 2)
- rc = -EBUSY;
- else {
+ if (ch->collect_len + l > ch->max_bufsize - 2) {
+ spin_unlock_irqrestore(&ch->collect_lock, saveflags);
+ return -EBUSY;
+ } else {
atomic_inc(&skb->users);
header.length = l;
header.type = skb->protocol;
@@ -2231,7 +2234,7 @@ transmit_skb(struct channel *ch, struct
int ccw_idx;
struct sk_buff *nskb;
unsigned long hi;
-
+ spin_unlock_irqrestore(&ch->collect_lock, saveflags);
/**
* Protect skb against beeing free'd by upper
* layers.
@@ -2256,6 +2259,7 @@ transmit_skb(struct channel *ch, struct
if (!nskb) {
atomic_dec(&skb->users);
skb_pull(skb, LL_HEADER_LENGTH + 2);
+ ctc_clear_busy(ch->netdev);
return -ENOMEM;
} else {
memcpy(skb_put(nskb, skb->len),
@@ -2281,6 +2285,7 @@ transmit_skb(struct channel *ch, struct
*/
atomic_dec(&skb->users);
skb_pull(skb, LL_HEADER_LENGTH + 2);
+ ctc_clear_busy(ch->netdev);
return -EBUSY;
}
@@ -2327,9 +2332,10 @@ transmit_skb(struct channel *ch, struct
}
}
+ ctc_clear_busy(ch->netdev);
return rc;
}
-\f
+
/**
* Interface API for upper network layers
*****************************************************************************/
@@ -2421,7 +2427,6 @@ ctc_tx(struct sk_buff *skb, struct net_d
dev->trans_start = jiffies;
if (transmit_skb(privptr->channel[WRITE], skb) != 0)
rc = 1;
- ctc_clear_busy(dev);
return rc;
}
@@ -2610,7 +2615,6 @@ stats_write(struct device *dev, struct d
return count;
}
-\f
static void
ctc_netdev_unregister(struct net_device * dev)
{
@@ -2685,7 +2689,6 @@ ctc_proto_store(struct device *dev, stru
return count;
}
-
static ssize_t
ctc_type_show(struct device *dev, struct device_attribute *attr, char *buf)
{
^ permalink raw reply
* Re: [git patches] net driver fixes
From: Frank Pavlic @ 2005-09-14 15:38 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev, linux-kernel
In-Reply-To: <20050914131414.GA1095@havoc.gtf.org>
Jeff ,
didn't you get the qeth patches ? let me know if not I will resend them
once again ....
Thanks
linux-kernel-owner@vger.kernel.org wrote on 14.09.2005 15:14:14:
>
> Please pull from 'upstream-fixes' branch of
> rsync://rsync.kernel.org/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git
>
> to obtain the following fixes:
>
>
> drivers/net/Kconfig | 2
> drivers/net/e100.c | 4 -
> drivers/net/e1000/e1000_main.c | 1
> drivers/net/ixgb/ixgb_main.c | 2
> drivers/net/s2io.c | 9 ++-
> drivers/net/sk98lin/skge.c | 12 ++---
> drivers/net/skge.c | 98
> ++++++++++++++++++++++-------------------
> drivers/net/skge.h | 2
> drivers/net/tulip/xircom_cb.c | 2
> drivers/net/wireless/airo.c | 5 +-
> drivers/s390/net/ctcmain.c | 41 +++++++++--------
> 11 files changed, 94 insertions(+), 84 deletions(-)
>
>
>
> Andrew Morton:
> s2io warning fixes
>
> Frank Pavlic:
> s390: ctc driver fixes
>
> John W. Linville:
> e1000: correct rx_dropped counting
> e100: correct rx_dropped and add rx_missed_errors
> ixgb: correct rx_dropped counting
>
> Keith Owens:
> Correct xircom_cb use of CONFIG_NET_POLL_CONTROLLER
>
> matthieu castet:
> airo : fix channel number in scan
>
> Stephen Hemminger:
> sk98lin: remove PCI id info for cards for conflicting devices
> skge: gmac register access errors in dual port
>
>
>
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -1951,7 +1951,7 @@ config SKGE
> ---help---
> This driver support the Marvell Yukon or SysKonnect
SK-98xx/SK-95xx
> and related Gigabit Ethernet adapters. It is a new smaller driver
> - driver with better performance and more complete ethtool support.
> + with better performance and more complete ethtool support.
>
> It does not support the link failover and network management
> features that "portable" vendor supplied sk98lin driver does.
> diff --git a/drivers/net/e100.c b/drivers/net/e100.c
> --- a/drivers/net/e100.c
> +++ b/drivers/net/e100.c
> @@ -1387,13 +1387,13 @@ static void e100_update_stats(struct nic
> ns->collisions += nic->tx_collisions;
> ns->tx_errors += le32_to_cpu(s->tx_max_collisions) +
> le32_to_cpu(s->tx_lost_crs);
> - ns->rx_dropped += le32_to_cpu(s->rx_resource_errors);
> ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) +
> nic->rx_over_length_errors;
> ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors);
> ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors);
> ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors);
> ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors);
> + ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors);
> ns->rx_errors += le32_to_cpu(s->rx_crc_errors) +
> le32_to_cpu(s->rx_alignment_errors) +
> le32_to_cpu(s->rx_short_frame_errors) +
> @@ -1727,12 +1727,10 @@ static inline int e100_rx_indicate(struc
>
> if(unlikely(!(rfd_status & cb_ok))) {
> /* Don't indicate if hardware indicates errors */
> - nic->net_stats.rx_dropped++;
> dev_kfree_skb_any(skb);
> } else if(actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) {
> /* Don't indicate oversized frames */
> nic->rx_over_length_errors++;
> - nic->net_stats.rx_dropped++;
> dev_kfree_skb_any(skb);
> } else {
> nic->net_stats.rx_packets++;
> diff --git a/drivers/net/e1000/e1000_main.c
b/drivers/net/e1000/e1000_main.c
> --- a/drivers/net/e1000/e1000_main.c
> +++ b/drivers/net/e1000/e1000_main.c
> @@ -2544,7 +2544,6 @@ e1000_update_stats(struct e1000_adapter
> adapter->stats.crcerrs + adapter->stats.algnerrc +
> adapter->stats.rlec + adapter->stats.mpc +
> adapter->stats.cexterr;
> - adapter->net_stats.rx_dropped = adapter->stats.mpc;
> adapter->net_stats.rx_length_errors = adapter->stats.rlec;
> adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs;
> adapter->net_stats.rx_frame_errors = adapter->stats.algnerrc;
> diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
> --- a/drivers/net/ixgb/ixgb_main.c
> +++ b/drivers/net/ixgb/ixgb_main.c
> @@ -1616,8 +1616,6 @@ ixgb_update_stats(struct ixgb_adapter *a
> adapter->stats.icbc +
> adapter->stats.ecbc + adapter->stats.mpc;
>
> - adapter->net_stats.rx_dropped = adapter->stats.mpc;
> -
> /* see above
> * adapter->net_stats.rx_length_errors = adapter->stats.rlec;
> */
> diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
> --- a/drivers/net/s2io.c
> +++ b/drivers/net/s2io.c
> @@ -428,7 +428,7 @@ static int init_shared_mem(struct s2io_n
> DBG_PRINT(INIT_DBG,
> "%s: Zero DMA address for TxDL. ", dev->name);
> DBG_PRINT(INIT_DBG,
> - "Virtual address %llx\n", (u64)tmp_v);
> + "Virtual address %p\n", tmp_v);
> tmp_v = pci_alloc_consistent(nic->pdev,
> PAGE_SIZE, &tmp_p);
> if (!tmp_v) {
> @@ -657,9 +657,10 @@ static void free_shared_mem(struct s2io_
> mac_control->zerodma_virt_addr,
> (dma_addr_t)0);
> DBG_PRINT(INIT_DBG,
> - "%s: Freeing TxDL with zero DMA addr. ", dev->name);
> - DBG_PRINT(INIT_DBG, "Virtual address %llx\n",
> - (u64)(mac_control->zerodma_virt_addr));
> + "%s: Freeing TxDL with zero DMA addr. ",
> + dev->name);
> + DBG_PRINT(INIT_DBG, "Virtual address %p\n",
> + mac_control->zerodma_virt_addr);
> }
> kfree(mac_control->fifos[i].list_info);
> }
> diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
> --- a/drivers/net/sk98lin/skge.c
> +++ b/drivers/net/sk98lin/skge.c
> @@ -5216,17 +5216,15 @@ static struct pci_device_id skge_pci_tbl
> { PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
> { PCI_VENDOR_ID_SYSKONNECT, 0x4300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0
},
> { PCI_VENDOR_ID_SYSKONNECT, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0
},
> - { PCI_VENDOR_ID_DLINK, 0x4c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
> +/* DLink card does not have valid VPD so this driver gags
> + * { PCI_VENDOR_ID_DLINK, 0x4c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
> + */
> { PCI_VENDOR_ID_MARVELL, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
> -#if 0 /* don't handle Yukon2 cards at the moment --
> mlindner@syskonnect.de */
> - { PCI_VENDOR_ID_MARVELL, 0x4360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
> - { PCI_VENDOR_ID_MARVELL, 0x4361, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
> -#endif
> { PCI_VENDOR_ID_MARVELL, 0x5005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
> { PCI_VENDOR_ID_CNET, 0x434e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
> - { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
> + { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015, },
> { PCI_VENDOR_ID_LINKSYS, 0x1064, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
> - { 0, }
> + { 0 }
> };
>
> MODULE_DEVICE_TABLE(pci, skge_pci_tbl);
> diff --git a/drivers/net/skge.c b/drivers/net/skge.c
> --- a/drivers/net/skge.c
> +++ b/drivers/net/skge.c
> @@ -42,7 +42,7 @@
> #include "skge.h"
>
> #define DRV_NAME "skge"
> -#define DRV_VERSION "0.9"
> +#define DRV_VERSION "1.0"
> #define PFX DRV_NAME " "
>
> #define DEFAULT_TX_RING_SIZE 128
> @@ -669,7 +669,7 @@ static void skge_led(struct skge_port *s
> PHY_M_LED_BLINK_RT(BLINK_84MS) |
> PHY_M_LEDC_TX_CTRL |
> PHY_M_LEDC_DP_CTRL);
> -
> +
> gm_phy_write(hw, port, PHY_MARV_LED_OVER,
> PHY_M_LED_MO_RX(MO_LED_OFF) |
> (skge->speed == SPEED_100 ?
> @@ -876,7 +876,7 @@ static int skge_rx_fill(struct skge_port
>
> static void skge_link_up(struct skge_port *skge)
> {
> - skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG),
> + skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG),
> LED_BLK_OFF|LED_SYNC_OFF|LED_ON);
>
> netif_carrier_on(skge->netdev);
> @@ -987,6 +987,8 @@ static void genesis_reset(struct skge_hw
> {
> const u8 zero[8] = { 0 };
>
> + skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0);
> +
> /* reset the statistics module */
> xm_write32(hw, port, XM_GP_PORT, XM_GP_RES_STAT);
> xm_write16(hw, port, XM_IMSK, 0xffff); /* disable XMAC IRQs */
> @@ -1021,8 +1023,6 @@ static void bcom_check_link(struct skge_
> (void) xm_phy_read(hw, port, PHY_BCOM_STAT);
> status = xm_phy_read(hw, port, PHY_BCOM_STAT);
>
> - pr_debug("bcom_check_link status=0x%x\n", status);
> -
> if ((status & PHY_ST_LSYNC) == 0) {
> u16 cmd = xm_read16(hw, port, XM_MMU_CMD);
> cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX);
> @@ -1106,8 +1106,6 @@ static void bcom_phy_init(struct skge_po
> { 0x17, 0x0013 }, { 0x15, 0x0A04 }, { 0x18, 0x0420 },
> };
>
> - pr_debug("bcom_phy_init\n");
> -
> /* read Id from external PHY (all have the same address) */
> id1 = xm_phy_read(hw, port, PHY_XMAC_ID1);
>
> @@ -1340,6 +1338,8 @@ static void genesis_stop(struct skge_por
> int port = skge->port;
> u32 reg;
>
> + genesis_reset(hw, port);
> +
> /* Clear Tx packet arbiter timeout IRQ */
> skge_write16(hw, B3_PA_CTRL,
> port == 0 ? PA_CLR_TO_TX1 : PA_CLR_TO_TX2);
> @@ -1465,7 +1465,6 @@ static void genesis_link_up(struct skge_
> u16 cmd;
> u32 mode, msk;
>
> - pr_debug("genesis_link_up\n");
> cmd = xm_read16(hw, port, XM_MMU_CMD);
>
> /*
> @@ -1578,7 +1577,6 @@ static void yukon_init(struct skge_hw *h
> struct skge_port *skge = netdev_priv(hw->dev[port]);
> u16 ctrl, ct1000, adv;
>
> - pr_debug("yukon_init\n");
> if (skge->autoneg == AUTONEG_ENABLE) {
> u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL);
>
> @@ -1677,9 +1675,11 @@ static void yukon_mac_init(struct skge_h
>
> /* WA code for COMA mode -- set PHY reset */
> if (hw->chip_id == CHIP_ID_YUKON_LITE &&
> - hw->chip_rev >= CHIP_REV_YU_LITE_A3)
> - skge_write32(hw, B2_GP_IO,
> - (skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9));
> + hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
> + reg = skge_read32(hw, B2_GP_IO);
> + reg |= GP_DIR_9 | GP_IO_9;
> + skge_write32(hw, B2_GP_IO, reg);
> + }
>
> /* hard reset */
> skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
> @@ -1687,10 +1687,12 @@ static void yukon_mac_init(struct skge_h
>
> /* WA code for COMA mode -- clear PHY reset */
> if (hw->chip_id == CHIP_ID_YUKON_LITE &&
> - hw->chip_rev >= CHIP_REV_YU_LITE_A3)
> - skge_write32(hw, B2_GP_IO,
> - (skge_read32(hw, B2_GP_IO) | GP_DIR_9)
> - & ~GP_IO_9);
> + hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
> + reg = skge_read32(hw, B2_GP_IO);
> + reg |= GP_DIR_9;
> + reg &= ~GP_IO_9;
> + skge_write32(hw, B2_GP_IO, reg);
> + }
>
> /* Set hardware config mode */
> reg = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP |
> @@ -1729,7 +1731,7 @@ static void yukon_mac_init(struct skge_h
> }
>
> gma_write16(hw, port, GM_GP_CTRL, reg);
> - skge_read16(hw, GMAC_IRQ_SRC);
> + skge_read16(hw, SK_REG(port, GMAC_IRQ_SRC));
>
> yukon_init(hw, port);
>
> @@ -1801,20 +1803,26 @@ static void yukon_stop(struct skge_port
> struct skge_hw *hw = skge->hw;
> int port = skge->port;
>
> - if (hw->chip_id == CHIP_ID_YUKON_LITE &&
> - hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
> - skge_write32(hw, B2_GP_IO,
> - skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9);
> - }
> + skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0);
> + yukon_reset(hw, port);
>
> gma_write16(hw, port, GM_GP_CTRL,
> gma_read16(hw, port, GM_GP_CTRL)
> & ~(GM_GPCR_TX_ENA|GM_GPCR_RX_ENA));
> gma_read16(hw, port, GM_GP_CTRL);
>
> + if (hw->chip_id == CHIP_ID_YUKON_LITE &&
> + hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
> + u32 io = skge_read32(hw, B2_GP_IO);
> +
> + io |= GP_DIR_9 | GP_IO_9;
> + skge_write32(hw, B2_GP_IO, io);
> + skge_read32(hw, B2_GP_IO);
> + }
> +
> /* set GPHY Control reset */
> - skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
> - skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET);
> + skge_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
> + skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET);
> }
>
> static void yukon_get_stats(struct skge_port *skge, u64 *data)
> @@ -1873,10 +1881,8 @@ static void yukon_link_up(struct skge_po
> int port = skge->port;
> u16 reg;
>
> - pr_debug("yukon_link_up\n");
> -
> /* Enable Transmit FIFO Underrun */
> - skge_write8(hw, GMAC_IRQ_MSK, GMAC_DEF_MSK);
> + skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), GMAC_DEF_MSK);
>
> reg = gma_read16(hw, port, GM_GP_CTRL);
> if (skge->duplex == DUPLEX_FULL || skge->autoneg == AUTONEG_ENABLE)
> @@ -1896,7 +1902,6 @@ static void yukon_link_down(struct skge_
> int port = skge->port;
> u16 ctrl;
>
> - pr_debug("yukon_link_down\n");
> gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);
>
> ctrl = gma_read16(hw, port, GM_GP_CTRL);
> @@ -2112,7 +2117,6 @@ static int skge_up(struct net_device *de
> skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START |
CSR_IRQ_CL_F);
> skge_led(skge, LED_MODE_ON);
>
> - pr_debug("skge_up completed\n");
> return 0;
>
> free_rx_ring:
> @@ -2135,15 +2139,20 @@ static int skge_down(struct net_device *
>
> netif_stop_queue(dev);
>
> + skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
> + if (hw->chip_id == CHIP_ID_GENESIS)
> + genesis_stop(skge);
> + else
> + yukon_stop(skge);
> +
> + hw->intr_mask &= ~portirqmask[skge->port];
> + skge_write32(hw, B0_IMSK, hw->intr_mask);
> +
> /* Stop transmitter */
> skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP);
> skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL),
> RB_RST_SET|RB_DIS_OP_MD);
>
> - if (hw->chip_id == CHIP_ID_GENESIS)
> - genesis_stop(skge);
> - else
> - yukon_stop(skge);
>
> /* Disable Force Sync bit and Enable Alloc bit */
> skge_write8(hw, SK_REG(port, TXA_CTRL),
> @@ -2367,8 +2376,6 @@ static void genesis_set_multicast(struct
> u32 mode;
> u8 filter[8];
>
> - pr_debug("genesis_set_multicast flags=%x count=%d\n",
> dev->flags, dev->mc_count);
> -
> mode = xm_read32(hw, port, XM_MODE);
> mode |= XM_MD_ENA_HASH;
> if (dev->flags & IFF_PROMISC)
> @@ -2530,8 +2537,6 @@ static int skge_poll(struct net_device *
> unsigned int to_do = min(dev->quota, *budget);
> unsigned int work_done = 0;
>
> - pr_debug("skge_poll\n");
> -
> for (e = ring->to_clean; work_done < to_do; e = e->next) {
> struct skge_rx_desc *rd = e->desc;
> struct sk_buff *skb;
> @@ -2672,9 +2677,9 @@ static void skge_error_irq(struct skge_h
> if (hw->chip_id == CHIP_ID_GENESIS) {
> /* clear xmac errors */
> if (hwstatus & (IS_NO_STAT_M1|IS_NO_TIST_M1))
> - skge_write16(hw, SK_REG(0, RX_MFF_CTRL1), MFF_CLR_INSTAT);
> + skge_write16(hw, RX_MFF_CTRL1, MFF_CLR_INSTAT);
> if (hwstatus & (IS_NO_STAT_M2|IS_NO_TIST_M2))
> - skge_write16(hw, SK_REG(0, RX_MFF_CTRL2), MFF_CLR_INSTAT);
> + skge_write16(hw, RX_MFF_CTRL2, MFF_CLR_INSTAT);
> } else {
> /* Timestamp (unused) overflow */
> if (hwstatus & IS_IRQ_TIST_OV)
> @@ -3000,9 +3005,6 @@ static int skge_reset(struct skge_hw *hw
>
> skge_write32(hw, B0_IMSK, hw->intr_mask);
>
> - if (hw->chip_id != CHIP_ID_GENESIS)
> - skge_write8(hw, GMAC_IRQ_MSK, 0);
> -
> spin_lock_bh(&hw->phy_lock);
> for (i = 0; i < hw->ports; i++) {
> if (hw->chip_id == CHIP_ID_GENESIS)
> @@ -3230,6 +3232,11 @@ static void __devexit skge_remove(struct
> dev0 = hw->dev[0];
> unregister_netdev(dev0);
>
> + skge_write32(hw, B0_IMSK, 0);
> + skge_write16(hw, B0_LED, LED_STAT_OFF);
> + skge_pci_clear(hw);
> + skge_write8(hw, B0_CTST, CS_RST_SET);
> +
> tasklet_kill(&hw->ext_tasklet);
>
> free_irq(pdev->irq, hw);
> @@ -3238,7 +3245,7 @@ static void __devexit skge_remove(struct
> if (dev1)
> free_netdev(dev1);
> free_netdev(dev0);
> - skge_write16(hw, B0_LED, LED_STAT_OFF);
> +
> iounmap(hw->regs);
> kfree(hw);
> pci_set_drvdata(pdev, NULL);
> @@ -3257,7 +3264,10 @@ static int skge_suspend(struct pci_dev *
> struct skge_port *skge = netdev_priv(dev);
> if (netif_running(dev)) {
> netif_carrier_off(dev);
> - skge_down(dev);
> + if (skge->wol)
> + netif_stop_queue(dev);
> + else
> + skge_down(dev);
> }
> netif_device_detach(dev);
> wol |= skge->wol;
> diff --git a/drivers/net/skge.h b/drivers/net/skge.h
> --- a/drivers/net/skge.h
> +++ b/drivers/net/skge.h
> @@ -2008,7 +2008,7 @@ enum {
> GM_IS_RX_FF_OR = 1<<1, /* Receive FIFO Overrun */
> GM_IS_RX_COMPL = 1<<0, /* Frame Reception Complete */
>
> -#define GMAC_DEF_MSK (GM_IS_TX_CO_OV | GM_IS_RX_CO_OV |
GM_IS_TX_FF_UR)
> +#define GMAC_DEF_MSK (GM_IS_RX_FF_OR | GM_IS_TX_FF_UR)
>
> /* GMAC_LINK_CTRL 16 bit GMAC Link Control Reg (YUKON only) */
> /* Bits 15.. 2: reserved */
> diff --git a/drivers/net/tulip/xircom_cb.c
b/drivers/net/tulip/xircom_cb.c
> --- a/drivers/net/tulip/xircom_cb.c
> +++ b/drivers/net/tulip/xircom_cb.c
> @@ -117,7 +117,7 @@ static int xircom_open(struct net_device
> static int xircom_close(struct net_device *dev);
> static void xircom_up(struct xircom_private *card);
> static struct net_device_stats *xircom_get_stats(struct net_device
*dev);
> -#if CONFIG_NET_POLL_CONTROLLER
> +#ifdef CONFIG_NET_POLL_CONTROLLER
> static void xircom_poll_controller(struct net_device *dev);
> #endif
>
> diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
> --- a/drivers/net/wireless/airo.c
> +++ b/drivers/net/wireless/airo.c
> @@ -6852,7 +6852,10 @@ static inline char *airo_translate_scan(
> /* Add frequency */
> iwe.cmd = SIOCGIWFREQ;
> iwe.u.freq.m = le16_to_cpu(bss->dsChannel);
> - iwe.u.freq.m = frequency_list[iwe.u.freq.m] * 100000;
> + /* iwe.u.freq.m containt the channel (starting 1), our
> + * frequency_list array start at index 0...
> + */
> + iwe.u.freq.m = frequency_list[iwe.u.freq.m - 1] * 100000;
> iwe.u.freq.e = 1;
> current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
> IW_EV_FREQ_LEN);
>
> diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c
> --- a/drivers/s390/net/ctcmain.c
> +++ b/drivers/s390/net/ctcmain.c
> @@ -1,5 +1,5 @@
> /*
> - * $Id: ctcmain.c,v 1.74 2005/03/24 09:04:17 mschwide Exp $
> + * $Id: ctcmain.c,v 1.78 2005/09/07 12:18:02 pavlic Exp $
> *
> * CTC / ESCON network driver
> *
> @@ -37,10 +37,9 @@
> * along with this program; if not, write to the Free Software
> * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> *
> - * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.74 $
> + * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.78 $
> *
> */
> -\f
> #undef DEBUG
> #include <linux/module.h>
> #include <linux/init.h>
> @@ -135,7 +134,7 @@ static const char *dev_event_names[] = {
> "TX down",
> "Restart",
> };
> -\f
> +
> /**
> * Events of the channel statemachine
> */
> @@ -249,7 +248,7 @@ static void
> print_banner(void)
> {
> static int printed = 0;
> - char vbuf[] = "$Revision: 1.74 $";
> + char vbuf[] = "$Revision: 1.78 $";
> char *version = vbuf;
>
> if (printed)
> @@ -334,7 +333,7 @@ static const char *ch_state_names[] = {
> "Restarting",
> "Not operational",
> };
> -\f
> +
> #ifdef DEBUG
> /**
> * Dump header and first 16 bytes of an sk_buff for debugging purposes.
> @@ -671,7 +670,7 @@ static void
> fsm_action_nop(fsm_instance * fi, int event, void *arg)
> {
> }
> -\f
> +
> /**
> * Actions for channel - statemachines.
>
>
*****************************************************************************/
> @@ -1514,7 +1513,6 @@ ch_action_reinit(fsm_instance *fi, int e
> fsm_addtimer(&privptr->restart_timer, 1000, DEV_EVENT_RESTART,
dev);
> }
>
> -\f
> /**
> * The statemachine for a channel.
> */
> @@ -1625,7 +1623,7 @@ static const fsm_node ch_fsm[] = {
> };
>
> static const int CH_FSM_LEN = sizeof (ch_fsm) / sizeof (fsm_node);
> -\f
> +
> /**
> * Functions related to setup and device detection.
>
>
*****************************************************************************/
> @@ -1976,7 +1974,7 @@ ctc_irq_handler(struct ccw_device *cdev,
> fsm_event(ch->fsm, CH_EVENT_IRQ, ch);
>
> }
> -\f
> +
> /**
> * Actions for interface - statemachine.
>
>
*****************************************************************************/
> @@ -2209,13 +2207,18 @@ transmit_skb(struct channel *ch, struct
> int rc = 0;
>
> DBF_TEXT(trace, 5, __FUNCTION__);
> + /* we need to acquire the lock for testing the state
> + * otherwise we can have an IRQ changing the state to
> + * TXIDLE after the test but before acquiring the lock.
> + */
> + spin_lock_irqsave(&ch->collect_lock, saveflags);
> if (fsm_getstate(ch->fsm) != CH_STATE_TXIDLE) {
> int l = skb->len + LL_HEADER_LENGTH;
>
> - spin_lock_irqsave(&ch->collect_lock, saveflags);
> - if (ch->collect_len + l > ch->max_bufsize - 2)
> - rc = -EBUSY;
> - else {
> + if (ch->collect_len + l > ch->max_bufsize - 2) {
> + spin_unlock_irqrestore(&ch->collect_lock, saveflags);
> + return -EBUSY;
> + } else {
> atomic_inc(&skb->users);
> header.length = l;
> header.type = skb->protocol;
> @@ -2231,7 +2234,7 @@ transmit_skb(struct channel *ch, struct
> int ccw_idx;
> struct sk_buff *nskb;
> unsigned long hi;
> -
> + spin_unlock_irqrestore(&ch->collect_lock, saveflags);
> /**
> * Protect skb against beeing free'd by upper
> * layers.
> @@ -2256,6 +2259,7 @@ transmit_skb(struct channel *ch, struct
> if (!nskb) {
> atomic_dec(&skb->users);
> skb_pull(skb, LL_HEADER_LENGTH + 2);
> + ctc_clear_busy(ch->netdev);
> return -ENOMEM;
> } else {
> memcpy(skb_put(nskb, skb->len),
> @@ -2281,6 +2285,7 @@ transmit_skb(struct channel *ch, struct
> */
> atomic_dec(&skb->users);
> skb_pull(skb, LL_HEADER_LENGTH + 2);
> + ctc_clear_busy(ch->netdev);
> return -EBUSY;
> }
>
> @@ -2327,9 +2332,10 @@ transmit_skb(struct channel *ch, struct
> }
> }
>
> + ctc_clear_busy(ch->netdev);
> return rc;
> }
> -\f
> +
> /**
> * Interface API for upper network layers
>
>
*****************************************************************************/
> @@ -2421,7 +2427,6 @@ ctc_tx(struct sk_buff *skb, struct net_d
> dev->trans_start = jiffies;
> if (transmit_skb(privptr->channel[WRITE], skb) != 0)
> rc = 1;
> - ctc_clear_busy(dev);
> return rc;
> }
>
> @@ -2610,7 +2615,6 @@ stats_write(struct device *dev, struct d
> return count;
> }
>
> -\f
> static void
> ctc_netdev_unregister(struct net_device * dev)
> {
> @@ -2685,7 +2689,6 @@ ctc_proto_store(struct device *dev, stru
> return count;
> }
>
> -
> static ssize_t
> ctc_type_show(struct device *dev, struct device_attribute *attr, char
*buf)
> {
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel"
in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
^ permalink raw reply
* Re: [PATCH 1/3] orinoco: WE-18 support
From: Pavel Roskin @ 2005-09-14 15:39 UTC (permalink / raw)
To: Jeff Garzik
Cc: Orinoco Development List, netdev-u79uwXL29TY76Z2rM5mHXA,
Jean Tourrilhes
In-Reply-To: <43281824.7000705-e+AXbWqSrlAAvxtiuMwx3w@public.gmane.org>
On Wed, 2005-09-14 at 08:31 -0400, Jeff Garzik wrote:
> Pavel Roskin wrote:
> > Author: Jean Tourrilhes <jt-sDzT885Ts8HQT0dZR+AlfA@public.gmane.org>
> > Signed-off-by: Pavel Roskin <proski-mXXj517/zsQ@public.gmane.org>
> >
> > Use new Wireless Extension API for wireless stats.
>
> Applied patch #1, the rest failed:
Thanks! The rest will be resubmitted shortly.
--
Regards,
Pavel Roskin
-------------------------------------------------------
SF.Net email is sponsored by:
Tame your development challenges with Apache's Geronimo App Server.
Download it for free - -and be entered to win a 42" plasma tv or your very
own Sony(tm)PSP. Click here to play: http://sourceforge.net/geronimo.php
^ permalink raw reply
* Re: [git patches] net driver fixes
From: Jeff Garzik @ 2005-09-14 15:40 UTC (permalink / raw)
To: Frank Pavlic; +Cc: netdev, linux-kernel
In-Reply-To: <OFA34209F3.7B24497C-ONC125707C.0056132C-C125707C.0056326B@de.ibm.com>
On Wed, Sep 14, 2005 at 05:38:26PM +0200, Frank Pavlic wrote:
> Jeff ,
> didn't you get the qeth patches ? let me know if not I will resend them
> once again ....
You only resent patch #2, so please do resend patches 3 and 4.
Thanks,
Jeff
^ permalink raw reply
* [patch 3/4] s390: TSO related fixes in qeth driver
From: Frank Pavlic @ 2005-09-14 16:03 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linux-kernel
Jeff,
I'm sorry seems that they have not been sent out either ...
ok here they come ...
[patch 3/4] s390: TSO related fixes in qeth driver
From: Frank Pavlic <pavlic@de.ibm.com>
TSO related fixes :
- changing value of large_send attribute while network traffic
is running caused program check and thus device recovery.
- Due to hardware restriction discard packet when it exceeds 60K
otherwise qeth will cause program checks and thus traffic stall
when trying to send such huge packets.
Signed-off-by: Frank Pavlic <pavlic@de.ibm.com>
diffstat:
qeth.h | 4 ++--
qeth_main.c | 33 +++++++++++++++++++++------------
qeth_sys.c | 10 +++-------
3 files changed, 26 insertions(+), 21 deletions(-)
diff -Naupr linux-2.6-orig/drivers/s390/net/qeth.h linux-2.6-patched/drivers/s390/net/qeth.h
--- linux-2.6-orig/drivers/s390/net/qeth.h 2005-09-05 11:46:56.000000000 +0200
+++ linux-2.6-patched/drivers/s390/net/qeth.h 2005-09-05 12:16:08.000000000 +0200
@@ -24,7 +24,7 @@
#include "qeth_mpc.h"
-#define VERSION_QETH_H "$Revision: 1.139 $"
+#define VERSION_QETH_H "$Revision: 1.141 $"
#ifdef CONFIG_QETH_IPV6
#define QETH_VERSION_IPV6 ":IPv6"
@@ -1172,7 +1172,7 @@ extern int
qeth_realloc_buffer_pool(struct qeth_card *, int);
extern int
-qeth_set_large_send(struct qeth_card *);
+qeth_set_large_send(struct qeth_card *, enum qeth_large_send_types);
extern void
qeth_fill_header(struct qeth_card *, struct qeth_hdr *,
diff -Naupr linux-2.6-orig/drivers/s390/net/qeth_main.c linux-2.6-patched/drivers/s390/net/qeth_main.c
--- linux-2.6-orig/drivers/s390/net/qeth_main.c 2005-09-05 11:46:56.000000000 +0200
+++ linux-2.6-patched/drivers/s390/net/qeth_main.c 2005-09-05 12:17:38.000000000 +0200
@@ -1,6 +1,6 @@
/*
*
- * linux/drivers/s390/net/qeth_main.c ($Revision: 1.214 $)
+ * linux/drivers/s390/net/qeth_main.c ($Revision: 1.219 $)
*
* Linux on zSeries OSA Express and HiperSockets support
*
@@ -12,7 +12,7 @@
* Frank Pavlic (pavlic@de.ibm.com) and
* Thomas Spatzier <tspat@de.ibm.com>
*
- * $Revision: 1.214 $ $Date: 2005/05/04 20:19:18 $
+ * $Revision: 1.219 $ $Date: 2005/05/04 20:19:18 $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -80,7 +80,7 @@ qeth_eyecatcher(void)
#include "qeth_eddp.h"
#include "qeth_tso.h"
-#define VERSION_QETH_C "$Revision: 1.214 $"
+#define VERSION_QETH_C "$Revision: 1.219 $"
static const char *version = "qeth S/390 OSA-Express driver";
/**
@@ -3795,12 +3795,16 @@ static inline int
qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb,
struct qeth_hdr **hdr, int ipv)
{
+ int rc;
#ifdef CONFIG_QETH_VLAN
u16 *tag;
#endif
QETH_DBF_TEXT(trace, 6, "prepskb");
+ rc = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr));
+ if (rc)
+ return rc;
#ifdef CONFIG_QETH_VLAN
if (card->vlangrp && vlan_tx_tag_present(*skb) &&
((ipv == 6) || card->options.layer2) ) {
@@ -4251,7 +4255,8 @@ out:
}
static inline int
-qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb)
+qeth_get_elements_no(struct qeth_card *card, void *hdr,
+ struct sk_buff *skb, int elems)
{
int elements_needed = 0;
@@ -4261,9 +4266,10 @@ qeth_get_elements_no(struct qeth_card *c
if (elements_needed == 0 )
elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE)
+ skb->len) >> PAGE_SHIFT);
- if (elements_needed > QETH_MAX_BUFFER_ELEMENTS(card)){
+ if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)){
PRINT_ERR("qeth_do_send_packet: invalid size of "
- "IP packet. Discarded.");
+ "IP packet (Number=%d / Length=%d). Discarded.\n",
+ (elements_needed+elems), skb->len);
return 0;
}
return elements_needed;
@@ -4337,9 +4343,11 @@ qeth_send_packet(struct qeth_card *card,
return -EINVAL;
}
} else {
- elements_needed += qeth_get_elements_no(card,(void*) hdr, skb);
- if (!elements_needed)
+ int elems = qeth_get_elements_no(card,(void*) hdr, skb,
+ elements_needed);
+ if (!elems)
return -EINVAL;
+ elements_needed += elems;
}
if (card->info.type != QETH_CARD_TYPE_IQD)
@@ -7038,14 +7046,16 @@ qeth_setrouting_v6(struct qeth_card *car
}
int
-qeth_set_large_send(struct qeth_card *card)
+qeth_set_large_send(struct qeth_card *card, enum qeth_large_send_types type)
{
int rc = 0;
- if (card->dev == NULL)
+ if (card->dev == NULL) {
+ card->options.large_send = type;
return 0;
-
+ }
netif_stop_queue(card->dev);
+ card->options.large_send = type;
switch (card->options.large_send) {
case QETH_LARGE_SEND_EDDP:
card->dev->features |= NETIF_F_TSO | NETIF_F_SG;
@@ -7066,7 +7076,6 @@ qeth_set_large_send(struct qeth_card *ca
card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG);
break;
}
-
netif_wake_queue(card->dev);
return rc;
}
diff -Naupr linux-2.6-orig/drivers/s390/net/qeth_sys.c linux-2.6-patched/drivers/s390/net/qeth_sys.c
--- linux-2.6-orig/drivers/s390/net/qeth_sys.c 2005-09-05 11:46:56.000000000 +0200
+++ linux-2.6-patched/drivers/s390/net/qeth_sys.c 2005-09-05 12:14:30.000000000 +0200
@@ -1,6 +1,6 @@
/*
*
- * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.51 $)
+ * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.53 $)
*
* Linux on zSeries OSA Express and HiperSockets support
* This file contains code related to sysfs.
@@ -20,7 +20,7 @@
#include "qeth_mpc.h"
#include "qeth_fs.h"
-const char *VERSION_QETH_SYS_C = "$Revision: 1.51 $";
+const char *VERSION_QETH_SYS_C = "$Revision: 1.53 $";
/*****************************************************************************/
/* */
@@ -771,9 +771,7 @@ qeth_dev_large_send_store(struct device
if (!card)
return -EINVAL;
-
tmp = strsep((char **) &buf, "\n");
-
if (!strcmp(tmp, "no")){
type = QETH_LARGE_SEND_NO;
} else if (!strcmp(tmp, "EDDP")) {
@@ -786,10 +784,8 @@ qeth_dev_large_send_store(struct device
}
if (card->options.large_send == type)
return count;
- card->options.large_send = type;
- if ((rc = qeth_set_large_send(card)))
+ if ((rc = qeth_set_large_send(card, type)))
return rc;
-
return count;
}
^ permalink raw reply
* [patch 4/4] s390: qeth driver fixes
From: Frank Pavlic @ 2005-09-14 16:05 UTC (permalink / raw)
To: jgarzik; +Cc: linux-kernel, netdev
[patch 4/4] s390: qeth driver fixes .
From: Frank Pavlic <pavlic@de.ibm.com>
- Clear read channel first prior to using ccw_device_set_offline.
- use QETH_DBF_TEXT instead of QETH_DBF_SPRINTF
- invoke qeth_halt_channel and qeth_clear_channel for all channels,
even if halt/clear for one of the channel fails.
- enable qeth_arp_query function for GuestLAN devices
Signed-off-by: Frank Pavlic <pavlic@de.ibm.com>
diffstat:
qeth.h | 2 -
qeth_main.c | 106 +++++++++++++++++++++++++-----------------------------------
qeth_sys.c | 11 +++---
3 files changed, 53 insertions(+), 66 deletions(-)
diff -Naupr linux-2.6-orig/drivers/s390/net/qeth.h linux-2.6-patched/drivers/s390/net/qeth.h
--- linux-2.6-orig/drivers/s390/net/qeth.h 2005-09-05 13:53:40.000000000 +0200
+++ linux-2.6-patched/drivers/s390/net/qeth.h 2005-09-05 14:00:46.000000000 +0200
@@ -24,7 +24,7 @@
#include "qeth_mpc.h"
-#define VERSION_QETH_H "$Revision: 1.141 $"
+#define VERSION_QETH_H "$Revision: 1.142 $"
#ifdef CONFIG_QETH_IPV6
#define QETH_VERSION_IPV6 ":IPv6"
diff -Naupr linux-2.6-orig/drivers/s390/net/qeth_main.c linux-2.6-patched/drivers/s390/net/qeth_main.c
--- linux-2.6-orig/drivers/s390/net/qeth_main.c 2005-09-05 13:53:40.000000000 +0200
+++ linux-2.6-patched/drivers/s390/net/qeth_main.c 2005-09-05 14:05:43.000000000 +0200
@@ -1,6 +1,6 @@
/*
*
- * linux/drivers/s390/net/qeth_main.c ($Revision: 1.219 $)
+ * linux/drivers/s390/net/qeth_main.c ($Revision: 1.224 $)
*
* Linux on zSeries OSA Express and HiperSockets support
*
@@ -12,7 +12,7 @@
* Frank Pavlic (pavlic@de.ibm.com) and
* Thomas Spatzier <tspat@de.ibm.com>
*
- * $Revision: 1.219 $ $Date: 2005/05/04 20:19:18 $
+ * $Revision: 1.224 $ $Date: 2005/05/04 20:19:18 $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -29,14 +29,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/***
- * eye catcher; just for debugging purposes
- */
-void volatile
-qeth_eyecatcher(void)
-{
- return;
-}
#include <linux/config.h>
#include <linux/module.h>
@@ -80,7 +72,7 @@ qeth_eyecatcher(void)
#include "qeth_eddp.h"
#include "qeth_tso.h"
-#define VERSION_QETH_C "$Revision: 1.219 $"
+#define VERSION_QETH_C "$Revision: 1.224 $"
static const char *version = "qeth S/390 OSA-Express driver";
/**
@@ -2759,11 +2751,9 @@ qeth_flush_buffers(struct qeth_qdio_out_
queue->card->perf_stats.outbound_do_qdio_start_time;
#endif
if (rc){
- QETH_DBF_SPRINTF(trace, 0, "qeth_flush_buffers: do_QDIO "
- "returned error (%i) on device %s.",
- rc, CARD_DDEV_ID(queue->card));
QETH_DBF_TEXT(trace, 2, "flushbuf");
QETH_DBF_TEXT_(trace, 2, " err%d", rc);
+ QETH_DBF_TEXT_(trace, 2, "%s", CARD_DDEV_ID(queue->card));
queue->card->stats.tx_errors += count;
/* this must not happen under normal circumstances. if it
* happens something is really wrong -> recover */
@@ -2909,11 +2899,8 @@ qeth_qdio_output_handler(struct ccw_devi
QETH_DBF_TEXT(trace, 6, "qdouhdl");
if (status & QDIO_STATUS_LOOK_FOR_ERROR) {
if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){
- QETH_DBF_SPRINTF(trace, 2, "On device %s: "
- "received active check "
- "condition (0x%08x).",
- CARD_BUS_ID(card), status);
- QETH_DBF_TEXT(trace, 2, "chkcond");
+ QETH_DBF_TEXT(trace, 2, "achkcond");
+ QETH_DBF_TEXT_(trace, 2, "%s", CARD_BUS_ID(card));
QETH_DBF_TEXT_(trace, 2, "%08x", status);
netif_stop_queue(card->dev);
qeth_schedule_recovery(card);
@@ -3356,26 +3343,32 @@ qeth_halt_channel(struct qeth_channel *c
static int
qeth_halt_channels(struct qeth_card *card)
{
- int rc = 0;
+ int rc1 = 0, rc2=0, rc3 = 0;
QETH_DBF_TEXT(trace,3,"haltchs");
- if ((rc = qeth_halt_channel(&card->read)))
- return rc;
- if ((rc = qeth_halt_channel(&card->write)))
- return rc;
- return qeth_halt_channel(&card->data);
+ rc1 = qeth_halt_channel(&card->read);
+ rc2 = qeth_halt_channel(&card->write);
+ rc3 = qeth_halt_channel(&card->data);
+ if (rc1)
+ return rc1;
+ if (rc2)
+ return rc2;
+ return rc3;
}
static int
qeth_clear_channels(struct qeth_card *card)
{
- int rc = 0;
+ int rc1 = 0, rc2=0, rc3 = 0;
QETH_DBF_TEXT(trace,3,"clearchs");
- if ((rc = qeth_clear_channel(&card->read)))
- return rc;
- if ((rc = qeth_clear_channel(&card->write)))
- return rc;
- return qeth_clear_channel(&card->data);
+ rc1 = qeth_clear_channel(&card->read);
+ rc2 = qeth_clear_channel(&card->write);
+ rc3 = qeth_clear_channel(&card->data);
+ if (rc1)
+ return rc1;
+ if (rc2)
+ return rc2;
+ return rc3;
}
static int
@@ -3445,23 +3438,23 @@ qeth_mpc_initialize(struct qeth_card *ca
}
if ((rc = qeth_cm_enable(card))){
QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
- return rc;
+ goto out_qdio;
}
if ((rc = qeth_cm_setup(card))){
QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
- return rc;
+ goto out_qdio;
}
if ((rc = qeth_ulp_enable(card))){
QETH_DBF_TEXT_(setup, 2, "4err%d", rc);
- return rc;
+ goto out_qdio;
}
if ((rc = qeth_ulp_setup(card))){
QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
- return rc;
+ goto out_qdio;
}
if ((rc = qeth_alloc_qdio_buffers(card))){
QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
- return rc;
+ goto out_qdio;
}
if ((rc = qeth_qdio_establish(card))){
QETH_DBF_TEXT_(setup, 2, "6err%d", rc);
@@ -4281,7 +4274,7 @@ qeth_send_packet(struct qeth_card *card,
int ipv = 0;
int cast_type;
struct qeth_qdio_out_q *queue;
- struct qeth_hdr *hdr;
+ struct qeth_hdr *hdr = NULL;
int elements_needed = 0;
enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO;
struct qeth_eddp_context *ctx = NULL;
@@ -4512,7 +4505,11 @@ qeth_arp_set_no_entries(struct qeth_card
QETH_DBF_TEXT(trace,3,"arpstnoe");
- /* TODO: really not supported by GuestLAN? */
+ /*
+ * currently GuestLAN only supports the ARP assist function
+ * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_SET_NO_ENTRIES;
+ * thus we say EOPNOTSUPP for this ARP function
+ */
if (card->info.guestlan)
return -EOPNOTSUPP;
if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) {
@@ -4689,14 +4686,6 @@ qeth_arp_query(struct qeth_card *card, c
QETH_DBF_TEXT(trace,3,"arpquery");
- /*
- * currently GuestLAN does only deliver all zeros on query arp,
- * even though arp processing is supported (according to IPA supp.
- * funcs flags); since all zeros is no valueable information,
- * we say EOPNOTSUPP for all ARP functions
- */
- /*if (card->info.guestlan)
- return -EOPNOTSUPP; */
if (!qeth_is_supported(card,/*IPA_QUERY_ARP_ADDR_INFO*/
IPA_ARP_PROCESSING)) {
PRINT_WARN("ARP processing not supported "
@@ -4902,10 +4891,9 @@ qeth_arp_add_entry(struct qeth_card *car
QETH_DBF_TEXT(trace,3,"arpadent");
/*
- * currently GuestLAN does only deliver all zeros on query arp,
- * even though arp processing is supported (according to IPA supp.
- * funcs flags); since all zeros is no valueable information,
- * we say EOPNOTSUPP for all ARP functions
+ * currently GuestLAN only supports the ARP assist function
+ * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_ADD_ENTRY;
+ * thus we say EOPNOTSUPP for this ARP function
*/
if (card->info.guestlan)
return -EOPNOTSUPP;
@@ -4945,10 +4933,9 @@ qeth_arp_remove_entry(struct qeth_card *
QETH_DBF_TEXT(trace,3,"arprment");
/*
- * currently GuestLAN does only deliver all zeros on query arp,
- * even though arp processing is supported (according to IPA supp.
- * funcs flags); since all zeros is no valueable information,
- * we say EOPNOTSUPP for all ARP functions
+ * currently GuestLAN only supports the ARP assist function
+ * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_REMOVE_ENTRY;
+ * thus we say EOPNOTSUPP for this ARP function
*/
if (card->info.guestlan)
return -EOPNOTSUPP;
@@ -4986,11 +4973,10 @@ qeth_arp_flush_cache(struct qeth_card *c
QETH_DBF_TEXT(trace,3,"arpflush");
/*
- * currently GuestLAN does only deliver all zeros on query arp,
- * even though arp processing is supported (according to IPA supp.
- * funcs flags); since all zeros is no valueable information,
- * we say EOPNOTSUPP for all ARP functions
- */
+ * currently GuestLAN only supports the ARP assist function
+ * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_FLUSH_CACHE;
+ * thus we say EOPNOTSUPP for this ARP function
+ */
if (card->info.guestlan || (card->info.type == QETH_CARD_TYPE_IQD))
return -EOPNOTSUPP;
if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) {
@@ -8266,7 +8252,6 @@ qeth_init(void)
{
int rc=0;
- qeth_eyecatcher();
PRINT_INFO("loading %s (%s/%s/%s/%s/%s/%s/%s %s %s)\n",
version, VERSION_QETH_C, VERSION_QETH_H,
VERSION_QETH_MPC_H, VERSION_QETH_MPC_C,
@@ -8347,7 +8332,6 @@ again:
printk("qeth: removed\n");
}
-EXPORT_SYMBOL(qeth_eyecatcher);
module_init(qeth_init);
module_exit(qeth_exit);
MODULE_AUTHOR("Frank Pavlic <pavlic@de.ibm.com>");
diff -Naupr linux-2.6-orig/drivers/s390/net/qeth_sys.c linux-2.6-patched/drivers/s390/net/qeth_sys.c
--- linux-2.6-orig/drivers/s390/net/qeth_sys.c 2005-09-05 13:53:40.000000000 +0200
+++ linux-2.6-patched/drivers/s390/net/qeth_sys.c 2005-09-05 14:00:46.000000000 +0200
@@ -1,6 +1,6 @@
/*
*
- * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.53 $)
+ * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.54 $)
*
* Linux on zSeries OSA Express and HiperSockets support
* This file contains code related to sysfs.
@@ -20,7 +20,7 @@
#include "qeth_mpc.h"
#include "qeth_fs.h"
-const char *VERSION_QETH_SYS_C = "$Revision: 1.53 $";
+const char *VERSION_QETH_SYS_C = "$Revision: 1.54 $";
/*****************************************************************************/
/* */
@@ -722,10 +722,13 @@ qeth_dev_layer2_store(struct device *dev
if (!card)
return -EINVAL;
+ if (card->info.type == QETH_CARD_TYPE_IQD) {
+ PRINT_WARN("Layer2 on Hipersockets is not supported! \n");
+ return -EPERM;
+ }
if (((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER)) ||
- (card->info.type != QETH_CARD_TYPE_OSAE))
+ (card->state != CARD_STATE_RECOVER)))
return -EPERM;
i = simple_strtoul(buf, &tmp, 16);
^ permalink raw reply
* Re: [patch 3/4] s390: TSO related fixes in qeth driver
From: Jeff Garzik @ 2005-09-14 16:15 UTC (permalink / raw)
To: Frank Pavlic; +Cc: netdev, linux-kernel
In-Reply-To: <20050914160326.GA3458@pavlic>
applied patch #3 and #4, thanks for resending.
Jeff
^ permalink raw reply
* Re: [PATCH 1/2] New PowerPC 4xx on-chip ethernet controller driver
From: Eugene Surovegin @ 2005-09-14 16:18 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev, linuxppc-embedded
In-Reply-To: <43281B7D.5000106@pobox.com>
On Wed, Sep 14, 2005 at 08:45:49AM -0400, Jeff Garzik wrote:
> Eugene Surovegin wrote:
> >Remove old PPC4xx EMAC driver
> >
> >Signed-off-by: Eugene Surovegin <ebs@ebshome.net>
>
> Please post a diff, along with a description of the changes.
>
> One huge patch to "remove emac driver" and another huge patch to "add
> emac driver" is quite silly.
Jeff, it's not silly. I can post combined patch, but you won't be
able to read it (and combined patch is still big).
As I said, it's a _complete_ re-write. It's a _new_ driver, not just
some "changes". Description of what was done was in the first e-mail.
I've split it into two parts specifically, so _you_ will be able to
read new patch and comment on it.
--
Eugene
^ permalink raw reply
* [PATCH] New PowerPC 4xx on-chip ethernet controller driver
From: Eugene Surovegin @ 2005-09-14 17:08 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev, linuxppc-embedded
In-Reply-To: <43281B7D.5000106@pobox.com>
On Wed, Sep 14, 2005 at 08:45:49AM -0400, Jeff Garzik wrote:
> Eugene Surovegin wrote:
> >Remove old PPC4xx EMAC driver
> >
> >Signed-off-by: Eugene Surovegin <ebs@ebshome.net>
>
> Please post a diff, along with a description of the changes.
>
> One huge patch to "remove emac driver" and another huge patch to "add
> emac driver" is quite silly.
This patch replaces current PowerPC 4xx EMAC driver with
new, re-written version.
New driver uses NAPI, it solves stability problems under heavy packet
load and low memory, corrects chip register access and fixes numerous
small bugs I don't even remember now :).
This patch has been tested on all supported in 2.6 PPC 4xx boards.
It's been used in production for almost a year now on custom
4xx hardware. PPC32 specific parts are already upstream.
Patch was acked by the current EMAC driver maintainer (Matt Porter). I
will be maintaining this new version.
Signed-off-by: Eugene Surovegin <ebs@ebshome.net>
--
Kconfig | 72
ibm_emac/Makefile | 13
ibm_emac/ibm_emac.h | 418 +++--
ibm_emac/ibm_emac_core.c | 3391 ++++++++++++++++++++++++----------------------
ibm_emac/ibm_emac_core.h | 313 ++--
ibm_emac/ibm_emac_debug.c | 377 ++---
ibm_emac/ibm_emac_debug.h | 63
ibm_emac/ibm_emac_mal.c | 671 +++++----
ibm_emac/ibm_emac_mal.h | 336 +++-
ibm_emac/ibm_emac_phy.c | 335 ++--
ibm_emac/ibm_emac_phy.h | 105 -
ibm_emac/ibm_emac_rgmii.c | 202 ++
ibm_emac/ibm_emac_rgmii.h | 68
ibm_emac/ibm_emac_tah.c | 111 +
ibm_emac/ibm_emac_tah.h | 96 -
ibm_emac/ibm_emac_zmii.c | 256 +++
ibm_emac/ibm_emac_zmii.h | 114 -
17 files changed, 4119 insertions(+), 2822 deletions(-)
Patch is quite big (~234K) because there is virtualy 0% of common code
between old and new version.
It can be found at http://kernel.ebshome.net/emac/4xx_napi_emac.diff
^ permalink raw reply
* [PATCH] gt96100: stop using pci_find_device()
From: Alexey Dobriyan @ 2005-09-14 18:51 UTC (permalink / raw)
To: Ralf Baechle; +Cc: Scott Feldman, netdev, linux-mips
From: Scott Feldman <sfeldma@pobox.com>
Replace pci_find_device with pci_get_device/pci_dev_put to plug race
with pci_find_device.
Signed-off-by: Scott Feldman <sfeldma@pobox.com>
Signed-off-by: Maximilian Attems <janitor@sternwelten.at>
Signed-off-by: Domen Puncer <domen@coderock.org>
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
drivers/net/gt96100eth.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
--- a/drivers/net/gt96100eth.c
+++ b/drivers/net/gt96100eth.c
@@ -615,9 +615,9 @@ static int gt96100_init_module(void)
/*
* Stupid probe because this really isn't a PCI device
*/
- if (!(pci = pci_find_device(PCI_VENDOR_ID_MARVELL,
+ if (!(pci = pci_get_device(PCI_VENDOR_ID_MARVELL,
PCI_DEVICE_ID_MARVELL_GT96100, NULL)) &&
- !(pci = pci_find_device(PCI_VENDOR_ID_MARVELL,
+ !(pci = pci_get_device(PCI_VENDOR_ID_MARVELL,
PCI_DEVICE_ID_MARVELL_GT96100A, NULL))) {
printk(KERN_ERR __FILE__ ": GT96100 not found!\n");
return -ENODEV;
@@ -627,12 +627,14 @@ static int gt96100_init_module(void)
if (cpuConfig & (1<<12)) {
printk(KERN_ERR __FILE__
": must be in Big Endian mode!\n");
+ pci_dev_put(pci);
return -ENODEV;
}
for (i=0; i < NUM_INTERFACES; i++)
retval |= gt96100_probe1(pci, i);
+ pci_dev_put(pci);
return retval;
}
^ permalink raw reply
* Re: [PATCH] gt96100: stop using pci_find_device()
From: Jeff Garzik @ 2005-09-14 19:00 UTC (permalink / raw)
To: Alexey Dobriyan; +Cc: Ralf Baechle, Scott Feldman, netdev, linux-mips
In-Reply-To: <20050914185136.GE19491@mipter.zuzino.mipt.ru>
Alexey Dobriyan wrote:
> From: Scott Feldman <sfeldma@pobox.com>
>
> Replace pci_find_device with pci_get_device/pci_dev_put to plug race
> with pci_find_device.
>
> Signed-off-by: Scott Feldman <sfeldma@pobox.com>
> Signed-off-by: Maximilian Attems <janitor@sternwelten.at>
> Signed-off-by: Domen Puncer <domen@coderock.org>
> Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
> ---
>
> drivers/net/gt96100eth.c | 6 ++++--
> 1 files changed, 4 insertions(+), 2 deletions(-)
>
> --- a/drivers/net/gt96100eth.c
> +++ b/drivers/net/gt96100eth.c
> @@ -615,9 +615,9 @@ static int gt96100_init_module(void)
> /*
> * Stupid probe because this really isn't a PCI device
> */
> - if (!(pci = pci_find_device(PCI_VENDOR_ID_MARVELL,
> + if (!(pci = pci_get_device(PCI_VENDOR_ID_MARVELL,
> PCI_DEVICE_ID_MARVELL_GT96100, NULL)) &&
> - !(pci = pci_find_device(PCI_VENDOR_ID_MARVELL,
> + !(pci = pci_get_device(PCI_VENDOR_ID_MARVELL,
> PCI_DEVICE_ID_MARVELL_GT96100A, NULL))) {
> printk(KERN_ERR __FILE__ ": GT96100 not found!\n");
> return -ENODEV;
> @@ -627,12 +627,14 @@ static int gt96100_init_module(void)
> if (cpuConfig & (1<<12)) {
> printk(KERN_ERR __FILE__
> ": must be in Big Endian mode!\n");
> + pci_dev_put(pci);
> return -ENODEV;
NAK -- convert it to use standard PCI driver API.
Jeff
^ permalink raw reply
* Re: Fw: masquerading failure for at least icmp and tcp+sack on amd64
From: Marc Lehmann @ 2005-09-14 19:09 UTC (permalink / raw)
To: Patrick McHardy
Cc: Andrew Morton, netdev, Netfilter Development Mailinglist,
Stephen Hemminger
In-Reply-To: <43243AB9.9000705@trash.net>
On Sun, Sep 11, 2005 at 04:10:01PM +0200, Patrick McHardy <kaber@trash.net> wrote:
> >>What network driver are you using?
> >
> >Happens with both skge and sk98.
>
> Are you sure the same checksum error happens?
No, of course not.
I have two similar network cards in that machine (a normal sk98 pci card
and an onboard one that skge calls Yukon lite and the sk98lin driver calls
9521. The onboard one does not, though, work with sk98lin).
What I did test was with skge and the onboard card, and sk98_lin with
the pci card, and in both cases I couldn't get masquerading to work, but
everything else worked fine.
> ip_summed to CHECKSUM_HW, it uses either CHECKSUM_UNNECESSARY for
> HW checksummed packets, in which case the check is skipped in
> ip_conntrack, or it uses CHECKSUM_NONE, in which case the checksum
> in the packet must be invalid if the check fails and the packet
> wouldn't be accepted by the final receipient anyway. skge uses
> CHECKSUM_HW for every packet, so they have nothing in common wrt.
> HW checksumming. This would normally mean we can rule out HW
> checksumming, but for some reason turning it off on skge seems
> to help in your case.
... and I have not tried turning it off with sk98lin (and would like to
avoid it, as it requires reconfiguration to test). If any additional tests
arre required, I will do them, though.
> > nfs_acl 3136 1 nfsd
> > sunrpc 142632 13 nfsd,lockd,nfs_acl
> >
> >However, it happens with init=/bin/bash and loading the single iptables
> >rule I sent in the original report, for either eth0/1 or the ppp
> >interface. I can send you my 278 other rules if you want, but they have
> >had no effect on the problem here.
>
> No, thanks. But your entire .config might help ..
Sorry for the delay :( It's here:
http://data.plan9.de/config.doom
This is the currently-running 2.6.13 config, when testing 2.6.11, i just
did "make oldconfig" on this one.
--
The choice of a
-----==- _GNU_
----==-- _ generation Marc Lehmann
---==---(_)__ __ ____ __ pcg@goof.com
--==---/ / _ \/ // /\ \/ / http://schmorp.de/
-=====/_/_//_/\_,_/ /_/\_\ XX11-RIPE
^ permalink raw reply
* Re: [PATCH] gt96100: stop using pci_find_device()
From: Ralf Baechle @ 2005-09-14 19:40 UTC (permalink / raw)
To: Alexey Dobriyan; +Cc: Scott Feldman, netdev, linux-mips
In-Reply-To: <20050914185136.GE19491@mipter.zuzino.mipt.ru>
On Wed, Sep 14, 2005 at 10:51:37PM +0400, Alexey Dobriyan wrote:
> Replace pci_find_device with pci_get_device/pci_dev_put to plug race
> with pci_find_device.
The system is a little odd; the race condition probably doens't exist on
this particular chipset.
Ralf
^ permalink raw reply
* VPN server over windows XP
From: Alaa Dalghan @ 2005-09-14 20:18 UTC (permalink / raw)
To: linux-crypto, linux-kernel, linux-net, linux-security-module,
netdev
hello everyone,
I am trying to setup a windows xp machine as a vpn server that accepts
multiple ipsec tunnels from other windows xp machines.
My restrictions are the following:
1- I need to set the vpn server on windows XP (not windows 2000 server, nor
2003, nor ISA server, etc.)
2- I need to use tunnel mode ipsec
3- The vpn server should accept MULTIPLE vpn tunnels.
The first problem I faced is that windows xp does not support ipsec tunnel
mode between 2 xp machines. It only supports transport mode which is not
what I want.
To overcome this lack of IP tunneling I tried to use the built-in tunneling
capabilities such as PPTP and L2TP/ipsec, and it worked. But the problem
here is that a windows xp can not accept more than ONE SINGLE incoming
connection at a time, and I need multiple connections.
I think the solution could be one of the following:
1-Installing a third party FREE vpn server (or L2TP server) on windows XP.
If you know one please tell me.
2-Importing some features from windows 2000 server or 2003 server (some
executables or services or plugins that enable xp to run as a vpn server and
accept multiple connections). If you know what to import please tell me.
3- Installing a pure IP tunneling solution on windows xp so that it can be
combined with ipsec encryption to yield tunnel mode encryption.
I appreciate any help,
Alaadin
_________________________________________________________________
Express yourself instantly with MSN Messenger! Download today - it's FREE!
http://messenger.msn.click-url.com/go/onm00200471ave/direct/01/
-
Linux-crypto: cryptography in and on the Linux system
Archive: http://mail.nl.linux.org/linux-crypto/
^ permalink raw reply
* Re: VPN server over windows XP
From: Redeeman @ 2005-09-14 20:29 UTC (permalink / raw)
To: Alaa Dalghan
Cc: linux-crypto, linux-kernel, linux-net, linux-security-module,
netdev
In-Reply-To: <BAY106-F29965CB20274069D3A5BA5AB9F0@phx.gbl>
On Wed, 2005-09-14 at 20:18 +0000, Alaa Dalghan wrote:
> hello everyone,
<snip>
this really isnt the place for this discussion
>
> Alaadin
>
> _________________________________________________________________
> Express yourself instantly with MSN Messenger! Download today - it's FREE!
> http://messenger.msn.click-url.com/go/onm00200471ave/direct/01/
>
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
>
^ permalink raw reply
* Re: [RFC] hippi: change to not use skb private
From: David S. Miller @ 2005-09-15 4:03 UTC (permalink / raw)
To: shemminger; +Cc: jes, netdev, linux-kernel
In-Reply-To: <20050913113858.440d3a0f@localhost.localdomain>
From: Stephen Hemminger <shemminger@osdl.org>
Date: Tue, 13 Sep 2005 11:38:58 -0700
> It looks like the following would fix hippi to not have to put
> fields in sk_buff. The ifield looks appears to to be additional
> header information that is being passed in the skb but could just
> be put in the header.
Stephen this patch is against 2.6.13 or something. We already
put this thing into a SKB control block for 2.6.14-rc1. Do you
want to keep things that way or update your patch for 2.6.14-rc1?
^ permalink raw reply
* [PATCH 1/3] NETFILTER: CLUSTERIP entry refcounting
From: Harald Welte @ 2005-09-15 14:51 UTC (permalink / raw)
To: David Miller; +Cc: Linux Netdev List, Netfilter Development Mailinglist
[-- Attachment #1: Type: text/plain, Size: 6847 bytes --]
Hi Dave, please push this bugfix to mainline.
CLUSTERIP: introduce reference counting for entries
The CLUSTERIP target creates a procfs entry for all different cluster
IPs. Although more than one rules can refer to a single cluster IP (and
thus a single config structure), removal of the procfs entry is done
unconditionally in destroy(). In more complicated situations involving
deferred dereferencing of the config structure by procfs and creating a
new rule with the same cluster IP it's also possible that no entry will
be created for the new rule.
This patch fixes the problem by counting the number of entries
referencing a given config structure and moving the config list
manipulation and procfs entry deletion parts to the
clusterip_config_entry_put() function.
Signed-off-by: KOVACS Krisztian <hidden@balabit.hu>
Signed-off-by: Harald Welte <laforge@netfilter.org>
---
commit 8d5367b6545c19e551564c26adc808861624ef15
tree 33e3c99394a7f9fae6cc09e5f328144f4786c9f0
parent 8e662a0c0b3aa1257641dd32d5c92d880c110623
author Harald Welte <laforge@netfilter.org> Di, 13 Sep 2005 14:53:17 +0200
committer Harald Welte <laforge@netfilter.org> Di, 13 Sep 2005 14:53:17 +0200
net/ipv4/netfilter/ipt_CLUSTERIP.c | 80 ++++++++++++++++++++++++++++--------
1 files changed, 62 insertions(+), 18 deletions(-)
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -49,6 +49,8 @@ MODULE_DESCRIPTION("iptables target for
struct clusterip_config {
struct list_head list; /* list of all configs */
atomic_t refcount; /* reference count */
+ atomic_t entries; /* number of entries/rules
+ * referencing us */
u_int32_t clusterip; /* the IP address */
u_int8_t clustermac[ETH_ALEN]; /* the MAC address */
@@ -76,23 +78,48 @@ static struct proc_dir_entry *clusterip_
#endif
static inline void
-clusterip_config_get(struct clusterip_config *c) {
+clusterip_config_get(struct clusterip_config *c)
+{
atomic_inc(&c->refcount);
}
static inline void
-clusterip_config_put(struct clusterip_config *c) {
- if (atomic_dec_and_test(&c->refcount)) {
+clusterip_config_put(struct clusterip_config *c)
+{
+ if (atomic_dec_and_test(&c->refcount))
+ kfree(c);
+}
+
+/* increase the count of entries(rules) using/referencing this config */
+static inline void
+clusterip_config_entry_get(struct clusterip_config *c)
+{
+ atomic_inc(&c->entries);
+}
+
+/* decrease the count of entries using/referencing this config. If last
+ * entry(rule) is removed, remove the config from lists, but don't free it
+ * yet, since proc-files could still be holding references */
+static inline void
+clusterip_config_entry_put(struct clusterip_config *c)
+{
+ if (atomic_dec_and_test(&c->entries)) {
write_lock_bh(&clusterip_lock);
list_del(&c->list);
write_unlock_bh(&clusterip_lock);
+
dev_mc_delete(c->dev, c->clustermac, ETH_ALEN, 0);
dev_put(c->dev);
- kfree(c);
+
+ /* In case anyone still accesses the file, the open/close
+ * functions are also incrementing the refcount on their own,
+ * so it's safe to remove the entry even if it's in use. */
+#ifdef CONFIG_PROC_FS
+ remove_proc_entry(c->pde->name, c->pde->parent);
+#endif
}
}
-
static struct clusterip_config *
__clusterip_config_find(u_int32_t clusterip)
{
@@ -111,7 +138,7 @@ __clusterip_config_find(u_int32_t cluste
}
static inline struct clusterip_config *
-clusterip_config_find_get(u_int32_t clusterip)
+clusterip_config_find_get(u_int32_t clusterip, int entry)
{
struct clusterip_config *c;
@@ -122,6 +149,8 @@ clusterip_config_find_get(u_int32_t clus
return NULL;
}
atomic_inc(&c->refcount);
+ if (entry)
+ atomic_inc(&c->entries);
read_unlock_bh(&clusterip_lock);
return c;
@@ -148,6 +177,7 @@ clusterip_config_init(struct ipt_cluster
c->hash_mode = i->hash_mode;
c->hash_initval = i->hash_initval;
atomic_set(&c->refcount, 1);
+ atomic_set(&c->entries, 1);
#ifdef CONFIG_PROC_FS
/* create proc dir entry */
@@ -415,8 +445,26 @@ checkentry(const char *tablename,
/* FIXME: further sanity checks */
- config = clusterip_config_find_get(e->ip.dst.s_addr);
- if (!config) {
+ config = clusterip_config_find_get(e->ip.dst.s_addr, 1);
+ if (config) {
+ if (cipinfo->config != NULL) {
+ /* Case A: This is an entry that gets reloaded, since
+ * it still has a cipinfo->config pointer. Simply
+ * increase the entry refcount and return */
+ if (cipinfo->config != config) {
+ printk(KERN_ERR "CLUSTERIP: Reloaded entry "
+ "has invalid config pointer!\n");
+ return 0;
+ }
+ clusterip_config_entry_get(cipinfo->config);
+ } else {
+ /* Case B: This is a new rule referring to an existing
+ * clusterip config. */
+ cipinfo->config = config;
+ clusterip_config_entry_get(cipinfo->config);
+ }
+ } else {
+ /* Case C: This is a completely new clusterip config */
if (!(cipinfo->flags & CLUSTERIP_FLAG_NEW)) {
printk(KERN_WARNING "CLUSTERIP: no config found for %u.%u.%u.%u, need 'new'\n", NIPQUAD(e->ip.dst.s_addr));
return 0;
@@ -443,10 +491,9 @@ checkentry(const char *tablename,
}
dev_mc_add(config->dev,config->clustermac, ETH_ALEN, 0);
}
+ cipinfo->config = config;
}
- cipinfo->config = config;
-
return 1;
}
@@ -455,13 +502,10 @@ static void destroy(void *matchinfo, uns
{
struct ipt_clusterip_tgt_info *cipinfo = matchinfo;
- /* we first remove the proc entry and then drop the reference
- * count. In case anyone still accesses the file, the open/close
- * functions are also incrementing the refcount on their own */
-#ifdef CONFIG_PROC_FS
- remove_proc_entry(cipinfo->config->pde->name,
- cipinfo->config->pde->parent);
-#endif
+ /* if no more entries are referencing the config, remove it
+ * from the list and destroy the proc entry */
+ clusterip_config_entry_put(cipinfo->config);
+
clusterip_config_put(cipinfo->config);
}
@@ -533,7 +577,7 @@ arp_mangle(unsigned int hook,
/* if there is no clusterip configuration for the arp reply's
* source ip, we don't want to mangle it */
- c = clusterip_config_find_get(payload->src_ip);
+ c = clusterip_config_find_get(payload->src_ip, 0);
if (!c)
return NF_ACCEPT;
--
- Harald Welte <laforge@netfilter.org> http://netfilter.org/
============================================================================
"Fragmentation is like classful addressing -- an interesting early
architectural error that shows how much experimentation was going
on while IP was being designed." -- Paul Vixie
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox