* net-2.6.24 rebased...
From: David Miller @ 2007-09-26 6:33 UTC (permalink / raw)
To: netdev; +Cc: linville, jeff, akpm
Ok the rebase is complete and I integrated all of the
"easy" stuff in my backlog. In the usual spot:
kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6.git
John, one patch didn't go in cleanly after I removed the
Z1211 driver. I put it here for your consideration so it
doesn't get lost:
http://vger.kernel.org/~davem/0433-Z1211-Fix-TX-status-reports.patch
What probably needs to happen is some other changes that
were in z1211 need to go into the non-mac80211 driver and
then this patch applies correctly.
I tried the simple thing to rename the directory in the patch
and that didn't work, obviously :-)
Jeff, if you have any pending driver bits please toss them my
way as most of my backlog is clear now.
Andrew, I applied a good chunk of the driver build fixes you had
accumulated. I think I missed one or two, so please check that out
and send my way the ones that I missed.
Thanks!
^ permalink raw reply
* [patch 33/43] lguest: Net driver using virtio
From: rusty @ 2007-09-26 6:36 UTC (permalink / raw)
To: lguest; +Cc: virtualization, Christian Borntraeger, Herbert Xu, netdev
In-Reply-To: <20070926063618.956228976@rustcorp.com.au>
[-- Attachment #1: new-io-net.patch --]
[-- Type: text/plain, Size: 14981 bytes --]
The network driver uses two virtqueues: one for input packets and one
for output packets. This has nice locking properties (ie. we don't do
any for recv vs send).
TODO:
1) Big packets.
2) Multi-client devices (maybe separate driver?).
3) Resolve freeing of old xmit skbs (Christian Borntraeger)
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Cc: Christian Borntraeger <borntraeger@de.ibm.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: netdev@vger.kernel.org
---
drivers/net/Kconfig | 6
drivers/net/Makefile | 2
drivers/net/virtio_net.c | 438 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/virtio_net.h | 36 +++
4 files changed, 481 insertions(+), 1 deletion(-)
===================================================================
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2998,4 +2998,10 @@ config NET_POLL_CONTROLLER
config NET_POLL_CONTROLLER
def_bool NETPOLL
+config VIRTIO_NET
+ tristate "Virtio network driver (EXPERIMENTAL)"
+ depends on EXPERIMENTAL && VIRTIO
+ ---help---
+ This is the virtual network driver for lguest. Say Y or M.
+
endif # NETDEVICES
===================================================================
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -38,7 +38,7 @@ obj-$(CONFIG_SUNVNET) += sunvnet.o
obj-$(CONFIG_MACE) += mace.o
obj-$(CONFIG_BMAC) += bmac.o
-
+obj-$(CONFIG_VIRTIO_NET) += virtio_net.o
obj-$(CONFIG_DGRS) += dgrs.o
obj-$(CONFIG_VORTEX) += 3c59x.o
obj-$(CONFIG_TYPHOON) += typhoon.o
===================================================================
--- /dev/null
+++ b/drivers/net/virtio_net.c
@@ -0,0 +1,438 @@
+/* A simple network driver using virtio.
+ *
+ * Copyright 2007 Rusty Russell <rusty@rustcorp.com.au> IBM Corporation
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+//#define DEBUG
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/module.h>
+#include <linux/virtio.h>
+#include <linux/virtio_net.h>
+#include <linux/scatterlist.h>
+
+/* FIXME: MTU in config. */
+#define MAX_PACKET_LEN (ETH_HLEN+ETH_DATA_LEN)
+
+struct virtnet_info
+{
+ struct virtio_device *vdev;
+ struct virtqueue *rvq, *svq;
+ struct net_device *dev;
+
+ /* Number of input buffers, and max we've ever had. */
+ unsigned int num, max;
+
+ /* Receive & send queues. */
+ struct sk_buff_head recv;
+ struct sk_buff_head send;
+};
+
+static inline struct virtio_net_hdr *skb_vnet_hdr(struct sk_buff *skb)
+{
+ return (struct virtio_net_hdr *)skb->cb;
+}
+
+static inline void vnet_hdr_to_sg(struct scatterlist *sg, struct sk_buff *skb)
+{
+ sg_init_one(sg, skb_vnet_hdr(skb), sizeof(struct virtio_net_hdr));
+}
+
+static bool skb_xmit_done(struct virtqueue *rvq)
+{
+ struct virtnet_info *vi = rvq->vdev->priv;
+
+ /* In case we were waiting for output buffers. */
+ netif_wake_queue(vi->dev);
+ return true;
+}
+
+static void receive_skb(struct net_device *dev, struct sk_buff *skb,
+ unsigned len)
+{
+ struct virtio_net_hdr *hdr = skb_vnet_hdr(skb);
+
+ if (unlikely(len < sizeof(struct virtio_net_hdr) + ETH_HLEN)) {
+ pr_debug("%s: short packet %i\n", dev->name, len);
+ dev->stats.rx_length_errors++;
+ goto drop;
+ }
+ len -= sizeof(struct virtio_net_hdr);
+ BUG_ON(len > MAX_PACKET_LEN);
+
+ skb_trim(skb, len);
+ skb->protocol = eth_type_trans(skb, dev);
+ pr_debug("Receiving skb proto 0x%04x len %i type %i\n",
+ ntohs(skb->protocol), skb->len, skb->pkt_type);
+ dev->stats.rx_bytes += skb->len;
+ dev->stats.rx_packets++;
+
+ if (hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
+ pr_debug("Needs csum!\n");
+ skb->ip_summed = CHECKSUM_PARTIAL;
+ skb->csum_start = hdr->csum_start;
+ skb->csum_offset = hdr->csum_offset;
+ if (skb->csum_start > skb->len - 2
+ || skb->csum_offset > skb->len - 2) {
+ if (net_ratelimit())
+ printk(KERN_WARNING "%s: csum=%u/%u len=%u\n",
+ dev->name, skb->csum_start,
+ skb->csum_offset, skb->len);
+ goto frame_err;
+ }
+ }
+
+ if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) {
+ pr_debug("GSO!\n");
+ switch (hdr->gso_type) {
+ case VIRTIO_NET_HDR_GSO_TCPV4:
+ skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
+ break;
+ case VIRTIO_NET_HDR_GSO_TCPV4_ECN:
+ skb_shinfo(skb)->gso_type = SKB_GSO_TCP_ECN;
+ break;
+ case VIRTIO_NET_HDR_GSO_UDP:
+ skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
+ break;
+ case VIRTIO_NET_HDR_GSO_TCPV6:
+ skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
+ break;
+ default:
+ if (net_ratelimit())
+ printk(KERN_WARNING "%s: bad gso type %u.\n",
+ dev->name, hdr->gso_type);
+ goto frame_err;
+ }
+
+ skb_shinfo(skb)->gso_size = hdr->gso_size;
+ if (skb_shinfo(skb)->gso_size == 0) {
+ if (net_ratelimit())
+ printk(KERN_WARNING "%s: zero gso size.\n",
+ dev->name);
+ goto frame_err;
+ }
+
+ /* Header must be checked, and gso_segs computed. */
+ skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
+ skb_shinfo(skb)->gso_segs = 0;
+ }
+
+ netif_receive_skb(skb);
+ return;
+
+frame_err:
+ dev->stats.rx_frame_errors++;
+drop:
+ dev_kfree_skb(skb);
+}
+
+static void try_fill_recv(struct virtnet_info *vi)
+{
+ struct sk_buff *skb;
+ struct scatterlist sg[1+MAX_SKB_FRAGS];
+ int num, err;
+
+ for (;;) {
+ skb = netdev_alloc_skb(vi->dev, MAX_PACKET_LEN);
+ if (unlikely(!skb))
+ break;
+
+ skb_put(skb, MAX_PACKET_LEN);
+ vnet_hdr_to_sg(sg, skb);
+ num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1;
+ skb_queue_head(&vi->recv, skb);
+
+ err = vi->rvq->vq_ops->add_buf(vi->rvq, sg, 0, num, skb);
+ if (err) {
+ skb_unlink(skb, &vi->recv);
+ kfree_skb(skb);
+ break;
+ }
+ vi->num++;
+ }
+ if (unlikely(vi->num > vi->max))
+ vi->max = vi->num;
+ vi->rvq->vq_ops->kick(vi->rvq);
+}
+
+static bool skb_recv_done(struct virtqueue *rvq)
+{
+ struct virtnet_info *vi = rvq->vdev->priv;
+ netif_rx_schedule(vi->dev);
+ /* Suppress further interrupts. */
+ return false;
+}
+
+static int virtnet_poll(struct net_device *dev, int *budget)
+{
+ struct virtnet_info *vi = netdev_priv(dev);
+ struct sk_buff *skb = NULL;
+ unsigned int len, received = 0;
+
+again:
+ while (received < dev->quota &&
+ (skb = vi->rvq->vq_ops->get_buf(vi->rvq, &len)) != NULL) {
+ __skb_unlink(skb, &vi->recv);
+ receive_skb(vi->dev, skb, len);
+ vi->num--;
+ received++;
+ }
+
+ dev->quota -= received;
+ *budget -= received;
+
+ /* FIXME: If we oom and completely run out of inbufs, we need
+ * to start a timer trying to fill more. */
+ if (vi->num < vi->max / 2)
+ try_fill_recv(vi);
+
+ /* Still more work to do? */
+ if (skb)
+ return 1; /* not done */
+
+ netif_rx_complete(dev);
+ if (unlikely(!vi->rvq->vq_ops->restart(vi->rvq))
+ && netif_rx_reschedule(dev, received))
+ goto again;
+
+ return 0;
+}
+
+static void free_old_xmit_skbs(struct virtnet_info *vi)
+{
+ struct sk_buff *skb;
+ unsigned int len;
+
+ while ((skb = vi->svq->vq_ops->get_buf(vi->svq, &len)) != NULL) {
+ pr_debug("Sent skb %p\n", skb);
+ __skb_unlink(skb, &vi->send);
+ vi->dev->stats.tx_bytes += len;
+ vi->dev->stats.tx_packets++;
+ kfree_skb(skb);
+ }
+}
+
+static int start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct virtnet_info *vi = netdev_priv(dev);
+ int num, err;
+ struct scatterlist sg[1+MAX_SKB_FRAGS];
+ struct virtio_net_hdr *hdr;
+ const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest;
+
+ pr_debug("%s: xmit %p %02x:%02x:%02x:%02x:%02x:%02x\n",
+ dev->name, skb,
+ dest[0], dest[1], dest[2], dest[3], dest[4], dest[5]);
+
+ free_old_xmit_skbs(vi);
+
+ /* Encode metadata header at front. */
+ hdr = skb_vnet_hdr(skb);
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
+ hdr->csum_start = skb->csum_start - skb_headroom(skb);
+ hdr->csum_offset = skb->csum_offset;
+ } else {
+ hdr->flags = 0;
+ hdr->csum_offset = hdr->csum_start = 0;
+ }
+
+ if (skb_is_gso(skb)) {
+ hdr->gso_size = skb_shinfo(skb)->gso_size;
+ if (skb_shinfo(skb)->gso_type & SKB_GSO_TCP_ECN)
+ hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4_ECN;
+ else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4)
+ hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
+ else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
+ hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
+ else if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP)
+ hdr->gso_type = VIRTIO_NET_HDR_GSO_UDP;
+ else
+ BUG();
+ } else {
+ hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE;
+ hdr->gso_size = 0;
+ }
+
+ vnet_hdr_to_sg(sg, skb);
+ num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1;
+ __skb_queue_head(&vi->send, skb);
+ err = vi->svq->vq_ops->add_buf(vi->svq, sg, num, 0, skb);
+ if (err) {
+ pr_debug("%s: virtio not prepared to send\n", dev->name);
+ skb_unlink(skb, &vi->send);
+ netif_stop_queue(dev);
+ return NETDEV_TX_BUSY;
+ }
+ vi->svq->vq_ops->kick(vi->svq);
+
+ return 0;
+}
+
+static int virtnet_open(struct net_device *dev)
+{
+ struct virtnet_info *vi = netdev_priv(dev);
+
+ try_fill_recv(vi);
+
+ /* If we didn't even get one input buffer, we're useless. */
+ if (vi->num == 0)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static int virtnet_close(struct net_device *dev)
+{
+ struct virtnet_info *vi = netdev_priv(dev);
+ struct sk_buff *skb;
+
+ /* networking core has neutered skb_xmit_done/skb_recv_done, so don't
+ * worry about races vs. get(). */
+ vi->rvq->vq_ops->shutdown(vi->rvq);
+ while ((skb = __skb_dequeue(&vi->recv)) != NULL) {
+ kfree_skb(skb);
+ vi->num--;
+ }
+ vi->svq->vq_ops->shutdown(vi->svq);
+ while ((skb = __skb_dequeue(&vi->send)) != NULL)
+ kfree_skb(skb);
+
+ BUG_ON(vi->num != 0);
+ return 0;
+}
+
+static int virtnet_probe(struct virtio_device *vdev)
+{
+ int err;
+ unsigned int len;
+ struct net_device *dev;
+ struct virtnet_info *vi;
+ void *token;
+
+ /* Allocate ourselves a network device with room for our info */
+ dev = alloc_etherdev(sizeof(struct virtnet_info));
+ if (!dev)
+ return -ENOMEM;
+
+ /* Set up network device as normal. */
+ SET_MODULE_OWNER(dev);
+ ether_setup(dev);
+ dev->open = virtnet_open;
+ dev->stop = virtnet_close;
+ dev->poll = virtnet_poll;
+ dev->hard_start_xmit = start_xmit;
+ dev->weight = 16;
+ dev->features = NETIF_F_HIGHDMA;
+ SET_NETDEV_DEV(dev, &vdev->dev);
+
+ /* Do we support "hardware" checksums? */
+ token = vdev->config->find(vdev, VIRTIO_CONFIG_NET_F, &len);
+ if (virtio_use_bit(vdev, token, len, VIRTIO_NET_F_NO_CSUM)) {
+ /* This opens up the world of extra features. */
+ dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST;
+ if (virtio_use_bit(vdev, token, len, VIRTIO_NET_F_TSO4))
+ dev->features |= NETIF_F_TSO;
+ if (virtio_use_bit(vdev, token, len, VIRTIO_NET_F_UFO))
+ dev->features |= NETIF_F_UFO;
+ if (virtio_use_bit(vdev, token, len, VIRTIO_NET_F_TSO4_ECN))
+ dev->features |= NETIF_F_TSO_ECN;
+ if (virtio_use_bit(vdev, token, len, VIRTIO_NET_F_TSO6))
+ dev->features |= NETIF_F_TSO6;
+ }
+
+ /* Configuration may specify what MAC to use. Otherwise random. */
+ token = vdev->config->find(vdev, VIRTIO_CONFIG_NET_MAC_F, &len);
+ if (token) {
+ dev->addr_len = len;
+ vdev->config->get(vdev, token, dev->dev_addr, len);
+ } else
+ random_ether_addr(dev->dev_addr);
+
+ /* Set up our device-specific information */
+ vi = netdev_priv(dev);
+ vi->dev = dev;
+ vi->vdev = vdev;
+
+ /* We expect two virtqueues, receive then send. */
+ vi->rvq = vdev->config->find_vq(vdev, skb_recv_done);
+ if (IS_ERR(vi->rvq)) {
+ err = PTR_ERR(vi->rvq);
+ goto free;
+ }
+
+ vi->svq = vdev->config->find_vq(vdev, skb_xmit_done);
+ if (IS_ERR(vi->svq)) {
+ err = PTR_ERR(vi->svq);
+ goto free_recv;
+ }
+
+ /* Initialize our empty receive and send queues. */
+ skb_queue_head_init(&vi->recv);
+ skb_queue_head_init(&vi->send);
+
+ err = register_netdev(dev);
+ if (err) {
+ pr_debug("virtio_net: registering device failed\n");
+ goto free_send;
+ }
+ pr_debug("virtnet: registered device %s\n", dev->name);
+ vdev->priv = vi;
+ return 0;
+
+free_send:
+ vdev->config->del_vq(vi->svq);
+free_recv:
+ vdev->config->del_vq(vi->rvq);
+free:
+ free_netdev(dev);
+ return err;
+}
+
+static void virtnet_remove(struct virtio_device *vdev)
+{
+ unregister_netdev(vdev->priv);
+ free_netdev(vdev->priv);
+}
+
+static struct virtio_device_id id_table[] = {
+ { VIRTIO_ID_NET, VIRTIO_DEV_ANY_ID },
+ { 0 },
+};
+
+static struct virtio_driver virtio_net = {
+ .driver.name = KBUILD_MODNAME,
+ .driver.owner = THIS_MODULE,
+ .id_table = id_table,
+ .probe = virtnet_probe,
+ .remove = __devexit_p(virtnet_remove),
+};
+
+static int __init init(void)
+{
+ return register_virtio_driver(&virtio_net);
+}
+
+static void __exit fini(void)
+{
+ unregister_virtio_driver(&virtio_net);
+}
+module_init(init);
+module_exit(fini);
+
+MODULE_DEVICE_TABLE(virtio, id_table);
+MODULE_DESCRIPTION("Virtio network driver");
+MODULE_LICENSE("GPL");
===================================================================
--- /dev/null
+++ b/include/linux/virtio_net.h
@@ -0,0 +1,36 @@
+#ifndef _LINUX_VIRTIO_NET_H
+#define _LINUX_VIRTIO_NET_H
+#include <linux/virtio_config.h>
+
+/* The ID for virtio_net */
+#define VIRTIO_ID_NET 1
+
+/* The bitmap of config for virtio net */
+#define VIRTIO_CONFIG_NET_F 0x40
+#define VIRTIO_NET_F_NO_CSUM 0
+#define VIRTIO_NET_F_TSO4 1
+#define VIRTIO_NET_F_UFO 2
+#define VIRTIO_NET_F_TSO4_ECN 3
+#define VIRTIO_NET_F_TSO6 4
+
+/* The config defining mac address. */
+#define VIRTIO_CONFIG_NET_MAC_F 0x41
+
+/* This is the first element of the scatter-gather list. If you don't
+ * specify GSO or CSUM features, you can simply ignore the header. */
+struct virtio_net_hdr
+{
+#define VIRTIO_NET_HDR_F_NEEDS_CSUM 1 // Use csum_start, csum_offset
+ __u8 flags;
+#define VIRTIO_NET_HDR_GSO_NONE 0 // Not a GSO frame
+#define VIRTIO_NET_HDR_GSO_TCPV4 1 // GSO frame, IPv4 TCP (TSO)
+/* FIXME: Do we need this? If they said they can handle ECN, do they care? */
+#define VIRTIO_NET_HDR_GSO_TCPV4_ECN 2 // GSO frame, IPv4 TCP w/ ECN
+#define VIRTIO_NET_HDR_GSO_UDP 3 // GSO frame, IPv4 UDP (UFO)
+#define VIRTIO_NET_HDR_GSO_TCPV6 4 // GSO frame, IPv6 TCP
+ __u8 gso_type;
+ __u16 gso_size;
+ __u16 csum_start;
+ __u16 csum_offset;
+};
+#endif /* _LINUX_VIRTIO_NET_H */
--
there are those who do and those who hang on and you don't see too
many doers quoting their contemporaries. -- Larry McVoy
^ permalink raw reply
* Re: net-2.6.24 rebased...
From: Johannes Berg @ 2007-09-26 7:19 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linville, jeff, akpm
In-Reply-To: <20070925.233344.43202361.davem@davemloft.net>
[-- Attachment #1: Type: text/plain, Size: 554 bytes --]
On Tue, 2007-09-25 at 23:33 -0700, David Miller wrote:
> http://vger.kernel.org/~davem/0433-Z1211-Fix-TX-status-reports.patch
>
> What probably needs to happen is some other changes that
> were in z1211 need to go into the non-mac80211 driver and
> then this patch applies correctly.
>
> I tried the simple thing to rename the directory in the patch
> and that didn't work, obviously :-)
That patch is specific to the mac80211 version and you don't have that
yet, it just needs to be stick along with it till the next time.
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 190 bytes --]
^ permalink raw reply
* Re: Userspace network stack and netchannels.
From: Evgeniy Polyakov @ 2007-09-26 8:47 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: netdev
In-Reply-To: <20070925123444.10346e99@freepuppy.rosehill>
On Tue, Sep 25, 2007 at 12:34:44PM -0700, Stephen Hemminger (shemminger@linux-foundation.org) wrote:
> > It was proven [3] that unetstack can be *much* faster than vanilla TCP
> > stack (mainly because of heavily reduced number of syscalls, different
> > congestion control algorithm and other features).
>
> I am glad to see a more complete implementation for comparison, but
> by changing several variables at once it makes it hard to evaluate whether
> the improvement comes from user space TCP or the other changes.
Number of issues were improved - mostly reduced number of syscalls (if
size of the message increases results become essentially the same).
Different (non-rfc-compliant) congestion control algorithm allows faster
start and recovery, but in slower links (or longer rtt) it can be wrong.
Originally it was created to show superiority of the netchannel architecture,
but several hundreds of percents in some cases is not result of
peer-to-peer and process context processing. This stack works with
netchannels, which just became a link between hardware and user, such
approach allows huge variety of usage for different network hardware
including safe offloading, sniffing and so on. This stack is an example.
--
Evgeniy Polyakov
^ permalink raw reply
* Re: Userspace network stack and netchannels.
From: Evgeniy Polyakov @ 2007-09-26 8:53 UTC (permalink / raw)
To: Robert Iakobashvili; +Cc: netdev
In-Reply-To: <7e63f56c0709251220s12ab10b5pade5b2c90fa4a8b9@mail.gmail.com>
Hi Robert.
On Tue, Sep 25, 2007 at 09:20:44PM +0200, Robert Iakobashvili (coroberti@gmail.com) wrote:
> > 3. Gigabit send/recv benchmark for netchannels and sockets using small
> > packets.
> > http://tservice.net.ru/~s0mbre/blog/devel/networking/2006_10_26.html
> > http://tservice.net.ru/~s0mbre/blog/devel/networking/2006_12_21.html
> >
>
> Very interesting. Are there any details of your benchmarking available,
> namely, how it was done?
> Have you some comparison profiling data (oprofile) to figure out where
> the advantages are coming from?
Those are throughput tests - one sender, one receiver with different
size of the packet being sent/received. CPU usage was determined via
/proc statistics. My analysis says that reduced number of syscalls is
main improvement factor, but different (non-rfc-compliant) congestion
control allows faster start and faster recovery.
--
Evgeniy Polyakov
^ permalink raw reply
* Re: [PATCH v3 2/2][BNX2]: Add iSCSI support to BNX2 devices.
From: FUJITA Tomonori @ 2007-09-26 8:57 UTC (permalink / raw)
To: hare
Cc: tomof, open-iscsi, hch, jeff, davem, mchristi, netdev, anilgv,
talm, lusinsky, uri, fujita.tomonori
In-Reply-To: <46F8C935.8050907@suse.de>
On Tue, 25 Sep 2007 10:39:17 +0200
Hannes Reinecke <hare@suse.de> wrote:
> Hi Tomo,
>
> FUJITA Tomonori wrote:
> > On Sat, 8 Sep 2007 13:00:36 +0100
> > Christoph Hellwig <hch@infradead.org> wrote:
> >
> >> On Sat, Sep 08, 2007 at 07:32:27AM -0400, Jeff Garzik wrote:
> >>> FUJITA Tomonori wrote:
> >>>> Yeah, iommu code ignores the lld limitations (the problem is that the
> >>>> lld limitations are in request_queue and iommu code can't access to
> >>>> request_queue). There is no way to tell iommu code about the lld
> >>>> limitations.
> >>>
> >>> This fact very much wants fixing.
> >>
> >> Absolutely. Unfortunately everyone wastes their time on creating workarounds
> >> instead of fixing the underlying problem.
> >
> > Any ideas on how to fix this?
> >
> > I chatted to Jens and James on this last week.
> >
> > - we could just copies the lld limitations to device structure. it's
> > hacky but device structure already has hacky stuff.
> >
> > - we could just link device structure to request_queue structure so
> > that iommu code can see request_queue structure.
> >
> > - we could remove the lld limitations in request_queue strucutre and
> > have a new strucutre (something like struct io_restrictions). then
> > somehow we could link the new structure with request_queue and device
> > strucutres.
> >
> I'd prefer the latter. These struct io_restrictions could then be used
> by dm (which has it's own version right now) to merge queue capabilities.
Yeah, we could nicely handle lld's restrictions (especially with
stacking devices). But iommu code needs only max_segment_size and
seg_boundary_mask, right? If so, the first simple approach to add two
values to device structure is not so bad, I think.
^ permalink raw reply
* Re: PROBLEM: 2.6.23-rc "NETDEV WATCHDOG: eth0: transmit timed out"
From: Karl Meyer @ 2007-09-26 9:07 UTC (permalink / raw)
To: Francois Romieu; +Cc: Michal Piotrowski, linux-kernel, netdev
In-Reply-To: <20070912205025.GA31709@electric-eye.fr.zoreil.com>
Hi Francois,
this is what I found and sent:
The error exists from patch 2 on. I did some network testing with
patch 1 and currently use it and have no errors so far.
>From my experiences up to now patch 1 should be error free.
Do you need additional info?
2007/9/12, Francois Romieu <romieu@fr.zoreil.com>:
> Karl Meyer <adhocrocker@gmail.com> :
> [...]
> > am am looking for this issue for some time now, but there where no
> > errors in 2.6.22-r2 (gentoo speak, I guess this is 2.6.22.2
> > officially), I also ran git-bisect (for more information see the older
> > messages in this thread).
>
> 2.6.22-r2 in gentoo is based on 2.6.22.1. It is way before
> 0e4851502f846b13b29b7f88f1250c980d57e944 that you reported to work.
> Thus it is not surprizing that it works.
>
> Any update regarding the patchkit that I sent on 2007/08/16 ?
>
> It would help to narrow the culprit.
>
> --
> Ueimor
>
^ permalink raw reply
* Re: [PATCH] ipg: add IP1000A driver to kernel tree
From: linux @ 2007-09-26 9:46 UTC (permalink / raw)
To: netdev
(Resend to netdev; already sent to relevant individuals.)
Here's a possible fix for the p[] array issues akpm noticed.
This replaces them with calls to a new mdio_write_bits function.
Boot-tested, passes net traffic, and mii-tool and mii-diag produce sensible
output (including noticing link status changes).
Also, regarding
>> + for (i = 0; i < IPG_TFDLIST_LENGTH; i++) {
>> + offset = (u32) &sp->txd[i].next_desc - (u32) sp->txd;
>> + printk(KERN_INFO "%2.2x %4.4x TFDNextPtr = %16.16lx\n", i,
>> + offset, (unsigned long) sp->txd[i].next_desc);
>> +
>> + offset = (u32) &sp->txd[i].tfc - (u32) sp->txd;
>
> Is the u32 cast safe here on all architectures?
IPG_TFDLIST_LENGTH is 256, and sp->txd is an array of struct ipg_tx,
which are 24 bytes each, so the most it can be is 6K. The result fits
into 32 bits, so the inputs can be safely truncated.
A more awkward way to write it would be
offset = i * sizeof(struct ipg_tx) + offsetof(struct ipg_tx, tfc);
This patch is placed in the public domain; copyright abandoned.
(The final hunk is a space-TAB whitespace repair that git complained about
when I imported the patch.)
diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c
index 87a674c..6267a34 100644
--- a/drivers/net/ipg.c
+++ b/drivers/net/ipg.c
@@ -180,12 +180,31 @@ static u16 read_phy_bit(void __iomem * ioaddr, u8 phyctrlpolarity)
}
/*
+ * Transmit the given bits, MSB-first, through the MgmtData bit (bit 1)
+ * of the PhyCtrl register. 1 <= len <= 32. "ioaddr" is the register
+ * address, and "otherbits" are the values of the other bits.
+ */
+static void mdio_write_bits(void __iomem *ioaddr, u8 otherbits, u32 data, unsigned len)
+{
+ otherbits |= IPG_PC_MGMTDIR;
+ do {
+ /* IPG_PC_MGMTDATA is a power of 2; compiler knows to shift */
+ u8 d = ((data >> --len) & 1) * IPG_PC_MGMTDATA;
+ /* + rather than | lets compiler microoptimize better */
+ ipg_drive_phy_ctl_low_high(ioaddr, d + otherbits);
+ } while (len);
+}
+
+/*
* Read a register from the Physical Layer device located
* on the IPG NIC, using the IPG PHYCTRL register.
*/
static int mdio_read(struct net_device * dev, int phy_id, int phy_reg)
{
void __iomem *ioaddr = ipg_ioaddr(dev);
+ u8 const polarity = ipg_r8(PHY_CTRL) &
+ (IPG_PC_DUPLEX_POLARITY | IPG_PC_LINK_POLARITY);
+ unsigned i, data = 0;
/*
* The GMII mangement frame structure for a read is as follows:
*
@@ -199,75 +218,30 @@ static int mdio_read(struct net_device * dev, int phy_id, int phy_reg)
* D = bit of read data (MSB first)
*
* Transmission order is 'Preamble' field first, bits transmitted
- * left to right (first to last).
+ * left to right (msbit-first).
*/
- struct {
- u32 field;
- unsigned int len;
- } p[] = {
- { GMII_PREAMBLE, 32 }, /* Preamble */
- { GMII_ST, 2 }, /* ST */
- { GMII_READ, 2 }, /* OP */
- { phy_id, 5 }, /* PHYAD */
- { phy_reg, 5 }, /* REGAD */
- { 0x0000, 2 }, /* TA */
- { 0x0000, 16 }, /* DATA */
- { 0x0000, 1 } /* IDLE */
- };
- unsigned int i, j;
- u8 polarity, data;
-
- polarity = ipg_r8(PHY_CTRL);
- polarity &= (IPG_PC_DUPLEX_POLARITY | IPG_PC_LINK_POLARITY);
-
- /* Create the Preamble, ST, OP, PHYAD, and REGAD field. */
- for (j = 0; j < 5; j++) {
- for (i = 0; i < p[j].len; i++) {
- /* For each variable length field, the MSB must be
- * transmitted first. Rotate through the field bits,
- * starting with the MSB, and move each bit into the
- * the 1st (2^1) bit position (this is the bit position
- * corresponding to the MgmtData bit of the PhyCtrl
- * register for the IPG).
- *
- * Example: ST = 01;
- *
- * First write a '0' to bit 1 of the PhyCtrl
- * register, then write a '1' to bit 1 of the
- * PhyCtrl register.
- *
- * To do this, right shift the MSB of ST by the value:
- * [field length - 1 - #ST bits already written]
- * then left shift this result by 1.
- */
- data = (p[j].field >> (p[j].len - 1 - i)) << 1;
- data &= IPG_PC_MGMTDATA;
- data |= polarity | IPG_PC_MGMTDIR;
-
- ipg_drive_phy_ctl_low_high(ioaddr, data);
- }
- }
-
- send_three_state(ioaddr, polarity);
-
- read_phy_bit(ioaddr, polarity);
+ mdio_write_bits(ioaddr, polarity, GMII_PREAMBLE, 32);
+ mdio_write_bits(ioaddr, polarity, GMII_ST<<12 | GMII_READ << 10 |
+ phy_id << 5 | phy_reg, 14);
/*
* For a read cycle, the bits for the next two fields (TA and
* DATA) are driven by the PHY (the IPG reads these bits).
*/
- for (i = 0; i < p[6].len; i++) {
- p[6].field |=
- (read_phy_bit(ioaddr, polarity) << (p[6].len - 1 - i));
- }
+ send_three_state(ioaddr, polarity); /* TA first bit */
+ (void)read_phy_bit(ioaddr, polarity); /* TA second bit */
+ for (i = 0; i < 16; i++)
+ data += data + read_phy_bit(ioaddr, polarity);
+
+ /* Trailing idle */
send_three_state(ioaddr, polarity);
send_three_state(ioaddr, polarity);
send_three_state(ioaddr, polarity);
send_end(ioaddr, polarity);
/* Return the value of the DATA field. */
- return p[6].field;
+ return data;
}
/*
@@ -277,6 +251,8 @@ static int mdio_read(struct net_device * dev, int phy_id, int phy_reg)
static void mdio_write(struct net_device *dev, int phy_id, int phy_reg, int val)
{
void __iomem *ioaddr = ipg_ioaddr(dev);
+ u8 const polarity = ipg_r8(PHY_CTRL) &
+ (IPG_PC_DUPLEX_POLARITY | IPG_PC_LINK_POLARITY);
/*
* The GMII mangement frame structure for a read is as follows:
*
@@ -290,66 +266,18 @@ static void mdio_write(struct net_device *dev, int phy_id, int phy_reg, int val)
* D = bit of write data (MSB first)
*
* Transmission order is 'Preamble' field first, bits transmitted
- * left to right (first to last).
+ * left to right (msbit-first).
*/
- struct {
- u32 field;
- unsigned int len;
- } p[] = {
- { GMII_PREAMBLE, 32 }, /* Preamble */
- { GMII_ST, 2 }, /* ST */
- { GMII_WRITE, 2 }, /* OP */
- { phy_id, 5 }, /* PHYAD */
- { phy_reg, 5 }, /* REGAD */
- { 0x0002, 2 }, /* TA */
- { val & 0xffff, 16 }, /* DATA */
- { 0x0000, 1 } /* IDLE */
- };
- unsigned int i, j;
- u8 polarity, data;
-
- polarity = ipg_r8(PHY_CTRL);
- polarity &= (IPG_PC_DUPLEX_POLARITY | IPG_PC_LINK_POLARITY);
-
- /* Create the Preamble, ST, OP, PHYAD, and REGAD field. */
- for (j = 0; j < 7; j++) {
- for (i = 0; i < p[j].len; i++) {
- /* For each variable length field, the MSB must be
- * transmitted first. Rotate through the field bits,
- * starting with the MSB, and move each bit into the
- * the 1st (2^1) bit position (this is the bit position
- * corresponding to the MgmtData bit of the PhyCtrl
- * register for the IPG).
- *
- * Example: ST = 01;
- *
- * First write a '0' to bit 1 of the PhyCtrl
- * register, then write a '1' to bit 1 of the
- * PhyCtrl register.
- *
- * To do this, right shift the MSB of ST by the value:
- * [field length - 1 - #ST bits already written]
- * then left shift this result by 1.
- */
- data = (p[j].field >> (p[j].len - 1 - i)) << 1;
- data &= IPG_PC_MGMTDATA;
- data |= polarity | IPG_PC_MGMTDIR;
-
- ipg_drive_phy_ctl_low_high(ioaddr, data);
- }
- }
+ mdio_write_bits(ioaddr, polarity, GMII_PREAMBLE, 32);
+ mdio_write_bits(ioaddr, polarity, GMII_ST << 14 | GMII_WRITE << 12 |
+ phy_id << 7 | phy_reg << 2 |
+ 0x2, 16);
+ mdio_write_bits(ioaddr, polarity, val, 16); /* DATA */
/* The last cycle is a tri-state, so read from the PHY. */
- for (j = 7; j < 8; j++) {
- for (i = 0; i < p[j].len; i++) {
- ipg_write_phy_ctl(ioaddr, IPG_PC_MGMTCLK_LO | polarity);
-
- p[j].field |= ((ipg_r8(PHY_CTRL) &
- IPG_PC_MGMTDATA) >> 1) << (p[j].len - 1 - i);
-
- ipg_write_phy_ctl(ioaddr, IPG_PC_MGMTCLK_HI | polarity);
- }
- }
+ ipg_write_phy_ctl(ioaddr, IPG_PC_MGMTCLK_LO | polarity);
+ (void)ipg_r8(PHY_CTRL);
+ ipg_write_phy_ctl(ioaddr, IPG_PC_MGMTCLK_HI | polarity);
}
/* Set LED_Mode JES20040127EEPROM */
@@ -1484,7 +1412,7 @@ static int ipg_nic_rx(struct net_device *dev)
* Indicate IP checksums were performed
* by the IPG.
*
- skb->ip_summed = CHECKSUM_UNNECESSARY;
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
} else
*/
{
^ permalink raw reply related
* Re: Userspace network stack and netchannels.
From: Robert Iakobashvili @ 2007-09-26 10:43 UTC (permalink / raw)
To: Evgeniy Polyakov; +Cc: netdev
In-Reply-To: <20070926085303.GB13187@2ka.mipt.ru>
On 9/26/07, Evgeniy Polyakov <johnpol@2ka.mipt.ru> wrote:
> > > http://tservice.net.ru/~s0mbre/blog/devel/networking/2006_10_26.html
> > > http://tservice.net.ru/~s0mbre/blog/devel/networking/2006_12_21.html
> > >
> >
> > Very interesting. Are there any details of your benchmarking available,
> > namely, how it was done?
> > Have you some comparison profiling data (oprofile) to figure out where
> > the advantages are coming from?
> My analysis says that reduced number of syscalls is
> main improvement factor,
Great! Just oprofile of the comparison tests is of my curiosity.
> but different (non-rfc-compliant) congestion
> control allows faster start and faster recovery.
People like compliance to standards, even if it decreases performance.
:) Take care.
--
Sincerely,
Robert Iakobashvili,
coroberti %x40 gmail %x2e com
...........................................................
http://curl-loader.sourceforge.net
A web testing and traffic generation tool.
^ permalink raw reply
* Re: [SCTP PULL Request]: Bug fixes for 2.6.23
From: Vlad Yasevich @ 2007-09-26 13:02 UTC (permalink / raw)
To: David Miller; +Cc: netdev, lksctp-developers
In-Reply-To: <20070925.225330.60538571.davem@davemloft.net>
David Miller wrote:
> From: Vlad Yasevich <vladislav.yasevich@hp.com>
> Date: Mon, 24 Sep 2007 16:59:25 -0400
>
>> Can you please pull the following changes since commit a41d3015c11a4e864b95cb57f579f2d8f40cd41b:
>
> I had to apply this by hand because:
>
>> David S. Miller (1):
>> Revert "PCI: disable MSI by default on systems with Serverworks HT1000 chips"
>
> You did this work on a very old tree of mine that I redid
> at one point. This MSI changeset I yanked out of my net-2.6
> tree during a rebase, so if I pull I get the thing back
> which I definitely don't want :-)
>
> Just to let you know what's happening and why I couldn't
> pull directly from your tree into mine.
Sorry, this was my fault. I forgot the -f when I pushed out the changes. That
should have updated the tree.
/me adds a + to the push line.
-vlad
^ permalink raw reply
* Re: net-2.6.24 rebased...
From: John W. Linville @ 2007-09-26 12:46 UTC (permalink / raw)
To: David Miller; +Cc: netdev, jeff, akpm
In-Reply-To: <20070925.233344.43202361.davem@davemloft.net>
On Tue, Sep 25, 2007 at 11:33:44PM -0700, David Miller wrote:
> John, one patch didn't go in cleanly after I removed the
> Z1211 driver. I put it here for your consideration so it
> doesn't get lost:
>
> http://vger.kernel.org/~davem/0433-Z1211-Fix-TX-status-reports.patch
>
> What probably needs to happen is some other changes that
> were in z1211 need to go into the non-mac80211 driver and
> then this patch applies correctly.
I have that one, so we're fine. It is a mac80211-specific fix,
so I think that takes care of it.
Thanks!
John
--
John W. Linville
linville@tuxdriver.com
^ permalink raw reply
* Re: Userspace network stack and netchannels.
From: jamal @ 2007-09-26 13:08 UTC (permalink / raw)
To: Evgeniy Polyakov; +Cc: netdev
In-Reply-To: <20070925180043.GA16698@2ka.mipt.ru>
Evgeniy,
Those numbers look impressive. How mysterious do things get in SMP?
Sorry havent had time to stare at the code. How do you measure cpu you
quoted?
cheers,
jamal
^ permalink raw reply
* Re: [RFC][NET_SCHED] explict hold dev tx lock
From: jamal @ 2007-09-26 13:11 UTC (permalink / raw)
To: David Miller; +Cc: herbert, netdev, kaber, dada1, johnpol
In-Reply-To: <20070925.192811.08341847.davem@davemloft.net>
On Tue, 2007-25-09 at 19:28 -0700, David Miller wrote:
> I've applied this to net-2.6.24, although I want to study more deeply
> the implications of this change myself at some point :)
sounds reasonable. Ive done a lot of testing with my 2-3 NIC variants;
ive cced whoever i thought was a stakeholder and they ALL seemed
silently-happy-joyous (wink;->), so letting more people go at it is the
best thing to do. I will be watching that space.
cheers,
jamal
^ permalink raw reply
* Re: Userspace network stack and netchannels.
From: Evgeniy Polyakov @ 2007-09-26 13:22 UTC (permalink / raw)
To: jamal; +Cc: netdev
In-Reply-To: <1190812125.4257.2.camel@localhost>
Hi Jamal.
On Wed, Sep 26, 2007 at 09:08:45AM -0400, jamal (hadi@cyberus.ca) wrote:
> Those numbers look impressive. How mysterious do things get in SMP?
> Sorry havent had time to stare at the code. How do you measure cpu you
> quoted?
I did not checked how netchannels and userspace stack behaves on SMP
just because I do not have SMP test machines. Getting into account that
netchannels have smaller number of locks (actually only one to queue
skb) compared to sockets, it should not behave worse, but I did not test
that.
CPU usage was obtained via /proc/$pid statistics.
--
Evgeniy Polyakov
^ permalink raw reply
* Re: [PATCH: 2.6.13-15-SMP 3/3] network: concurrentlyrunsoftirqnetwork code on SMP
From: jamal @ 2007-09-26 13:26 UTC (permalink / raw)
To: John Ye
Cc: Stephen Hemminger, David Miller, netdev, kuznet, pekkas, jmorris,
kaber, iceburgue
In-Reply-To: <004d01c7ffe2$b73fec20$ca8510ac@asimco>
On Wed, 2007-26-09 at 10:12 +0800, John Ye wrote:
> cpu hash (srcip + dstip) % nr_cpus, plus checking cpu balance periodically,
> shift cpu by an extra seed value?
That may work maybe even add ipproto as a 3rd tuple; experiments will
tell - you need to be able to generate a random enough traffic pattern.
For example if the traffic pattern is always for your local host the
dstip may not be useful to the hash.
You could always try the hash tests outside first; look at some of the
jenkins hashes in the kernel
> __do_IRQ has a tendency to collect same IRQ on different CPUs into one CPU
> when NIC is busy(by IRQ_PENDING & IRQ_INPROGRESS control skill). so,
> dispatch the load to SMP here may be good thing(?).
possibly. Or you may wanna tie the NIC IRQ to a CPU.
cheers,
jamal
^ permalink raw reply
* [PATCH] [TCP] MIB: Fine-tune reordered ACK's SACK block counting more
From: Ilpo Järvinen @ 2007-09-26 14:07 UTC (permalink / raw)
To: David Miller; +Cc: Netdev
In-Reply-To: <20070925.224711.26514452.davem@davemloft.net>
[-- Attachment #1: Type: TEXT/PLAIN, Size: 4110 bytes --]
On Tue, 25 Sep 2007, David Miller wrote:
> From: "Ilpo_Järvinen" <ilpo.jarvinen@helsinki.fi>
> Date: Mon, 24 Sep 2007 12:04:07 +0300
>
> > In case of ACK reordering, the SACK block might be valid in it's
> > time but is already obsoleted since we've received another kind
> > of confirmation about arrival of the segments through snd_una
> > advancement of an earlier packet.
> >
> > I didn't bother to build distinguishing of valid and invalid
> > SACK blocks but simply made reordered SACK blocks that are too
> > old always not counted regardless of their "real" validity which
> > could be determined by using the ack field of the reordered
> > packet (won't be significant IMHO).
> >
> > DSACKs can very well be considered useful even in this situation,
> > so won't do any of this for them.
> >
> > Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
>
> This looks fine to me, applied.
>
> If the skipped case is interesting we can add another MIB
> stat for it :-)
Hmm, thought a bit more about it... How about this then? No additional
counter. Compile tested. Not that I see a large benefit from it, in theory
could help logging in some malicious attempt cases; we safely discarded in
such case anyway... ...of course if somebody is paranoid enough one might
rejoice in it more than I do... :-) Buggy cases will very likely show up
regardless this reordering corner-case.
From: =?ISO-8859-1?q?Ilpo_J=E4rvinen?= <ilpo.jarvinen@helsinki.fi>
Date: Wed, 26 Sep 2007 14:17:12 +0300
Subject: [PATCH] [TCP] MIB: Fine-tune reordered ACK's SACK block counting more
Check the SACK block against the state that TCP was in at the
time of that ACK. Not really since we can summon just snd_una
back and not snd_nxt but that shouldn't be a problem. Reused
checking code which avoids adding other nasty wrap, etc. holes.
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
---
net/ipv4/tcp_input.c | 17 +++++++++++------
1 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 259f517..95c8a4a 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1063,7 +1063,7 @@ static void tcp_update_reordering(struct sock *sk, const int metric,
* be used as an exaggerated estimate.
*/
static int tcp_is_sackblock_valid(struct tcp_sock *tp, int is_dsack,
- u32 start_seq, u32 end_seq)
+ u32 start_seq, u32 end_seq, u32 snd_una)
{
/* Too far in future, or reversed (interpretation is ambiguous) */
if (after(end_seq, tp->snd_nxt) || !before(start_seq, end_seq))
@@ -1076,14 +1076,14 @@ static int tcp_is_sackblock_valid(struct tcp_sock *tp, int is_dsack,
/* In outstanding window? ...This is valid exit for DSACKs too.
* start_seq == snd_una is non-sensical (see comments above)
*/
- if (after(start_seq, tp->snd_una))
+ if (after(start_seq, snd_una))
return 1;
if (!is_dsack || !tp->undo_marker)
return 0;
/* ...Then it's D-SACK, and must reside below snd_una completely */
- if (!after(end_seq, tp->snd_una))
+ if (!after(end_seq, snd_una))
return 0;
if (!before(start_seq, tp->undo_marker))
@@ -1244,16 +1244,21 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
int fack_count;
int dup_sack = (found_dup_sack && (i == first_sack_index));
- if (!tcp_is_sackblock_valid(tp, dup_sack, start_seq, end_seq)) {
+ if (!tcp_is_sackblock_valid(tp, dup_sack, start_seq, end_seq,
+ tp->snd_una)) {
if (dup_sack) {
if (!tp->undo_marker)
NET_INC_STATS_BH(LINUX_MIB_TCPDSACKIGNOREDNOUNDO);
else
NET_INC_STATS_BH(LINUX_MIB_TCPDSACKIGNOREDOLD);
} else {
- /* Don't count olds caused by ACK reordering */
+ /* Don't count old SACK blocks caused by ACK
+ * reordering if it was valid back then
+ */
if ((TCP_SKB_CB(ack_skb)->ack_seq != tp->snd_una) &&
- !after(end_seq, tp->snd_una))
+ tcp_is_sackblock_valid(tp, dup_sack,
+ start_seq, end_seq,
+ TCP_SKB_CB(ack_skb)->ack_seq))
continue;
NET_INC_STATS_BH(LINUX_MIB_TCPSACKDISCARD);
}
--
1.5.0.6
^ permalink raw reply related
* e100 problems in .23rc8 ?
From: Dave Jones @ 2007-09-26 15:04 UTC (permalink / raw)
To: netdev
Last night, I hit this bug during boot up..
http://www.codemonkey.org.uk/junk/e100-2.jpg
This morning, I got a mail from a Fedora user of the same
.23-rc8 based kernel that has seen a different trace
also implicating e100..
http://www.codemonkey.org.uk/junk/e100.jpg
It may be that the two problems are unrelated, and it's
just coincidence that both reports happen to be on an e100,
but the timing is odd. Have there been other reports
of similar problems recently ?
Dave
--
http://www.codemonkey.org.uk
^ permalink raw reply
* Re: [RFC] Zero-length write() does not generate a datagram on connected socket
From: Rick Jones @ 2007-09-26 17:17 UTC (permalink / raw)
To: Herbert Xu; +Cc: Stephen Hemminger, netdev
In-Reply-To: <E1IaNQ7-0004DX-00@gondolin.me.apana.org.au>
Herbert Xu wrote:
> Stephen Hemminger <shemminger@linux-foundation.org> wrote:
>
>>The bug http://bugzilla.kernel.org/show_bug.cgi?id=5731
>>describes an issue where write() can't be used to generate a zero-length
>>datagram (but send, and sendto do work).
>>
>>I think the following is needed:
>>
>>--- a/net/socket.c 2007-08-20 09:54:28.000000000 -0700
>>+++ b/net/socket.c 2007-09-24 15:31:25.000000000 -0700
>>@@ -777,8 +777,11 @@ static ssize_t sock_aio_write(struct kio
>> if (pos != 0)
>> return -ESPIPE;
>>
>>- if (iocb->ki_left == 0) /* Match SYS5 behaviour */
>>- return 0;
>>+ if (unlikely(iocb->ki_left == 0)) {
>>+ struct socket *sock = iocb->ki_filp->private_data;
>>+ if (sock->type == SOCK_STREAM)
>>+ return 0;
>>+ }
>
>
> I'm not sure whether all STREAM protocols treat zero-length
> sends as no-ops. What about SCTP?
I asked Vlad that very question, since SCTP can preserve message
boundaries. He tells me that a zero-length message is not part of SCTP.
rick jones
^ permalink raw reply
* Re: e100 problems in .23rc8 ?
From: Kok, Auke @ 2007-09-26 18:10 UTC (permalink / raw)
To: Dave Jones; +Cc: netdev
In-Reply-To: <20070926150447.GA3761@redhat.com>
Dave Jones wrote:
> Last night, I hit this bug during boot up..
> http://www.codemonkey.org.uk/junk/e100-2.jpg
>
> This morning, I got a mail from a Fedora user of the same
> .23-rc8 based kernel that has seen a different trace
> also implicating e100..
>
> http://www.codemonkey.org.uk/junk/e100.jpg
>
> It may be that the two problems are unrelated, and it's
> just coincidence that both reports happen to be on an e100,
> but the timing is odd. Have there been other reports
> of similar problems recently ?
there hasn't been a change to e100 in two months now - perhaps something slipped
into the stack that broke it? If this reproduces, could you bisect?
Auke
^ permalink raw reply
* Re: e100 problems in .23rc8 ?
From: Dave Jones @ 2007-09-26 18:18 UTC (permalink / raw)
To: Kok, Auke; +Cc: netdev
In-Reply-To: <46FAA083.9020604@intel.com>
On Wed, Sep 26, 2007 at 11:10:11AM -0700, Kok, Auke wrote:
> Dave Jones wrote:
> > Last night, I hit this bug during boot up..
> > http://www.codemonkey.org.uk/junk/e100-2.jpg
> >
> > This morning, I got a mail from a Fedora user of the same
> > .23-rc8 based kernel that has seen a different trace
> > also implicating e100..
> >
> > http://www.codemonkey.org.uk/junk/e100.jpg
> >
> > It may be that the two problems are unrelated, and it's
> > just coincidence that both reports happen to be on an e100,
> > but the timing is odd. Have there been other reports
> > of similar problems recently ?
>
> there hasn't been a change to e100 in two months now - perhaps something slipped
> into the stack that broke it? If this reproduces, could you bisect?
Yeah, I notice only 3 changes to e100 since .22
I'll see if I can reproduce the first one and bisect.
Dave
--
http://www.codemonkey.org.uk
^ permalink raw reply
* Re: [RFC] Zero-length write() does not generate a datagram on connected socket
From: Vlad Yasevich @ 2007-09-26 18:47 UTC (permalink / raw)
To: Herbert Xu; +Cc: Stephen Hemminger, netdev
In-Reply-To: <E1IaNQ7-0004DX-00@gondolin.me.apana.org.au>
Herbert Xu wrote:
> Stephen Hemminger <shemminger@linux-foundation.org> wrote:
>> The bug http://bugzilla.kernel.org/show_bug.cgi?id=5731
>> describes an issue where write() can't be used to generate a zero-length
>> datagram (but send, and sendto do work).
>>
>> I think the following is needed:
>>
>> --- a/net/socket.c 2007-08-20 09:54:28.000000000 -0700
>> +++ b/net/socket.c 2007-09-24 15:31:25.000000000 -0700
>> @@ -777,8 +777,11 @@ static ssize_t sock_aio_write(struct kio
>> if (pos != 0)
>> return -ESPIPE;
>>
>> - if (iocb->ki_left == 0) /* Match SYS5 behaviour */
>> - return 0;
>> + if (unlikely(iocb->ki_left == 0)) {
>> + struct socket *sock = iocb->ki_filp->private_data;
>> + if (sock->type == SOCK_STREAM)
>> + return 0;
>> + }
>
> I'm not sure whether all STREAM protocols treat zero-length
> sends as no-ops. What about SCTP?
0 byte writes are not allowed in SCTP. A no-op is fine, otherwise
SCTP would return an error.
-vlad
>
> Put it another way, do we really need to keep the short-circuit
> for SOCK_STREAM?
>
> Cheers,
^ permalink raw reply
* Re: [ofa-general] [PATCH v3] iw_cxgb3: Support "iwarp-only" interfaces to avoid 4-tuple conflicts.
From: Steve Wise @ 2007-09-26 19:02 UTC (permalink / raw)
To: rdreier, sean.hefty; +Cc: netdev, linux-kernel, general
In-Reply-To: <20070923203649.8324.64524.stgit@dell3.ogc.int>
Rolan/Sean,
What do you all think?
Steve.
Steve Wise wrote:
> iw_cxgb3: Support "iwarp-only" interfaces to avoid 4-tuple conflicts.
>
> Version 3:
>
> - don't use list_del_init() where list_del() is sufficient.
>
> Version 2:
>
> - added a per-device mutex for the address and listening endpoints lists.
>
> - wait for all replies if sending multiple passive_open requests to rnic.
>
> - log warning if no addresses are available when a listen is issued.
>
> - tested
>
> ---
>
> Design:
>
> The sysadmin creates "for iwarp use only" alias interfaces of the form
> "devname:iw*" where devname is the native interface name (eg eth0) for the
> iwarp netdev device. The alias label can be anything starting with "iw".
> The "iw" immediately after the ':' is the key used by the iw_cxgb3 driver.
>
> EG:
> ifconfig eth0 192.168.70.123 up
> ifconfig eth0:iw1 192.168.71.123 up
> ifconfig eth0:iw2 192.168.72.123 up
>
> In the above example, 192.168.70/24 is for TCP traffic, while
> 192.168.71/24 and 192.168.72/24 are for iWARP/RDMA use.
>
> The rdma-only interface must be on its own IP subnet. This allows routing
> all rdma traffic onto this interface.
>
> The iWARP driver must translate all listens on address 0.0.0.0 to the
> set of rdma-only ip addresses for the device in question. This prevents
> incoming connect requests to the TCP ipaddresses from going up the
> rdma stack.
>
> Implementation Details:
>
> - The iw_cxgb3 driver registers for inetaddr events via
> register_inetaddr_notifier(). This allows tracking the iwarp-only
> addresses/subnets as they get added and deleted. The iwarp driver
> maintains a list of the current iwarp-only addresses.
>
> - The iw_cxgb3 driver builds the list of iwarp-only addresses for its
> devices at module insert time. This is needed because the inetaddr
> notifier callbacks don't "replay" address-add events when someone
> registers. So the driver must build the initial list at module load time.
>
> - When a listen is done on address 0.0.0.0, then the iw_cxgb3 driver
> must translate that into a set of listens on the iwarp-only addresses.
> This is implemented by maintaining a list of stid/addr entries per
> listening endpoint.
>
> - When a new iwarp-only address is added or removed, the iw_cxgb3 driver
> must traverse the set of listening endpoints and update them accordingly.
> This allows an application to bind to 0.0.0.0 prior to the iwarp-only
> interfaces being configured. It also allows changing the iwarp-only set
> of addresses and getting the expected behavior for apps already bound
> to 0.0.0.0. This is done by maintaining a list of listening endpoints
> off the device struct.
>
> - The address list, the listening endpoint list, and each list of
> stid/addrs in use per listening endpoint are all protected via a mutex
> per iw_cxgb3 device.
>
> Signed-off-by: Steve Wise <swise@opengridcomputing.com>
> ---
>
> drivers/infiniband/hw/cxgb3/iwch.c | 125 ++++++++++++++++
> drivers/infiniband/hw/cxgb3/iwch.h | 11 +
> drivers/infiniband/hw/cxgb3/iwch_cm.c | 259 +++++++++++++++++++++++++++------
> drivers/infiniband/hw/cxgb3/iwch_cm.h | 15 ++
> 4 files changed, 360 insertions(+), 50 deletions(-)
>
> diff --git a/drivers/infiniband/hw/cxgb3/iwch.c b/drivers/infiniband/hw/cxgb3/iwch.c
> index 0315c9d..d81d46e 100644
> --- a/drivers/infiniband/hw/cxgb3/iwch.c
> +++ b/drivers/infiniband/hw/cxgb3/iwch.c
> @@ -63,6 +63,123 @@ struct cxgb3_client t3c_client = {
> static LIST_HEAD(dev_list);
> static DEFINE_MUTEX(dev_mutex);
>
> +static void insert_ifa(struct iwch_dev *rnicp, struct in_ifaddr *ifa)
> +{
> + struct iwch_addrlist *addr;
> +
> + addr = kmalloc(sizeof *addr, GFP_KERNEL);
> + if (!addr) {
> + printk(KERN_ERR MOD "%s - failed to alloc memory!\n",
> + __FUNCTION__);
> + return;
> + }
> + addr->ifa = ifa;
> + mutex_lock(&rnicp->mutex);
> + list_add_tail(&addr->entry, &rnicp->addrlist);
> + mutex_unlock(&rnicp->mutex);
> +}
> +
> +static void remove_ifa(struct iwch_dev *rnicp, struct in_ifaddr *ifa)
> +{
> + struct iwch_addrlist *addr, *tmp;
> +
> + mutex_lock(&rnicp->mutex);
> + list_for_each_entry_safe(addr, tmp, &rnicp->addrlist, entry) {
> + if (addr->ifa == ifa) {
> + list_del(&addr->entry);
> + kfree(addr);
> + goto out;
> + }
> + }
> +out:
> + mutex_unlock(&rnicp->mutex);
> +}
> +
> +static int netdev_is_ours(struct iwch_dev *rnicp, struct net_device *netdev)
> +{
> + int i;
> +
> + for (i = 0; i < rnicp->rdev.port_info.nports; i++)
> + if (netdev == rnicp->rdev.port_info.lldevs[i])
> + return 1;
> + return 0;
> +}
> +
> +static inline int is_iwarp_label(char *label)
> +{
> + char *colon;
> +
> + colon = strchr(label, ':');
> + if (colon && !strncmp(colon+1, "iw", 2))
> + return 1;
> + return 0;
> +}
> +
> +static int nb_callback(struct notifier_block *self, unsigned long event,
> + void *ctx)
> +{
> + struct in_ifaddr *ifa = ctx;
> + struct iwch_dev *rnicp = container_of(self, struct iwch_dev, nb);
> +
> + PDBG("%s rnicp %p event %lx\n", __FUNCTION__, rnicp, event);
> +
> + switch (event) {
> + case NETDEV_UP:
> + if (netdev_is_ours(rnicp, ifa->ifa_dev->dev) &&
> + is_iwarp_label(ifa->ifa_label)) {
> + PDBG("%s label %s addr 0x%x added\n",
> + __FUNCTION__, ifa->ifa_label, ifa->ifa_address);
> + insert_ifa(rnicp, ifa);
> + iwch_listeners_add_addr(rnicp, ifa->ifa_address);
> + }
> + break;
> + case NETDEV_DOWN:
> + if (netdev_is_ours(rnicp, ifa->ifa_dev->dev) &&
> + is_iwarp_label(ifa->ifa_label)) {
> + PDBG("%s label %s addr 0x%x deleted\n",
> + __FUNCTION__, ifa->ifa_label, ifa->ifa_address);
> + iwch_listeners_del_addr(rnicp, ifa->ifa_address);
> + remove_ifa(rnicp, ifa);
> + }
> + break;
> + default:
> + break;
> + }
> + return 0;
> +}
> +
> +static void delete_addrlist(struct iwch_dev *rnicp)
> +{
> + struct iwch_addrlist *addr, *tmp;
> +
> + mutex_lock(&rnicp->mutex);
> + list_for_each_entry_safe(addr, tmp, &rnicp->addrlist, entry) {
> + list_del(&addr->entry);
> + kfree(addr);
> + }
> + mutex_unlock(&rnicp->mutex);
> +}
> +
> +static void populate_addrlist(struct iwch_dev *rnicp)
> +{
> + int i;
> + struct in_device *indev;
> +
> + for (i = 0; i < rnicp->rdev.port_info.nports; i++) {
> + indev = in_dev_get(rnicp->rdev.port_info.lldevs[i]);
> + if (!indev)
> + continue;
> + for_ifa(indev)
> + if (is_iwarp_label(ifa->ifa_label)) {
> + PDBG("%s label %s addr 0x%x added\n",
> + __FUNCTION__, ifa->ifa_label,
> + ifa->ifa_address);
> + insert_ifa(rnicp, ifa);
> + }
> + endfor_ifa(indev);
> + }
> +}
> +
> static void rnic_init(struct iwch_dev *rnicp)
> {
> PDBG("%s iwch_dev %p\n", __FUNCTION__, rnicp);
> @@ -70,6 +187,12 @@ static void rnic_init(struct iwch_dev *r
> idr_init(&rnicp->qpidr);
> idr_init(&rnicp->mmidr);
> spin_lock_init(&rnicp->lock);
> + INIT_LIST_HEAD(&rnicp->addrlist);
> + INIT_LIST_HEAD(&rnicp->listen_eps);
> + mutex_init(&rnicp->mutex);
> + rnicp->nb.notifier_call = nb_callback;
> + populate_addrlist(rnicp);
> + register_inetaddr_notifier(&rnicp->nb);
>
> rnicp->attr.vendor_id = 0x168;
> rnicp->attr.vendor_part_id = 7;
> @@ -148,6 +271,8 @@ static void close_rnic_dev(struct t3cdev
> mutex_lock(&dev_mutex);
> list_for_each_entry_safe(dev, tmp, &dev_list, entry) {
> if (dev->rdev.t3cdev_p == tdev) {
> + unregister_inetaddr_notifier(&dev->nb);
> + delete_addrlist(dev);
> list_del(&dev->entry);
> iwch_unregister_device(dev);
> cxio_rdev_close(&dev->rdev);
> diff --git a/drivers/infiniband/hw/cxgb3/iwch.h b/drivers/infiniband/hw/cxgb3/iwch.h
> index caf4e60..7fa0a47 100644
> --- a/drivers/infiniband/hw/cxgb3/iwch.h
> +++ b/drivers/infiniband/hw/cxgb3/iwch.h
> @@ -36,6 +36,8 @@ #include <linux/mutex.h>
> #include <linux/list.h>
> #include <linux/spinlock.h>
> #include <linux/idr.h>
> +#include <linux/notifier.h>
> +#include <linux/inetdevice.h>
>
> #include <rdma/ib_verbs.h>
>
> @@ -101,6 +103,11 @@ struct iwch_rnic_attributes {
> u32 cq_overflow_detection;
> };
>
> +struct iwch_addrlist {
> + struct list_head entry;
> + struct in_ifaddr *ifa;
> +};
> +
> struct iwch_dev {
> struct ib_device ibdev;
> struct cxio_rdev rdev;
> @@ -111,6 +118,10 @@ struct iwch_dev {
> struct idr mmidr;
> spinlock_t lock;
> struct list_head entry;
> + struct notifier_block nb;
> + struct list_head addrlist;
> + struct list_head listen_eps;
> + struct mutex mutex;
> };
>
> static inline struct iwch_dev *to_iwch_dev(struct ib_device *ibdev)
> diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
> index 1cdfcd4..afc8a48 100644
> --- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
> +++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
> @@ -1127,23 +1127,149 @@ static int act_open_rpl(struct t3cdev *t
> return CPL_RET_BUF_DONE;
> }
>
> -static int listen_start(struct iwch_listen_ep *ep)
> +static int wait_for_reply(struct iwch_ep_common *epc)
> +{
> + PDBG("%s ep %p waiting\n", __FUNCTION__, epc);
> + wait_event(epc->waitq, epc->rpl_done);
> + PDBG("%s ep %p done waiting err %d\n", __FUNCTION__, epc, epc->rpl_err);
> + return epc->rpl_err;
> +}
> +
> +static struct iwch_listen_entry *alloc_listener(struct iwch_listen_ep *ep,
> + __be32 addr)
> +{
> + struct iwch_dev *h = to_iwch_dev(ep->com.cm_id->device);
> + struct iwch_listen_entry *le;
> +
> + le = kmalloc(sizeof *le, GFP_KERNEL);
> + if (!le) {
> + printk(KERN_ERR MOD "%s - failed to alloc memory!\n",
> + __FUNCTION__);
> + return NULL;
> + }
> + le->stid = cxgb3_alloc_stid(h->rdev.t3cdev_p,
> + &t3c_client, ep);
> + if (le->stid == -1) {
> + printk(KERN_ERR MOD "%s - cannot alloc stid.\n",
> + __FUNCTION__);
> + kfree(le);
> + return NULL;
> + }
> + le->addr = addr;
> + PDBG("%s stid %u addr %x port %x\n", __FUNCTION__, le->stid,
> + ntohl(le->addr), ntohs(ep->com.local_addr.sin_port));
> + return le;
> +}
> +
> +static void dealloc_listener(struct iwch_listen_ep *ep,
> + struct iwch_listen_entry *le)
> +{
> + PDBG("%s stid %u addr %x port %x\n", __FUNCTION__, le->stid,
> + ntohl(le->addr), ntohs(ep->com.local_addr.sin_port));
> + cxgb3_free_stid(ep->com.tdev, le->stid);
> + kfree(le);
> +}
> +
> +static void dealloc_listener_list(struct iwch_listen_ep *ep)
> +{
> + struct iwch_listen_entry *le, *tmp;
> + struct iwch_dev *h = to_iwch_dev(ep->com.cm_id->device);
> +
> + mutex_lock(&h->mutex);
> + list_for_each_entry_safe(le, tmp, &ep->listeners, entry) {
> + list_del(&le->entry);
> + dealloc_listener(ep, le);
> + }
> + mutex_unlock(&h->mutex);
> +}
> +
> +static int alloc_listener_list(struct iwch_listen_ep *ep)
> +{
> + struct iwch_dev *h = to_iwch_dev(ep->com.cm_id->device);
> + struct iwch_addrlist *addr;
> + struct iwch_listen_entry *le;
> + int err = 0;
> + int added=0;
> + mutex_lock(&h->mutex);
> + list_for_each_entry(addr, &h->addrlist, entry) {
> + if (ep->com.local_addr.sin_addr.s_addr == 0 ||
> + ep->com.local_addr.sin_addr.s_addr ==
> + addr->ifa->ifa_address) {
> + le = alloc_listener(ep, addr->ifa->ifa_address);
> + if (!le)
> + break;
> + list_add_tail(&le->entry, &ep->listeners);
> + added++;
> + }
> + }
> + mutex_unlock(&h->mutex);
> + if (ep->com.local_addr.sin_addr.s_addr != 0 && !added)
> + err = -EADDRNOTAVAIL;
> + if (!err && !added)
> + printk(KERN_WARNING MOD
> + "No RDMA interface found for device %s\n",
> + pci_name(h->rdev.rnic_info.pdev));
> + return err;
> +}
> +
> +static int listen_stop_one(struct iwch_listen_ep *ep, unsigned int stid)
> {
> struct sk_buff *skb;
> - struct cpl_pass_open_req *req;
> + struct cpl_close_listserv_req *req;
> +
> + PDBG("%s stid %u\n", __FUNCTION__, stid);
> + skb = get_skb(NULL, sizeof(*req), GFP_KERNEL);
> + if (!skb) {
> + printk(KERN_ERR MOD "%s - failed to alloc skb\n", __FUNCTION__);
> + return -ENOMEM;
> + }
> + req = (struct cpl_close_listserv_req *) skb_put(skb, sizeof(*req));
> + req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
> + req->cpu_idx = 0;
> + OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_CLOSE_LISTSRV_REQ, stid));
> + skb->priority = 1;
> + ep->com.rpl_err = 0;
> + ep->com.rpl_done = 0;
> + cxgb3_ofld_send(ep->com.tdev, skb);
> + return wait_for_reply(&ep->com);
> +}
> +
> +static int listen_stop(struct iwch_listen_ep *ep)
> +{
> + struct iwch_listen_entry *le;
> + struct iwch_dev *h = to_iwch_dev(ep->com.cm_id->device);
> + int err = 0;
>
> PDBG("%s ep %p\n", __FUNCTION__, ep);
> + mutex_lock(&h->mutex);
> + list_for_each_entry(le, &ep->listeners, entry) {
> + err = listen_stop_one(ep, le->stid);
> + if (err)
> + break;
> + }
> + mutex_unlock(&h->mutex);
> + return err;
> +}
> +
> +static int listen_start_one(struct iwch_listen_ep *ep, unsigned int stid,
> + __be32 addr, __be16 port)
> +{
> + struct sk_buff *skb;
> + struct cpl_pass_open_req *req;
> +
> + PDBG("%s stid %u addr %x port %x\n", __FUNCTION__, stid, ntohl(addr),
> + ntohs(port));
> skb = get_skb(NULL, sizeof(*req), GFP_KERNEL);
> if (!skb) {
> - printk(KERN_ERR MOD "t3c_listen_start failed to alloc skb!\n");
> + printk(KERN_ERR MOD "%s - failed to alloc skb\n", __FUNCTION__);
> return -ENOMEM;
> }
>
> req = (struct cpl_pass_open_req *) skb_put(skb, sizeof(*req));
> req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
> - OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_PASS_OPEN_REQ, ep->stid));
> - req->local_port = ep->com.local_addr.sin_port;
> - req->local_ip = ep->com.local_addr.sin_addr.s_addr;
> + OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_PASS_OPEN_REQ, stid));
> + req->local_port = port;
> + req->local_ip = addr;
> req->peer_port = 0;
> req->peer_ip = 0;
> req->peer_netmask = 0;
> @@ -1152,8 +1278,32 @@ static int listen_start(struct iwch_list
> req->opt1 = htonl(V_CONN_POLICY(CPL_CONN_POLICY_ASK));
>
> skb->priority = 1;
> + ep->com.rpl_err = 0;
> + ep->com.rpl_done = 0;
> cxgb3_ofld_send(ep->com.tdev, skb);
> - return 0;
> + return wait_for_reply(&ep->com);
> +}
> +
> +static int listen_start(struct iwch_listen_ep *ep)
> +{
> + struct iwch_listen_entry *le;
> + struct iwch_dev *h = to_iwch_dev(ep->com.cm_id->device);
> + int err = 0;
> +
> + PDBG("%s ep %p\n", __FUNCTION__, ep);
> + mutex_lock(&h->mutex);
> + list_for_each_entry(le, &ep->listeners, entry) {
> + err = listen_start_one(ep, le->stid, le->addr,
> + ep->com.local_addr.sin_port);
> + if (err)
> + goto fail;
> + }
> + mutex_unlock(&h->mutex);
> + return err;
> +fail:
> + mutex_unlock(&h->mutex);
> + listen_stop(ep);
> + return err;
> }
>
> static int pass_open_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
> @@ -1170,39 +1320,59 @@ static int pass_open_rpl(struct t3cdev *
> return CPL_RET_BUF_DONE;
> }
>
> -static int listen_stop(struct iwch_listen_ep *ep)
> -{
> - struct sk_buff *skb;
> - struct cpl_close_listserv_req *req;
> -
> - PDBG("%s ep %p\n", __FUNCTION__, ep);
> - skb = get_skb(NULL, sizeof(*req), GFP_KERNEL);
> - if (!skb) {
> - printk(KERN_ERR MOD "%s - failed to alloc skb\n", __FUNCTION__);
> - return -ENOMEM;
> - }
> - req = (struct cpl_close_listserv_req *) skb_put(skb, sizeof(*req));
> - req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
> - req->cpu_idx = 0;
> - OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_CLOSE_LISTSRV_REQ, ep->stid));
> - skb->priority = 1;
> - cxgb3_ofld_send(ep->com.tdev, skb);
> - return 0;
> -}
> -
> static int close_listsrv_rpl(struct t3cdev *tdev, struct sk_buff *skb,
> void *ctx)
> {
> struct iwch_listen_ep *ep = ctx;
> struct cpl_close_listserv_rpl *rpl = cplhdr(skb);
>
> - PDBG("%s ep %p\n", __FUNCTION__, ep);
> + PDBG("%s ep %p stid %u\n", __FUNCTION__, ep, GET_TID(rpl));
> +
> ep->com.rpl_err = status2errno(rpl->status);
> ep->com.rpl_done = 1;
> wake_up(&ep->com.waitq);
> return CPL_RET_BUF_DONE;
> }
>
> +void iwch_listeners_add_addr(struct iwch_dev *rnicp, __be32 addr)
> +{
> + struct iwch_listen_ep *listen_ep;
> + struct iwch_listen_entry *le;
> +
> + mutex_lock(&rnicp->mutex);
> + list_for_each_entry(listen_ep, &rnicp->listen_eps, entry) {
> + if (listen_ep->com.local_addr.sin_addr.s_addr)
> + continue;
> + le = alloc_listener(listen_ep, addr);
> + if (le) {
> + list_add_tail(&le->entry, &listen_ep->listeners);
> + listen_start_one(listen_ep, le->stid, addr,
> + listen_ep->com.local_addr.sin_port);
> + }
> + }
> + mutex_unlock(&rnicp->mutex);
> +}
> +
> +void iwch_listeners_del_addr(struct iwch_dev *rnicp, __be32 addr)
> +{
> + struct iwch_listen_ep *listen_ep;
> + struct iwch_listen_entry *le, *tmp;
> +
> + mutex_lock(&rnicp->mutex);
> + list_for_each_entry(listen_ep, &rnicp->listen_eps, entry) {
> + if (listen_ep->com.local_addr.sin_addr.s_addr)
> + continue;
> + list_for_each_entry_safe(le, tmp, &listen_ep->listeners,
> + entry)
> + if (le->addr == addr) {
> + listen_stop_one(listen_ep, le->stid);
> + list_del(&le->entry);
> + dealloc_listener(listen_ep, le);
> + }
> + }
> + mutex_unlock(&rnicp->mutex);
> +}
> +
> static void accept_cr(struct iwch_ep *ep, __be32 peer_ip, struct sk_buff *skb)
> {
> struct cpl_pass_accept_rpl *rpl;
> @@ -1767,8 +1937,7 @@ int iwch_accept_cr(struct iw_cm_id *cm_i
> goto err;
>
> /* wait for wr_ack */
> - wait_event(ep->com.waitq, ep->com.rpl_done);
> - err = ep->com.rpl_err;
> + err = wait_for_reply(&ep->com);
> if (err)
> goto err;
>
> @@ -1887,31 +2056,23 @@ int iwch_create_listen(struct iw_cm_id *
> ep->com.cm_id = cm_id;
> ep->backlog = backlog;
> ep->com.local_addr = cm_id->local_addr;
> + INIT_LIST_HEAD(&ep->listeners);
>
> - /*
> - * Allocate a server TID.
> - */
> - ep->stid = cxgb3_alloc_stid(h->rdev.t3cdev_p, &t3c_client, ep);
> - if (ep->stid == -1) {
> - printk(KERN_ERR MOD "%s - cannot alloc atid.\n", __FUNCTION__);
> - err = -ENOMEM;
> + err = alloc_listener_list(ep);
> + if (err)
> goto fail2;
> - }
>
> state_set(&ep->com, LISTEN);
> err = listen_start(ep);
> - if (err)
> - goto fail3;
>
> - /* wait for pass_open_rpl */
> - wait_event(ep->com.waitq, ep->com.rpl_done);
> - err = ep->com.rpl_err;
> if (!err) {
> cm_id->provider_data = ep;
> + mutex_lock(&h->mutex);
> + list_add_tail(&ep->entry, &h->listen_eps);
> + mutex_unlock(&h->mutex);
> goto out;
> }
> -fail3:
> - cxgb3_free_stid(ep->com.tdev, ep->stid);
> + dealloc_listener_list(ep);
> fail2:
> cm_id->rem_ref(cm_id);
> put_ep(&ep->com);
> @@ -1923,18 +2084,20 @@ out:
> int iwch_destroy_listen(struct iw_cm_id *cm_id)
> {
> int err;
> + struct iwch_dev *h = to_iwch_dev(cm_id->device);
> struct iwch_listen_ep *ep = to_listen_ep(cm_id);
>
> PDBG("%s ep %p\n", __FUNCTION__, ep);
>
> might_sleep();
> + mutex_lock(&h->mutex);
> + list_del(&ep->entry);
> + mutex_unlock(&h->mutex);
> state_set(&ep->com, DEAD);
> ep->com.rpl_done = 0;
> ep->com.rpl_err = 0;
> err = listen_stop(ep);
> - wait_event(ep->com.waitq, ep->com.rpl_done);
> - cxgb3_free_stid(ep->com.tdev, ep->stid);
> - err = ep->com.rpl_err;
> + dealloc_listener_list(ep);
> cm_id->rem_ref(cm_id);
> put_ep(&ep->com);
> return err;
> diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.h b/drivers/infiniband/hw/cxgb3/iwch_cm.h
> index 6107e7c..23e5a22 100644
> --- a/drivers/infiniband/hw/cxgb3/iwch_cm.h
> +++ b/drivers/infiniband/hw/cxgb3/iwch_cm.h
> @@ -162,10 +162,19 @@ struct iwch_ep_common {
> int rpl_err;
> };
>
> -struct iwch_listen_ep {
> - struct iwch_ep_common com;
> +struct iwch_listen_entry {
> + struct list_head entry;
> unsigned int stid;
> + __be32 addr;
> +};
> +
> +struct iwch_listen_ep {
> + struct iwch_ep_common com; /* Must be first entry! */
> + struct list_head entry;
> + struct list_head listeners;
> int backlog;
> + int listen_count;
> + int listen_rpls;
> };
>
> struct iwch_ep {
> @@ -222,6 +231,8 @@ int iwch_resume_tid(struct iwch_ep *ep);
> void __free_ep(struct kref *kref);
> void iwch_rearp(struct iwch_ep *ep);
> int iwch_ep_redirect(void *ctx, struct dst_entry *old, struct dst_entry *new, struct l2t_entry *l2t);
> +void iwch_listeners_add_addr(struct iwch_dev *rnicp, __be32 addr);
> +void iwch_listeners_del_addr(struct iwch_dev *rnicp, __be32 addr);
>
> int __init iwch_cm_init(void);
> void __exit iwch_cm_term(void);
> _______________________________________________
> general mailing list
> general@lists.openfabrics.org
> http://lists.openfabrics.org/cgi-bin/mailman/listinfo/general
>
> To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general
^ permalink raw reply
* Re: net-2.6.24 rebased...
From: David Miller @ 2007-09-26 20:01 UTC (permalink / raw)
To: linville; +Cc: netdev, jeff, akpm
In-Reply-To: <20070926124649.GC6171@tuxdriver.com>
From: "John W. Linville" <linville@tuxdriver.com>
Date: Wed, 26 Sep 2007 08:46:49 -0400
> On Tue, Sep 25, 2007 at 11:33:44PM -0700, David Miller wrote:
>
> > John, one patch didn't go in cleanly after I removed the
> > Z1211 driver. I put it here for your consideration so it
> > doesn't get lost:
> >
> > http://vger.kernel.org/~davem/0433-Z1211-Fix-TX-status-reports.patch
> >
> > What probably needs to happen is some other changes that
> > were in z1211 need to go into the non-mac80211 driver and
> > then this patch applies correctly.
>
> I have that one, so we're fine. It is a mac80211-specific fix,
> so I think that takes care of it.
Great, thanks to everyone for checking this out.
^ permalink raw reply
* [PATCH] [0/6] Bugfixes for pasemi_mac
From: Olof Johansson @ 2007-09-26 21:22 UTC (permalink / raw)
To: jgarzik; +Cc: netdev
Hi,
Following patches are for various bug fixes against current netdev-2.6.24
upstream branch. Please apply.
[PATCH] [1/6] pasemi_mac: fix build break in pasemi_mac_probe()
[PATCH] [2/6] pasemi_mac: fix build break in pasemi_mac_clean_rx()
[PATCH] [3/6] pasemi_mac: set interface speed correctly on XAUI ports
[PATCH] [4/6] pasemi_mac: flags as passed to spin_*_irqsave() should be unsigned long
[PATCH] [5/6] pasemi_mac: don't enable rx before there are buffers on the ring
[PATCH] [6/6] pasemi_mac: pass in count of buffers to replenish rx ring with
Thanks,
-Olof
^ permalink raw reply
* [PATCH] [1/6] pasemi_mac: fix build break in pasemi_mac_probe()
From: Olof Johansson @ 2007-09-26 21:22 UTC (permalink / raw)
To: jgarzik; +Cc: netdev
In-Reply-To: <20070926212200.GA24168@lixom.net>
pasemi_mac: fix build break in pasemi_mac_probe()
Fix breakage caused by recent unification of print_mac() stuff.
Signed-off-by: Olof Johansson <olof@lixom.net>
Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -1155,7 +1155,7 @@ pasemi_mac_probe(struct pci_dev *pdev, c
struct net_device *dev;
struct pasemi_mac *mac;
int err;
- DECLARE_MAC_BUF(mac);
+ DECLARE_MAC_BUF(mac_buf);
err = pci_enable_device(pdev);
if (err)
@@ -1241,7 +1241,7 @@ pasemi_mac_probe(struct pci_dev *pdev, c
"hw addr %s\n",
dev->name, mac->type == MAC_TYPE_GMAC ? "GMAC" : "XAUI",
mac->dma_if, mac->dma_txch, mac->dma_rxch,
- print_mac(mac, dev->dev_addr));
+ print_mac(mac_buf, dev->dev_addr));
return err;
^ 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