Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Mon, 26 Mar 2007 21:51:24 +0000 (14:51 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Mon, 26 Mar 2007 21:51:24 +0000 (14:51 -0700)
* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6:
  [SUNGEM]: Fix MAC address setting when interface is up.
  [IPV4] fib_trie: Document locking.
  [NET]: Correct accept(2) recovery after sock_attach_fd()
  [PPP]: Don't leak an sk_buff on interface destruction.
  [NET_SCHED]: Fix ingress locking
  [NET_SCHED]: cls_basic: fix NULL pointer dereference
  [DCCP]: make dccp_write_xmit_timer() static again
  [TG3]: Update version and reldate.
  [TG3]: Exit irq handler during chip reset.
  [TG3]: Eliminate the unused TG3_FLAG_SPLIT_MODE flag.
  [IPV6]: Fix routing round-robin locking.
  [DECNet] fib: Fix out of bound access of dn_fib_props[]
  [IPv4] fib: Fix out of bound access of fib_props[]
  [NET] AX.25 Kconfig and docs updates and fixes
  [NET]: Fix neighbour destructor handling.
  [NET]: Fix fib_rules compatibility breakage
  [SCTP]: Update SCTP Maintainers entry
  [NET]: remove unused header file: drivers/net/wan/lmc/lmc_media.h

29 files changed:
Documentation/networking/ax25.txt
MAINTAINERS
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/net/ppp_generic.c
drivers/net/sungem.c
drivers/net/tg3.c
drivers/net/tg3.h
drivers/net/wan/lmc/lmc_media.h [deleted file]
include/net/fib_rules.h
include/net/ip6_fib.h
include/net/neighbour.h
net/atm/clip.c
net/ax25/Kconfig
net/core/dev.c
net/core/fib_rules.c
net/core/neighbour.c
net/dccp/dccp.h
net/dccp/timer.c
net/decnet/dn_fib.c
net/decnet/dn_rules.c
net/ipv4/fib_frontend.c
net/ipv4/fib_rules.c
net/ipv4/fib_semantics.c
net/ipv4/fib_trie.c
net/ipv6/fib6_rules.c
net/ipv6/ip6_fib.c
net/ipv6/route.c
net/sched/cls_basic.c
net/socket.c

index 37c25b0925f03d9244724ba62f8252d7215145ef..8257dbf9be5729aa419d91844e54f1a08c15e6dc 100644 (file)
@@ -1,16 +1,10 @@
 To use the amateur radio protocols within Linux you will need to get a
-suitable copy of the AX.25 Utilities. More detailed information about these
-and associated programs can be found on http://zone.pspt.fi/~jsn/.
-
-For more information about the AX.25, NET/ROM and ROSE protocol stacks, see
-the AX25-HOWTO written by Terry Dawson <terry@perf.no.itg.telstra.com.au>
-who is also the AX.25 Utilities maintainer.
+suitable copy of the AX.25 Utilities. More detailed information about
+AX.25, NET/ROM and ROSE, associated programs and and utilities can be
+found on http://www.linux-ax25.org.
 
 There is an active mailing list for discussing Linux amateur radio matters
-called linux-hams. To subscribe to it, send a message to
+called linux-hams@vger.kernel.org. To subscribe to it, send a message to
 majordomo@vger.kernel.org with the words "subscribe linux-hams" in the body
-of the message, the subject field is ignored.
-
-Jonathan G4KLX
-
-g4klx@g4klx.demon.co.uk
+of the message, the subject field is ignored.  You don't need to be
+subscribed to post but of course that means you might miss an answer.
index dd6978b1e8fbcbde19e874828a16bdb3100e6f7a..2524323671b0d563d0a57fd8f1b8dbf30901401e 100644 (file)
@@ -2928,9 +2928,12 @@ L:       linux-scsi@vger.kernel.org
 S:     Maintained
 
 SCTP PROTOCOL
+P:     Vlad Yasevich
+M:     vladislav.yasevich@hp.com
 P:     Sridhar Samudrala
 M:     sri@us.ibm.com
 L:     lksctp-developers@lists.sourceforge.net
+W:     http://lksctp.sourceforge.net
 S:     Supported
 
 SCx200 CPU SUPPORT
index 0741c6d1337c1984cca1fd083bfc6242c6b230e5..f2a40ae8e7d0c8af562f03ad7254b62d5db1caf0 100644 (file)
@@ -814,7 +814,7 @@ static void ipoib_set_mcast_list(struct net_device *dev)
        queue_work(ipoib_workqueue, &priv->restart_task);
 }
 
-static void ipoib_neigh_destructor(struct neighbour *n)
+static void ipoib_neigh_cleanup(struct neighbour *n)
 {
        struct ipoib_neigh *neigh;
        struct ipoib_dev_priv *priv = netdev_priv(n->dev);
@@ -822,7 +822,7 @@ static void ipoib_neigh_destructor(struct neighbour *n)
        struct ipoib_ah *ah = NULL;
 
        ipoib_dbg(priv,
-                 "neigh_destructor for %06x " IPOIB_GID_FMT "\n",
+                 "neigh_cleanup for %06x " IPOIB_GID_FMT "\n",
                  IPOIB_QPN(n->ha),
                  IPOIB_GID_RAW_ARG(n->ha + 4));
 
@@ -874,7 +874,7 @@ void ipoib_neigh_free(struct net_device *dev, struct ipoib_neigh *neigh)
 
 static int ipoib_neigh_setup_dev(struct net_device *dev, struct neigh_parms *parms)
 {
-       parms->neigh_destructor = ipoib_neigh_destructor;
+       parms->neigh_cleanup = ipoib_neigh_cleanup;
 
        return 0;
 }
index 11b575f89856b55d0307c06513cc4695909cba2a..ef58e41287820dd23d0066c4aede6b3822983299 100644 (file)
@@ -2544,6 +2544,9 @@ static void ppp_destroy_interface(struct ppp *ppp)
        ppp->active_filter = NULL;
 #endif /* CONFIG_PPP_FILTER */
 
+       if (ppp->xmit_pending)
+               kfree_skb(ppp->xmit_pending);
+
        kfree(ppp);
 }
 
index 616be8d0fa854712445c668eb4f249cf89bebad6..08ea61db46fe5fae257415a54a30211202ff8990 100644 (file)
@@ -2530,6 +2530,35 @@ static struct net_device_stats *gem_get_stats(struct net_device *dev)
        return &gp->net_stats;
 }
 
+static int gem_set_mac_address(struct net_device *dev, void *addr)
+{
+       struct sockaddr *macaddr = (struct sockaddr *) addr;
+       struct gem *gp = dev->priv;
+       unsigned char *e = &dev->dev_addr[0];
+
+       if (!is_valid_ether_addr(macaddr->sa_data))
+               return -EADDRNOTAVAIL;
+
+       if (!netif_running(dev) || !netif_device_present(dev)) {
+               /* We'll just catch it later when the
+                * device is up'd or resumed.
+                */
+               memcpy(dev->dev_addr, macaddr->sa_data, dev->addr_len);
+               return 0;
+       }
+
+       mutex_lock(&gp->pm_mutex);
+       memcpy(dev->dev_addr, macaddr->sa_data, dev->addr_len);
+       if (gp->running) {
+               writel((e[4] << 8) | e[5], gp->regs + MAC_ADDR0);
+               writel((e[2] << 8) | e[3], gp->regs + MAC_ADDR1);
+               writel((e[0] << 8) | e[1], gp->regs + MAC_ADDR2);
+       }
+       mutex_unlock(&gp->pm_mutex);
+
+       return 0;
+}
+
 static void gem_set_multicast(struct net_device *dev)
 {
        struct gem *gp = dev->priv;
@@ -3122,6 +3151,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
        dev->change_mtu = gem_change_mtu;
        dev->irq = pdev->irq;
        dev->dma = 0;
+       dev->set_mac_address = gem_set_mac_address;
 #ifdef CONFIG_NET_POLL_CONTROLLER
        dev->poll_controller = gem_poll_controller;
 #endif
index 8c8f9f4d47a599c8b0ef91fcfef65bfffda5df79..0acee9f324e92aaf57a53a49fe26dfd4bdf8b119 100644 (file)
@@ -64,8 +64,8 @@
 
 #define DRV_MODULE_NAME                "tg3"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "3.74"
-#define DRV_MODULE_RELDATE     "February 20, 2007"
+#define DRV_MODULE_VERSION     "3.75"
+#define DRV_MODULE_RELDATE     "March 23, 2007"
 
 #define TG3_DEF_MAC_MODE       0
 #define TG3_DEF_RX_MODE                0
@@ -3568,32 +3568,34 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id)
         * Reading the PCI State register will confirm whether the
         * interrupt is ours and will flush the status block.
         */
-       if ((sblk->status & SD_STATUS_UPDATED) ||
-           !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
-               /*
-                * Writing any value to intr-mbox-0 clears PCI INTA# and
-                * chip-internal interrupt pending events.
-                * Writing non-zero to intr-mbox-0 additional tells the
-                * NIC to stop sending us irqs, engaging "in-intr-handler"
-                * event coalescing.
-                */
-               tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
-                            0x00000001);
-               if (tg3_irq_sync(tp))
+       if (unlikely(!(sblk->status & SD_STATUS_UPDATED))) {
+               if ((tp->tg3_flags & TG3_FLAG_CHIP_RESETTING) ||
+                   (tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
+                       handled = 0;
                        goto out;
-               sblk->status &= ~SD_STATUS_UPDATED;
-               if (likely(tg3_has_work(tp))) {
-                       prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
-                       netif_rx_schedule(dev);         /* schedule NAPI poll */
-               } else {
-                       /* No work, shared interrupt perhaps?  re-enable
-                        * interrupts, and flush that PCI write
-                        */
-                       tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
-                               0x00000000);
                }
-       } else {        /* shared interrupt */
-               handled = 0;
+       }
+
+       /*
+        * Writing any value to intr-mbox-0 clears PCI INTA# and
+        * chip-internal interrupt pending events.
+        * Writing non-zero to intr-mbox-0 additional tells the
+        * NIC to stop sending us irqs, engaging "in-intr-handler"
+        * event coalescing.
+        */
+       tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
+       if (tg3_irq_sync(tp))
+               goto out;
+       sblk->status &= ~SD_STATUS_UPDATED;
+       if (likely(tg3_has_work(tp))) {
+               prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
+               netif_rx_schedule(dev);         /* schedule NAPI poll */
+       } else {
+               /* No work, shared interrupt perhaps?  re-enable
+                * interrupts, and flush that PCI write
+                */
+               tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
+                              0x00000000);
        }
 out:
        return IRQ_RETVAL(handled);
@@ -3611,31 +3613,33 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id)
         * Reading the PCI State register will confirm whether the
         * interrupt is ours and will flush the status block.
         */
-       if ((sblk->status_tag != tp->last_tag) ||
-           !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
-               /*
-                * writing any value to intr-mbox-0 clears PCI INTA# and
-                * chip-internal interrupt pending events.
-                * writing non-zero to intr-mbox-0 additional tells the
-                * NIC to stop sending us irqs, engaging "in-intr-handler"
-                * event coalescing.
-                */
-               tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
-                            0x00000001);
-               if (tg3_irq_sync(tp))
+       if (unlikely(sblk->status_tag == tp->last_tag)) {
+               if ((tp->tg3_flags & TG3_FLAG_CHIP_RESETTING) ||
+                   (tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
+                       handled = 0;
                        goto out;
-               if (netif_rx_schedule_prep(dev)) {
-                       prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
-                       /* Update last_tag to mark that this status has been
-                        * seen. Because interrupt may be shared, we may be
-                        * racing with tg3_poll(), so only update last_tag
-                        * if tg3_poll() is not scheduled.
-                        */
-                       tp->last_tag = sblk->status_tag;
-                       __netif_rx_schedule(dev);
                }
-       } else {        /* shared interrupt */
-               handled = 0;
+       }
+
+       /*
+        * writing any value to intr-mbox-0 clears PCI INTA# and
+        * chip-internal interrupt pending events.
+        * writing non-zero to intr-mbox-0 additional tells the
+        * NIC to stop sending us irqs, engaging "in-intr-handler"
+        * event coalescing.
+        */
+       tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
+       if (tg3_irq_sync(tp))
+               goto out;
+       if (netif_rx_schedule_prep(dev)) {
+               prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
+               /* Update last_tag to mark that this status has been
+                * seen. Because interrupt may be shared, we may be
+                * racing with tg3_poll(), so only update last_tag
+                * if tg3_poll() is not scheduled.
+                */
+               tp->last_tag = sblk->status_tag;
+               __netif_rx_schedule(dev);
        }
 out:
        return IRQ_RETVAL(handled);
@@ -4823,6 +4827,19 @@ static int tg3_chip_reset(struct tg3 *tp)
        if (write_op == tg3_write_flush_reg32)
                tp->write32 = tg3_write32;
 
+       /* Prevent the irq handler from reading or writing PCI registers
+        * during chip reset when the memory enable bit in the PCI command
+        * register may be cleared.  The chip does not generate interrupt
+        * at this time, but the irq handler may still be called due to irq
+        * sharing or irqpoll.
+        */
+       tp->tg3_flags |= TG3_FLAG_CHIP_RESETTING;
+       tp->hw_status->status = 0;
+       tp->hw_status->status_tag = 0;
+       tp->last_tag = 0;
+       smp_mb();
+       synchronize_irq(tp->pdev->irq);
+
        /* do the reset */
        val = GRC_MISC_CFG_CORECLK_RESET;
 
@@ -4904,6 +4921,8 @@ static int tg3_chip_reset(struct tg3 *tp)
 
        pci_restore_state(tp->pdev);
 
+       tp->tg3_flags &= ~TG3_FLAG_CHIP_RESETTING;
+
        /* Make sure PCI-X relaxed ordering bit is clear. */
        pci_read_config_dword(tp->pdev, TG3PCI_X_CAPS, &val);
        val &= ~PCIX_CAPS_RELAXED_ORDERING;
@@ -6321,8 +6340,6 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
                      RDMAC_MODE_ADDROFLOW_ENAB | RDMAC_MODE_FIFOOFLOW_ENAB |
                      RDMAC_MODE_FIFOURUN_ENAB | RDMAC_MODE_FIFOOREAD_ENAB |
                      RDMAC_MODE_LNGREAD_ENAB);
-       if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE)
-               rdmac_mode |= RDMAC_MODE_SPLIT_ENABLE;
 
        /* If statement applies to 5705 and 5750 PCI devices only */
        if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
@@ -6495,9 +6512,6 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
                } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
                        val &= ~(PCIX_CAPS_SPLIT_MASK | PCIX_CAPS_BURST_MASK);
                        val |= (PCIX_CAPS_MAX_BURST_CPIOB << PCIX_CAPS_BURST_SHIFT);
-                       if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE)
-                               val |= (tp->split_mode_max_reqs <<
-                                       PCIX_CAPS_SPLIT_SHIFT);
                }
                tw32(TG3PCI_X_CAPS, val);
        }
@@ -10863,14 +10877,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        grc_misc_cfg = tr32(GRC_MISC_CFG);
        grc_misc_cfg &= GRC_MISC_CFG_BOARD_ID_MASK;
 
-       /* Broadcom's driver says that CIOBE multisplit has a bug */
-#if 0
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
-           grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5704CIOBE) {
-               tp->tg3_flags |= TG3_FLAG_SPLIT_MODE;
-               tp->split_mode_max_reqs = SPLIT_MODE_5704_MAX_REQ;
-       }
-#endif
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
            (grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788 ||
             grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788M))
@@ -11968,14 +11974,12 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
                       i == 5 ? '\n' : ':');
 
        printk(KERN_INFO "%s: RXcsums[%d] LinkChgREG[%d] "
-              "MIirq[%d] ASF[%d] Split[%d] WireSpeed[%d] "
-              "TSOcap[%d] \n",
+              "MIirq[%d] ASF[%d] WireSpeed[%d] TSOcap[%d]\n",
               dev->name,
               (tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0,
               (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) != 0,
               (tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT) != 0,
               (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0,
-              (tp->tg3_flags & TG3_FLAG_SPLIT_MODE) != 0,
               (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) == 0,
               (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) != 0);
        printk(KERN_INFO "%s: dma_rwctrl[%08x] dma_mask[%d-bit]\n",
index 086892d8c1f17433afc44bf1b78f921b915dd6fc..d515ed23841b5484d1d7c8f44f66ec3fde3e6b73 100644 (file)
@@ -2223,7 +2223,7 @@ struct tg3 {
 #define TG3_FLAG_40BIT_DMA_BUG         0x08000000
 #define TG3_FLAG_BROKEN_CHECKSUMS      0x10000000
 #define TG3_FLAG_GOT_SERDES_FLOWCTL    0x20000000
-#define TG3_FLAG_SPLIT_MODE            0x40000000
+#define TG3_FLAG_CHIP_RESETTING                0x40000000
 #define TG3_FLAG_INIT_COMPLETE         0x80000000
        u32                             tg3_flags2;
 #define TG3_FLG2_RESTART_TIMER         0x00000001
@@ -2262,9 +2262,6 @@ struct tg3 {
 #define TG3_FLG2_NO_FWARE_REPORTED     0x40000000
 #define TG3_FLG2_PHY_ADJUST_TRIM       0x80000000
 
-       u32                             split_mode_max_reqs;
-#define SPLIT_MODE_5704_MAX_REQ                3
-
        struct timer_list               timer;
        u16                             timer_counter;
        u16                             timer_multiplier;
diff --git a/drivers/net/wan/lmc/lmc_media.h b/drivers/net/wan/lmc/lmc_media.h
deleted file mode 100644 (file)
index ddcc004..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-#ifndef _LMC_MEDIA_H_
-#define _LMC_MEDIA_H_
-
-lmc_media_t lmc_ds3_media = {
-  lmc_ds3_init,                        /* special media init stuff */
-  lmc_ds3_default,             /* reset to default state */
-  lmc_ds3_set_status,          /* reset status to state provided */
-  lmc_dummy_set_1,             /* set clock source */
-  lmc_dummy_set2_1,            /* set line speed */
-  lmc_ds3_set_100ft,           /* set cable length */
-  lmc_ds3_set_scram,           /* set scrambler */
-  lmc_ds3_get_link_status,     /* get link status */
-  lmc_dummy_set_1,             /* set link status */
-  lmc_ds3_set_crc_length,      /* set CRC length */
-  lmc_dummy_set_1,             /* set T1 or E1 circuit type */
-  lmc_ds3_watchdog
-};
-
-lmc_media_t lmc_hssi_media = {
-  lmc_hssi_init,               /* special media init stuff */
-  lmc_hssi_default,            /* reset to default state */
-  lmc_hssi_set_status,         /* reset status to state provided */
-  lmc_hssi_set_clock,          /* set clock source */
-  lmc_dummy_set2_1,            /* set line speed */
-  lmc_dummy_set_1,             /* set cable length */
-  lmc_dummy_set_1,             /* set scrambler */
-  lmc_hssi_get_link_status,    /* get link status */
-  lmc_hssi_set_link_status,    /* set link status */
-  lmc_hssi_set_crc_length,     /* set CRC length */
-  lmc_dummy_set_1,             /* set T1 or E1 circuit type */
-  lmc_hssi_watchdog
-};
-
-lmc_media_t lmc_ssi_media = { lmc_ssi_init,    /* special media init stuff */
-  lmc_ssi_default,             /* reset to default state */
-  lmc_ssi_set_status,          /* reset status to state provided */
-  lmc_ssi_set_clock,           /* set clock source */
-  lmc_ssi_set_speed,           /* set line speed */
-  lmc_dummy_set_1,             /* set cable length */
-  lmc_dummy_set_1,             /* set scrambler */
-  lmc_ssi_get_link_status,     /* get link status */
-  lmc_ssi_set_link_status,     /* set link status */
-  lmc_ssi_set_crc_length,      /* set CRC length */
-  lmc_dummy_set_1,             /* set T1 or E1 circuit type */
-  lmc_ssi_watchdog
-};
-
-lmc_media_t lmc_t1_media = {
-  lmc_t1_init,                 /* special media init stuff */
-  lmc_t1_default,              /* reset to default state */
-  lmc_t1_set_status,           /* reset status to state provided */
-  lmc_t1_set_clock,            /* set clock source */
-  lmc_dummy_set2_1,            /* set line speed */
-  lmc_dummy_set_1,             /* set cable length */
-  lmc_dummy_set_1,             /* set scrambler */
-  lmc_t1_get_link_status,      /* get link status */
-  lmc_dummy_set_1,             /* set link status */
-  lmc_t1_set_crc_length,       /* set CRC length */
-  lmc_t1_set_circuit_type,     /* set T1 or E1 circuit type */
-  lmc_t1_watchdog
-};
-
-
-#endif
-
index bc3c26494c3d2f4b578be0d12f4c20fd8e1b127c..d585ea9fa97d3887435e064922f5e65a62748851 100644 (file)
@@ -34,6 +34,7 @@ struct fib_rules_ops
        int                     family;
        struct list_head        list;
        int                     rule_size;
+       int                     addr_size;
 
        int                     (*action)(struct fib_rule *,
                                          struct flowi *, int,
index 9eda572a2a6534f157b233b71f22bf9ed70abd65..cf355a3c2ad5945c95d2fe24cc44efb679b042b1 100644 (file)
@@ -58,6 +58,7 @@ struct fib6_node
        __u16                   fn_bit;         /* bit key */
        __u16                   fn_flags;
        __u32                   fn_sernum;
+       struct rt6_info         *rr_ptr;
 };
 
 #ifndef CONFIG_IPV6_SUBTREES
index 3725b93c52f3efabf4abe8519fcb0d03a723bb9c..ad7fe1121412a013c67c7638ab3907b28716bb61 100644 (file)
@@ -36,7 +36,7 @@ struct neigh_parms
        struct net_device *dev;
        struct neigh_parms *next;
        int     (*neigh_setup)(struct neighbour *);
-       void    (*neigh_destructor)(struct neighbour *);
+       void    (*neigh_cleanup)(struct neighbour *);
        struct neigh_table *tbl;
 
        void    *sysctl_table;
index ebb5d0ce8b6fd6f61fbe705c3b5162a6b6bca425..8c38258160852a5a21e4020f51051b1ea2b4d77b 100644 (file)
@@ -261,14 +261,6 @@ static void clip_pop(struct atm_vcc *vcc, struct sk_buff *skb)
        spin_unlock_irqrestore(&PRIV(dev)->xoff_lock, flags);
 }
 
-static void clip_neigh_destroy(struct neighbour *neigh)
-{
-       DPRINTK("clip_neigh_destroy (neigh %p)\n", neigh);
-       if (NEIGH2ENTRY(neigh)->vccs)
-               printk(KERN_CRIT "clip_neigh_destroy: vccs != NULL !!!\n");
-       NEIGH2ENTRY(neigh)->vccs = (void *) NEIGHBOR_DEAD;
-}
-
 static void clip_neigh_solicit(struct neighbour *neigh, struct sk_buff *skb)
 {
        DPRINTK("clip_neigh_solicit (neigh %p, skb %p)\n", neigh, skb);
@@ -342,7 +334,6 @@ static struct neigh_table clip_tbl = {
        /* parameters are copied from ARP ... */
        .parms = {
                .tbl                    = &clip_tbl,
-               .neigh_destructor       = clip_neigh_destroy,
                .base_reachable_time    = 30 * HZ,
                .retrans_time           = 1 * HZ,
                .gc_staletime           = 60 * HZ,
index a8993a041724b9f3d2671e72805c54134cf937cc..43dd86fca4d3d0cd558d6bce78793e6113a2604e 100644 (file)
@@ -1,30 +1,27 @@
 #
 # Amateur Radio protocols and AX.25 device configuration
 #
-# 19971130     Now in an own category to make correct compilation of the
-#              AX.25 stuff easier...
-#              Joerg Reuter DL1BKE <jreuter@yaina.de>
-# 19980129     Moved to net/ax25/Config.in, sourcing device drivers.
 
 menuconfig HAMRADIO
        depends on NET
        bool "Amateur Radio support"
        help
          If you want to connect your Linux box to an amateur radio, answer Y
-         here. You want to read <http://www.tapr.org/tapr/html/pkthome.html> and
-         the AX25-HOWTO, available from <http://www.tldp.org/docs.html#howto>.
+         here. You want to read <http://www.tapr.org/tapr/html/pkthome.html>
+         and more specifically about AX.25 on Linux
+         <http://www.linux-ax25.org/>.
 
          Note that the answer to this question won't directly affect the
          kernel: saying N will just cause the configurator to skip all
          the questions about amateur radio.
 
 comment "Packet Radio protocols"
-       depends on HAMRADIO && NET
+       depends on HAMRADIO
 
 config AX25
        tristate "Amateur Radio AX.25 Level 2 protocol"
-       depends on HAMRADIO && NET
-       ---help---
+       depends on HAMRADIO
+       help
          This is the protocol used for computer communication over amateur
          radio. It is either used by itself for point-to-point links, or to
          carry other protocols such as tcp/ip. To use it, you need a device
@@ -52,6 +49,7 @@ config AX25
 
 config AX25_DAMA_SLAVE
        bool "AX.25 DAMA Slave support"
+       default y
        depends on AX25
        help
          DAMA is a mechanism to prevent collisions when doing AX.25
@@ -59,23 +57,38 @@ config AX25_DAMA_SLAVE
          from clients (called "slaves") and redistributes it to other slaves.
          If you say Y here, your Linux box will act as a DAMA slave; this is
          transparent in that you don't have to do any special DAMA
-         configuration. (Linux cannot yet act as a DAMA server.) If unsure,
-         say N.
+         configuration. Linux cannot yet act as a DAMA server.  This option
+         only compiles DAMA slave support into the kernel.  It still needs to
+         be enabled at runtime.  For more about DAMA see
+         <http://www.linux-ax25.org>.  If unsure, say Y.
+
+# placeholder until implemented
+config AX25_DAMA_MASTER
+       bool 'AX.25 DAMA Master support'
+       depends on AX25_DAMA_SLAVE && BROKEN
+       help
+         DAMA is a mechanism to prevent collisions when doing AX.25
+         networking. A DAMA server (called "master") accepts incoming traffic
+         from clients (called "slaves") and redistributes it to other slaves.
+         If you say Y here, your Linux box will act as a DAMA master; this is
+         transparent in that you don't have to do any special DAMA
+         configuration. Linux cannot yet act as a DAMA server.  This option
+         only compiles DAMA slave support into the kernel.  It still needs to
+         be explicitly enabled, so if unsure, say Y.
 
-#       bool '    AX.25 DAMA Master support' CONFIG_AX25_DAMA_MASTER
 config NETROM
        tristate "Amateur Radio NET/ROM protocol"
        depends on AX25
-       ---help---
+       help
          NET/ROM is a network layer protocol on top of AX.25 useful for
          routing.
 
          A comprehensive listing of all the software for Linux amateur radio
          users as well as information about how to configure an AX.25 port is
-         contained in the AX25-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>. You also might want to
-         check out the file <file:Documentation/networking/ax25.txt>. More
-         information about digital amateur radio in general is on the WWW at
+         contained in the Linux Ham Wiki, available from
+         <http://www.linux-ax25.org>. You also might want to check out the
+         file <file:Documentation/networking/ax25.txt>. More information about
+         digital amateur radio in general is on the WWW at
          <http://www.tapr.org/tapr/html/pkthome.html>.
 
          To compile this driver as a module, choose M here: the
@@ -84,27 +97,25 @@ config NETROM
 config ROSE
        tristate "Amateur Radio X.25 PLP (Rose)"
        depends on AX25
-       ---help---
+       help
          The Packet Layer Protocol (PLP) is a way to route packets over X.25
          connections in general and amateur radio AX.25 connections in
          particular, essentially an alternative to NET/ROM.
 
          A comprehensive listing of all the software for Linux amateur radio
          users as well as information about how to configure an AX.25 port is
-         contained in the AX25-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.  You also might want to
-         check out the file <file:Documentation/networking/ax25.txt>. More
-         information about digital amateur radio in general is on the WWW at
+         contained in the Linux Ham Wiki, available from
+         <http://www.linux-ax25.org>.  You also might want to check out the
+         file <file:Documentation/networking/ax25.txt>. More information about
+         digital amateur radio in general is on the WWW at
          <http://www.tapr.org/tapr/html/pkthome.html>.
 
          To compile this driver as a module, choose M here: the
          module will be called rose.
 
-
 menu "AX.25 network device drivers"
-       depends on HAMRADIO && NET && AX25!=n
+       depends on HAMRADIO && AX25
 
 source "drivers/net/hamradio/Kconfig"
 
 endmenu
-
index cf71614dae93bf29d5211b86dc487c9e9a82faff..5984b55311a1d428cf534d2e0cc141b282f6b859 100644 (file)
@@ -1750,10 +1750,10 @@ static int ing_filter(struct sk_buff *skb)
 
                skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_INGRESS);
 
-               spin_lock(&dev->ingress_lock);
+               spin_lock(&dev->queue_lock);
                if ((q = dev->qdisc_ingress) != NULL)
                        result = q->enqueue(skb, q);
-               spin_unlock(&dev->ingress_lock);
+               spin_unlock(&dev->queue_lock);
 
        }
 
index 3aea4e87d3d7c679abf051c4af2e6adbabbcac5b..d011819a805805480d14fd0d00832f2b794d9082 100644 (file)
@@ -152,6 +152,28 @@ out:
 
 EXPORT_SYMBOL_GPL(fib_rules_lookup);
 
+static int validate_rulemsg(struct fib_rule_hdr *frh, struct nlattr **tb,
+                           struct fib_rules_ops *ops)
+{
+       int err = -EINVAL;
+
+       if (frh->src_len)
+               if (tb[FRA_SRC] == NULL ||
+                   frh->src_len > (ops->addr_size * 8) ||
+                   nla_len(tb[FRA_SRC]) != ops->addr_size)
+                       goto errout;
+
+       if (frh->dst_len)
+               if (tb[FRA_DST] == NULL ||
+                   frh->dst_len > (ops->addr_size * 8) ||
+                   nla_len(tb[FRA_DST]) != ops->addr_size)
+                       goto errout;
+
+       err = 0;
+errout:
+       return err;
+}
+
 int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
 {
        struct fib_rule_hdr *frh = nlmsg_data(nlh);
@@ -173,6 +195,10 @@ int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
        if (err < 0)
                goto errout;
 
+       err = validate_rulemsg(frh, tb, ops);
+       if (err < 0)
+               goto errout;
+
        rule = kzalloc(ops->rule_size, GFP_KERNEL);
        if (rule == NULL) {
                err = -ENOMEM;
@@ -260,6 +286,10 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
        if (err < 0)
                goto errout;
 
+       err = validate_rulemsg(frh, tb, ops);
+       if (err < 0)
+               goto errout;
+
        list_for_each_entry(rule, ops->rules_list, list) {
                if (frh->action && (frh->action != rule->action))
                        continue;
index 3183142c6044000b93829b4e340a3675a0c7d146..cfc60019cf920508cc9c416d950c147512c73766 100644 (file)
@@ -140,6 +140,8 @@ static int neigh_forced_gc(struct neigh_table *tbl)
                                n->dead = 1;
                                shrunk  = 1;
                                write_unlock(&n->lock);
+                               if (n->parms->neigh_cleanup)
+                                       n->parms->neigh_cleanup(n);
                                neigh_release(n);
                                continue;
                        }
@@ -211,6 +213,8 @@ static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev)
                                NEIGH_PRINTK2("neigh %p is stray.\n", n);
                        }
                        write_unlock(&n->lock);
+                       if (n->parms->neigh_cleanup)
+                               n->parms->neigh_cleanup(n);
                        neigh_release(n);
                }
        }
@@ -582,9 +586,6 @@ void neigh_destroy(struct neighbour *neigh)
                        kfree(hh);
        }
 
-       if (neigh->parms->neigh_destructor)
-               (neigh->parms->neigh_destructor)(neigh);
-
        skb_queue_purge(&neigh->arp_queue);
 
        dev_put(neigh->dev);
@@ -675,6 +676,8 @@ static void neigh_periodic_timer(unsigned long arg)
                        *np = n->next;
                        n->dead = 1;
                        write_unlock(&n->lock);
+                       if (n->parms->neigh_cleanup)
+                               n->parms->neigh_cleanup(n);
                        neigh_release(n);
                        continue;
                }
@@ -2088,8 +2091,11 @@ void __neigh_for_each_release(struct neigh_table *tbl,
                        } else
                                np = &n->next;
                        write_unlock(&n->lock);
-                       if (release)
+                       if (release) {
+                               if (n->parms->neigh_cleanup)
+                                       n->parms->neigh_cleanup(n);
                                neigh_release(n);
+                       }
                }
        }
 }
index a0e7cd183a5d3e648d40bf81b6a3d6420c9931bd..e33a9edb40363ef7c964de7de3eb55c0c81d7846 100644 (file)
@@ -191,7 +191,6 @@ extern void dccp_send_sync(struct sock *sk, const u64 seq,
                           const enum dccp_pkt_type pkt_type);
 
 extern void dccp_write_xmit(struct sock *sk, int block);
-extern void dccp_write_xmit_timer(unsigned long data);
 extern void dccp_write_space(struct sock *sk);
 
 extern void dccp_init_xmit_timers(struct sock *sk);
index b038a0a3ad40a1fcbc182c6f66e37a2171120144..0197a41c256ad72e37499f631f6df40498d4dad6 100644 (file)
@@ -262,7 +262,7 @@ out:
 }
 
 /* Transmit-delay timer: used by the CCIDs to delay actual send time */
-void dccp_write_xmit_timer(unsigned long data)
+static void dccp_write_xmit_timer(unsigned long data)
 {
        struct sock *sk = (struct sock *)data;
        struct dccp_sock *dp = dccp_sk(sk);
index 3cbfddc98430a5aa53cb59f0ff60d0a0eb5e6098..82d58a977e6fc15138d0eb2be331f19e3990512b 100644 (file)
@@ -63,7 +63,7 @@ static struct
 {
        int error;
        u8 scope;
-} dn_fib_props[RTA_MAX+1] = {
+} dn_fib_props[RTN_MAX+1] = {
        [RTN_UNSPEC] =      { .error = 0,       .scope = RT_SCOPE_NOWHERE },
        [RTN_UNICAST] =     { .error = 0,       .scope = RT_SCOPE_UNIVERSE },
        [RTN_LOCAL] =       { .error = 0,       .scope = RT_SCOPE_HOST },
@@ -276,6 +276,9 @@ struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r, struct dn_kern_rta
        struct dn_fib_info *ofi;
        int nhs = 1;
 
+       if (r->rtm_type > RTN_MAX)
+               goto err_inval;
+
        if (dn_fib_props[r->rtm_type].scope > r->rtm_scope)
                goto err_inval;
 
index b6c98ac93dc8737d96e54ac7f00dacacf90ae6f4..5e86dd5423024c3823cb1954e62b2d89c250441e 100644 (file)
@@ -109,8 +109,6 @@ errout:
 
 static struct nla_policy dn_fib_rule_policy[FRA_MAX+1] __read_mostly = {
        FRA_GENERIC_POLICY,
-       [FRA_SRC]       = { .type = NLA_U16 },
-       [FRA_DST]       = { .type = NLA_U16 },
 };
 
 static int dn_fib_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
@@ -133,7 +131,7 @@ static int dn_fib_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
        int err = -EINVAL;
        struct dn_fib_rule *r = (struct dn_fib_rule *)rule;
 
-       if (frh->src_len > 16 || frh->dst_len > 16 || frh->tos)
+       if (frh->tos)
                goto  errout;
 
        if (rule->table == RT_TABLE_UNSPEC) {
@@ -150,10 +148,10 @@ static int dn_fib_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
                }
        }
 
-       if (tb[FRA_SRC])
+       if (frh->src_len)
                r->src = nla_get_le16(tb[FRA_SRC]);
 
-       if (tb[FRA_DST])
+       if (frh->dst_len)
                r->dst = nla_get_le16(tb[FRA_DST]);
 
        r->src_len = frh->src_len;
@@ -176,10 +174,10 @@ static int dn_fib_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
        if (frh->dst_len && (r->dst_len != frh->dst_len))
                return 0;
 
-       if (tb[FRA_SRC] && (r->src != nla_get_le16(tb[FRA_SRC])))
+       if (frh->src_len && (r->src != nla_get_le16(tb[FRA_SRC])))
                return 0;
 
-       if (tb[FRA_DST] && (r->dst != nla_get_le16(tb[FRA_DST])))
+       if (frh->dst_len && (r->dst != nla_get_le16(tb[FRA_DST])))
                return 0;
 
        return 1;
@@ -249,6 +247,7 @@ int dn_fib_dump_rules(struct sk_buff *skb, struct netlink_callback *cb)
 static struct fib_rules_ops dn_fib_rules_ops = {
        .family         = AF_DECnet,
        .rule_size      = sizeof(struct dn_fib_rule),
+       .addr_size      = sizeof(u16),
        .action         = dn_fib_rule_action,
        .match          = dn_fib_rule_match,
        .configure      = dn_fib_rule_configure,
index 1fba6439fc576c9a892af95e5f68f56168cc40c0..fc920f63452bf4a11694eedb226163cc5c52f985 100644 (file)
@@ -493,6 +493,11 @@ static int rtm_to_fib_config(struct sk_buff *skb, struct nlmsghdr *nlh,
        cfg->fc_nlinfo.pid = NETLINK_CB(skb).pid;
        cfg->fc_nlinfo.nlh = nlh;
 
+       if (cfg->fc_type > RTN_MAX) {
+               err = -EINVAL;
+               goto errout;
+       }
+
        nlmsg_for_each_attr(attr, nlh, sizeof(struct rtmsg), remaining) {
                switch (attr->nla_type) {
                case RTA_DST:
index b837c33e0404fc09a8e54ea7798d8e8b698657af..c660c074c76cc5360d0db1750e668ce0c4bd57a7 100644 (file)
@@ -171,8 +171,6 @@ static struct fib_table *fib_empty_table(void)
 
 static struct nla_policy fib4_rule_policy[FRA_MAX+1] __read_mostly = {
        FRA_GENERIC_POLICY,
-       [FRA_SRC]       = { .type = NLA_U32 },
-       [FRA_DST]       = { .type = NLA_U32 },
        [FRA_FLOW]      = { .type = NLA_U32 },
 };
 
@@ -183,8 +181,7 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
        int err = -EINVAL;
        struct fib4_rule *rule4 = (struct fib4_rule *) rule;
 
-       if (frh->src_len > 32 || frh->dst_len > 32 ||
-           (frh->tos & ~IPTOS_TOS_MASK))
+       if (frh->tos & ~IPTOS_TOS_MASK)
                goto errout;
 
        if (rule->table == RT_TABLE_UNSPEC) {
@@ -201,10 +198,10 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
                }
        }
 
-       if (tb[FRA_SRC])
+       if (frh->src_len)
                rule4->src = nla_get_be32(tb[FRA_SRC]);
 
-       if (tb[FRA_DST])
+       if (frh->dst_len)
                rule4->dst = nla_get_be32(tb[FRA_DST]);
 
 #ifdef CONFIG_NET_CLS_ROUTE
@@ -242,10 +239,10 @@ static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
                return 0;
 #endif
 
-       if (tb[FRA_SRC] && (rule4->src != nla_get_be32(tb[FRA_SRC])))
+       if (frh->src_len && (rule4->src != nla_get_be32(tb[FRA_SRC])))
                return 0;
 
-       if (tb[FRA_DST] && (rule4->dst != nla_get_be32(tb[FRA_DST])))
+       if (frh->dst_len && (rule4->dst != nla_get_be32(tb[FRA_DST])))
                return 0;
 
        return 1;
@@ -309,6 +306,7 @@ static size_t fib4_rule_nlmsg_payload(struct fib_rule *rule)
 static struct fib_rules_ops fib4_rules_ops = {
        .family         = AF_INET,
        .rule_size      = sizeof(struct fib4_rule),
+       .addr_size      = sizeof(u32),
        .action         = fib4_rule_action,
        .match          = fib4_rule_match,
        .configure      = fib4_rule_configure,
index 2f1fdae6efa6df82489b850fe93e227c230dcc09..3dad12ee76c35a76b851a433108a5be1aa30aa44 100644 (file)
@@ -89,7 +89,7 @@ static const struct
 {
        int     error;
        u8      scope;
-} fib_props[RTA_MAX + 1] = {
+} fib_props[RTN_MAX + 1] = {
        {
                .error  = 0,
                .scope  = RT_SCOPE_NOWHERE,
index ada9b3db507d08b938ba8b9697dc35882a3f76fa..214c34732e84caa9ad6a7f44c3ede03ad769d977 100644 (file)
@@ -1123,6 +1123,9 @@ err:
        return fa_head;
 }
 
+/*
+ * Caller must hold RTNL.
+ */
 static int fn_trie_insert(struct fib_table *tb, struct fib_config *cfg)
 {
        struct trie *t = (struct trie *) tb->tb_data;
@@ -1540,6 +1543,9 @@ static int trie_leaf_remove(struct trie *t, t_key key)
        return 1;
 }
 
+/*
+ * Caller must hold RTNL.
+ */
 static int fn_trie_delete(struct fib_table *tb, struct fib_config *cfg)
 {
        struct trie *t = (struct trie *) tb->tb_data;
@@ -1718,6 +1724,9 @@ up:
        return NULL; /* Ready. Root of trie */
 }
 
+/*
+ * Caller must hold RTNL.
+ */
 static int fn_trie_flush(struct fib_table *tb)
 {
        struct trie *t = (struct trie *) tb->tb_data;
index 0862809ffcf7abad0a4593126c9cccf3e8b29da5..ea3035b4e3e8d078e2b3c421aca48c2db0d51b7a 100644 (file)
@@ -131,8 +131,6 @@ static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
 
 static struct nla_policy fib6_rule_policy[FRA_MAX+1] __read_mostly = {
        FRA_GENERIC_POLICY,
-       [FRA_SRC]       = { .len = sizeof(struct in6_addr) },
-       [FRA_DST]       = { .len = sizeof(struct in6_addr) },
 };
 
 static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
@@ -142,9 +140,6 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
        int err = -EINVAL;
        struct fib6_rule *rule6 = (struct fib6_rule *) rule;
 
-       if (frh->src_len > 128 || frh->dst_len > 128)
-               goto errout;
-
        if (rule->action == FR_ACT_TO_TBL) {
                if (rule->table == RT6_TABLE_UNSPEC)
                        goto errout;
@@ -155,11 +150,11 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
                }
        }
 
-       if (tb[FRA_SRC])
+       if (frh->src_len)
                nla_memcpy(&rule6->src.addr, tb[FRA_SRC],
                           sizeof(struct in6_addr));
 
-       if (tb[FRA_DST])
+       if (frh->dst_len)
                nla_memcpy(&rule6->dst.addr, tb[FRA_DST],
                           sizeof(struct in6_addr));
 
@@ -186,11 +181,11 @@ static int fib6_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
        if (frh->tos && (rule6->tclass != frh->tos))
                return 0;
 
-       if (tb[FRA_SRC] &&
+       if (frh->src_len &&
            nla_memcmp(tb[FRA_SRC], &rule6->src.addr, sizeof(struct in6_addr)))
                return 0;
 
-       if (tb[FRA_DST] &&
+       if (frh->dst_len &&
            nla_memcmp(tb[FRA_DST], &rule6->dst.addr, sizeof(struct in6_addr)))
                return 0;
 
@@ -240,6 +235,7 @@ static size_t fib6_rule_nlmsg_payload(struct fib_rule *rule)
 static struct fib_rules_ops fib6_rules_ops = {
        .family                 = AF_INET6,
        .rule_size              = sizeof(struct fib6_rule),
+       .addr_size              = sizeof(struct in6_addr),
        .action                 = fib6_rule_action,
        .match                  = fib6_rule_match,
        .configure              = fib6_rule_configure,
index f4d7be77eb0fefa93446010f9c335655c18fa654..268f476ef3dbe34aafaedc9d089d381da76f7667 100644 (file)
@@ -658,6 +658,10 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
                ins = &iter->u.dst.rt6_next;
        }
 
+       /* Reset round-robin state, if necessary */
+       if (ins == &fn->leaf)
+               fn->rr_ptr = NULL;
+
        /*
         *      insert node
         */
@@ -1109,6 +1113,10 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
        rt6_stats.fib_rt_entries--;
        rt6_stats.fib_discarded_routes++;
 
+       /* Reset round-robin state, if necessary */
+       if (fn->rr_ptr == rt)
+               fn->rr_ptr = NULL;
+
        /* Adjust walkers */
        read_lock(&fib6_walker_lock);
        FOR_WALKERS(w) {
index a6b3117df5466298041ec4d8d2c03c5c52ddb79a..3931b33b25e8b77b25033ec311ec5c6f8b876cef 100644 (file)
@@ -363,55 +363,76 @@ static int rt6_score_route(struct rt6_info *rt, int oif,
        return m;
 }
 
-static struct rt6_info *rt6_select(struct rt6_info **head, int oif,
-                                  int strict)
+static struct rt6_info *find_match(struct rt6_info *rt, int oif, int strict,
+                                  int *mpri, struct rt6_info *match)
 {
-       struct rt6_info *match = NULL, *last = NULL;
-       struct rt6_info *rt, *rt0 = *head;
-       u32 metric;
+       int m;
+
+       if (rt6_check_expired(rt))
+               goto out;
+
+       m = rt6_score_route(rt, oif, strict);
+       if (m < 0)
+               goto out;
+
+       if (m > *mpri) {
+               if (strict & RT6_LOOKUP_F_REACHABLE)
+                       rt6_probe(match);
+               *mpri = m;
+               match = rt;
+       } else if (strict & RT6_LOOKUP_F_REACHABLE) {
+               rt6_probe(rt);
+       }
+
+out:
+       return match;
+}
+
+static struct rt6_info *find_rr_leaf(struct fib6_node *fn,
+                                    struct rt6_info *rr_head,
+                                    u32 metric, int oif, int strict)
+{
+       struct rt6_info *rt, *match;
        int mpri = -1;
 
-       RT6_TRACE("%s(head=%p(*head=%p), oif=%d)\n",
-                 __FUNCTION__, head, head ? *head : NULL, oif);
+       match = NULL;
+       for (rt = rr_head; rt && rt->rt6i_metric == metric;
+            rt = rt->u.dst.rt6_next)
+               match = find_match(rt, oif, strict, &mpri, match);
+       for (rt = fn->leaf; rt && rt != rr_head && rt->rt6i_metric == metric;
+            rt = rt->u.dst.rt6_next)
+               match = find_match(rt, oif, strict, &mpri, match);
 
-       for (rt = rt0, metric = rt0->rt6i_metric;
-            rt && rt->rt6i_metric == metric && (!last || rt != rt0);
-            rt = rt->u.dst.rt6_next) {
-               int m;
+       return match;
+}
 
-               if (rt6_check_expired(rt))
-                       continue;
+static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict)
+{
+       struct rt6_info *match, *rt0;
 
-               last = rt;
+       RT6_TRACE("%s(fn->leaf=%p, oif=%d)\n",
+                 __FUNCTION__, fn->leaf, oif);
 
-               m = rt6_score_route(rt, oif, strict);
-               if (m < 0)
-                       continue;
+       rt0 = fn->rr_ptr;
+       if (!rt0)
+               fn->rr_ptr = rt0 = fn->leaf;
 
-               if (m > mpri) {
-                       if (strict & RT6_LOOKUP_F_REACHABLE)
-                               rt6_probe(match);
-                       match = rt;
-                       mpri = m;
-               } else if (strict & RT6_LOOKUP_F_REACHABLE) {
-                       rt6_probe(rt);
-               }
-       }
+       match = find_rr_leaf(fn, rt0, rt0->rt6i_metric, oif, strict);
 
        if (!match &&
-           (strict & RT6_LOOKUP_F_REACHABLE) &&
-           last && last != rt0) {
+           (strict & RT6_LOOKUP_F_REACHABLE)) {
+               struct rt6_info *next = rt0->u.dst.rt6_next;
+
                /* no entries matched; do round-robin */
-               static DEFINE_SPINLOCK(lock);
-               spin_lock(&lock);
-               *head = rt0->u.dst.rt6_next;
-               rt0->u.dst.rt6_next = last->u.dst.rt6_next;
-               last->u.dst.rt6_next = rt0;
-               spin_unlock(&lock);
+               if (!next || next->rt6i_metric != rt0->rt6i_metric)
+                       next = fn->leaf;
+
+               if (next != rt0)
+                       fn->rr_ptr = next;
        }
 
-       RT6_TRACE("%s() => %p, score=%d\n",
-                 __FUNCTION__, match, mpri);
+       RT6_TRACE("%s() => %p\n",
+                 __FUNCTION__, match);
 
        return (match ? match : &ip6_null_entry);
 }
@@ -657,7 +678,7 @@ restart_2:
        fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
 
 restart:
-       rt = rt6_select(&fn->leaf, fl->iif, strict | reachable);
+       rt = rt6_select(fn, fl->iif, strict | reachable);
        BACKTRACK(&fl->fl6_src);
        if (rt == &ip6_null_entry ||
            rt->rt6i_flags & RTF_CACHE)
@@ -752,7 +773,7 @@ restart_2:
        fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
 
 restart:
-       rt = rt6_select(&fn->leaf, fl->oif, strict | reachable);
+       rt = rt6_select(fn, fl->oif, strict | reachable);
        BACKTRACK(&fl->fl6_src);
        if (rt == &ip6_null_entry ||
            rt->rt6i_flags & RTF_CACHE)
index fad08e521c24f91456590ac4cb6988776f80171b..70fe36eb66a2619e038f4f83419f673d1370375c 100644 (file)
@@ -81,6 +81,13 @@ static void basic_put(struct tcf_proto *tp, unsigned long f)
 
 static int basic_init(struct tcf_proto *tp)
 {
+       struct basic_head *head;
+
+       head = kzalloc(sizeof(*head), GFP_KERNEL);
+       if (head == NULL)
+               return -ENOBUFS;
+       INIT_LIST_HEAD(&head->flist);
+       tp->root = head;
        return 0;
 }
 
@@ -176,15 +183,6 @@ static int basic_change(struct tcf_proto *tp, unsigned long base, u32 handle,
        }
 
        err = -ENOBUFS;
-       if (head == NULL) {
-               head = kzalloc(sizeof(*head), GFP_KERNEL);
-               if (head == NULL)
-                       goto errout;
-
-               INIT_LIST_HEAD(&head->flist);
-               tp->root = head;
-       }
-
        f = kzalloc(sizeof(*f), GFP_KERNEL);
        if (f == NULL)
                goto errout;
index 9566e57ac7f58175a71021c5959a6c81e7b426f5..ea8f81abc45cee0dcc69e6375c37d109d31ab807 100644 (file)
@@ -1381,7 +1381,7 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,
 
        err = sock_attach_fd(newsock, newfile);
        if (err < 0)
-               goto out_fd;
+               goto out_fd_simple;
 
        err = security_socket_accept(sock, newsock);
        if (err)
@@ -1414,6 +1414,11 @@ out_put:
        fput_light(sock->file, fput_needed);
 out:
        return err;
+out_fd_simple:
+       sock_release(newsock);
+       put_filp(newfile);
+       put_unused_fd(newfd);
+       goto out_put;
 out_fd:
        fput(newfile);
        put_unused_fd(newfd);
This page took 0.050202 seconds and 5 git commands to generate.