Browse Source

Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6

* 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
Linus Torvalds 18 years ago
parent
commit
703071b5b9

+ 6 - 12
Documentation/networking/ax25.txt

@@ -1,16 +1,10 @@
 To use the amateur radio protocols within Linux you will need to get a
 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
 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
 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.

+ 3 - 0
MAINTAINERS

@@ -2928,9 +2928,12 @@ L:	linux-scsi@vger.kernel.org
 S:	Maintained
 S:	Maintained
 
 
 SCTP PROTOCOL
 SCTP PROTOCOL
+P:	Vlad Yasevich
+M:	vladislav.yasevich@hp.com
 P:	Sridhar Samudrala
 P:	Sridhar Samudrala
 M:	sri@us.ibm.com
 M:	sri@us.ibm.com
 L:	lksctp-developers@lists.sourceforge.net
 L:	lksctp-developers@lists.sourceforge.net
+W:	http://lksctp.sourceforge.net
 S:	Supported
 S:	Supported
 
 
 SCx200 CPU SUPPORT
 SCx200 CPU SUPPORT

+ 3 - 3
drivers/infiniband/ulp/ipoib/ipoib_main.c

@@ -814,7 +814,7 @@ static void ipoib_set_mcast_list(struct net_device *dev)
 	queue_work(ipoib_workqueue, &priv->restart_task);
 	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_neigh *neigh;
 	struct ipoib_dev_priv *priv = netdev_priv(n->dev);
 	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;
 	struct ipoib_ah *ah = NULL;
 
 
 	ipoib_dbg(priv,
 	ipoib_dbg(priv,
-		  "neigh_destructor for %06x " IPOIB_GID_FMT "\n",
+		  "neigh_cleanup for %06x " IPOIB_GID_FMT "\n",
 		  IPOIB_QPN(n->ha),
 		  IPOIB_QPN(n->ha),
 		  IPOIB_GID_RAW_ARG(n->ha + 4));
 		  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)
 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;
 	return 0;
 }
 }

+ 3 - 0
drivers/net/ppp_generic.c

@@ -2544,6 +2544,9 @@ static void ppp_destroy_interface(struct ppp *ppp)
 	ppp->active_filter = NULL;
 	ppp->active_filter = NULL;
 #endif /* CONFIG_PPP_FILTER */
 #endif /* CONFIG_PPP_FILTER */
 
 
+	if (ppp->xmit_pending)
+		kfree_skb(ppp->xmit_pending);
+
 	kfree(ppp);
 	kfree(ppp);
 }
 }
 
 

+ 30 - 0
drivers/net/sungem.c

@@ -2530,6 +2530,35 @@ static struct net_device_stats *gem_get_stats(struct net_device *dev)
 	return &gp->net_stats;
 	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)
 static void gem_set_multicast(struct net_device *dev)
 {
 {
 	struct gem *gp = dev->priv;
 	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->change_mtu = gem_change_mtu;
 	dev->irq = pdev->irq;
 	dev->irq = pdev->irq;
 	dev->dma = 0;
 	dev->dma = 0;
+	dev->set_mac_address = gem_set_mac_address;
 #ifdef CONFIG_NET_POLL_CONTROLLER
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	dev->poll_controller = gem_poll_controller;
 	dev->poll_controller = gem_poll_controller;
 #endif
 #endif

+ 69 - 65
drivers/net/tg3.c

@@ -64,8 +64,8 @@
 
 
 #define DRV_MODULE_NAME		"tg3"
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
 #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_MAC_MODE	0
 #define TG3_DEF_RX_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
 	 * Reading the PCI State register will confirm whether the
 	 * interrupt is ours and will flush the status block.
 	 * 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;
 			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:
 out:
 	return IRQ_RETVAL(handled);
 	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
 	 * Reading the PCI State register will confirm whether the
 	 * interrupt is ours and will flush the status block.
 	 * 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;
 			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:
 out:
 	return IRQ_RETVAL(handled);
 	return IRQ_RETVAL(handled);
@@ -4823,6 +4827,19 @@ static int tg3_chip_reset(struct tg3 *tp)
 	if (write_op == tg3_write_flush_reg32)
 	if (write_op == tg3_write_flush_reg32)
 		tp->write32 = tg3_write32;
 		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 */
 	/* do the reset */
 	val = GRC_MISC_CFG_CORECLK_RESET;
 	val = GRC_MISC_CFG_CORECLK_RESET;
 
 
@@ -4904,6 +4921,8 @@ static int tg3_chip_reset(struct tg3 *tp)
 
 
 	pci_restore_state(tp->pdev);
 	pci_restore_state(tp->pdev);
 
 
+	tp->tg3_flags &= ~TG3_FLAG_CHIP_RESETTING;
+
 	/* Make sure PCI-X relaxed ordering bit is clear. */
 	/* Make sure PCI-X relaxed ordering bit is clear. */
 	pci_read_config_dword(tp->pdev, TG3PCI_X_CAPS, &val);
 	pci_read_config_dword(tp->pdev, TG3PCI_X_CAPS, &val);
 	val &= ~PCIX_CAPS_RELAXED_ORDERING;
 	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_ADDROFLOW_ENAB | RDMAC_MODE_FIFOOFLOW_ENAB |
 		      RDMAC_MODE_FIFOURUN_ENAB | RDMAC_MODE_FIFOOREAD_ENAB |
 		      RDMAC_MODE_FIFOURUN_ENAB | RDMAC_MODE_FIFOOREAD_ENAB |
 		      RDMAC_MODE_LNGREAD_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 statement applies to 5705 and 5750 PCI devices only */
 	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
 	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) {
 		} 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_SPLIT_MASK | PCIX_CAPS_BURST_MASK);
 			val |= (PCIX_CAPS_MAX_BURST_CPIOB << PCIX_CAPS_BURST_SHIFT);
 			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);
 		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 = tr32(GRC_MISC_CFG);
 	grc_misc_cfg &= GRC_MISC_CFG_BOARD_ID_MASK;
 	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 &&
 	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_5788 ||
 	     grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788M))
 	     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' : ':');
 		       i == 5 ? '\n' : ':');
 
 
 	printk(KERN_INFO "%s: RXcsums[%d] LinkChgREG[%d] "
 	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,
 	       dev->name,
 	       (tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0,
 	       (tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0,
 	       (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) != 0,
 	       (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) != 0,
 	       (tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT) != 0,
 	       (tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT) != 0,
 	       (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 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_NO_ETH_WIRE_SPEED) == 0,
 	       (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) != 0);
 	       (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) != 0);
 	printk(KERN_INFO "%s: dma_rwctrl[%08x] dma_mask[%d-bit]\n",
 	printk(KERN_INFO "%s: dma_rwctrl[%08x] dma_mask[%d-bit]\n",

+ 1 - 4
drivers/net/tg3.h

@@ -2223,7 +2223,7 @@ struct tg3 {
 #define TG3_FLAG_40BIT_DMA_BUG		0x08000000
 #define TG3_FLAG_40BIT_DMA_BUG		0x08000000
 #define TG3_FLAG_BROKEN_CHECKSUMS	0x10000000
 #define TG3_FLAG_BROKEN_CHECKSUMS	0x10000000
 #define TG3_FLAG_GOT_SERDES_FLOWCTL	0x20000000
 #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
 #define TG3_FLAG_INIT_COMPLETE		0x80000000
 	u32				tg3_flags2;
 	u32				tg3_flags2;
 #define TG3_FLG2_RESTART_TIMER		0x00000001
 #define TG3_FLG2_RESTART_TIMER		0x00000001
@@ -2262,9 +2262,6 @@ struct tg3 {
 #define TG3_FLG2_NO_FWARE_REPORTED	0x40000000
 #define TG3_FLG2_NO_FWARE_REPORTED	0x40000000
 #define TG3_FLG2_PHY_ADJUST_TRIM	0x80000000
 #define TG3_FLG2_PHY_ADJUST_TRIM	0x80000000
 
 
-	u32				split_mode_max_reqs;
-#define SPLIT_MODE_5704_MAX_REQ		3
-
 	struct timer_list		timer;
 	struct timer_list		timer;
 	u16				timer_counter;
 	u16				timer_counter;
 	u16				timer_multiplier;
 	u16				timer_multiplier;

+ 0 - 65
drivers/net/wan/lmc/lmc_media.h

@@ -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
-

+ 1 - 0
include/net/fib_rules.h

@@ -34,6 +34,7 @@ struct fib_rules_ops
 	int			family;
 	int			family;
 	struct list_head	list;
 	struct list_head	list;
 	int			rule_size;
 	int			rule_size;
+	int			addr_size;
 
 
 	int			(*action)(struct fib_rule *,
 	int			(*action)(struct fib_rule *,
 					  struct flowi *, int,
 					  struct flowi *, int,

+ 1 - 0
include/net/ip6_fib.h

@@ -58,6 +58,7 @@ struct fib6_node
 	__u16			fn_bit;		/* bit key */
 	__u16			fn_bit;		/* bit key */
 	__u16			fn_flags;
 	__u16			fn_flags;
 	__u32			fn_sernum;
 	__u32			fn_sernum;
+	struct rt6_info		*rr_ptr;
 };
 };
 
 
 #ifndef CONFIG_IPV6_SUBTREES
 #ifndef CONFIG_IPV6_SUBTREES

+ 1 - 1
include/net/neighbour.h

@@ -36,7 +36,7 @@ struct neigh_parms
 	struct net_device *dev;
 	struct net_device *dev;
 	struct neigh_parms *next;
 	struct neigh_parms *next;
 	int	(*neigh_setup)(struct neighbour *);
 	int	(*neigh_setup)(struct neighbour *);
-	void	(*neigh_destructor)(struct neighbour *);
+	void	(*neigh_cleanup)(struct neighbour *);
 	struct neigh_table *tbl;
 	struct neigh_table *tbl;
 
 
 	void	*sysctl_table;
 	void	*sysctl_table;

+ 0 - 9
net/atm/clip.c

@@ -261,14 +261,6 @@ static void clip_pop(struct atm_vcc *vcc, struct sk_buff *skb)
 	spin_unlock_irqrestore(&PRIV(dev)->xoff_lock, flags);
 	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)
 static void clip_neigh_solicit(struct neighbour *neigh, struct sk_buff *skb)
 {
 {
 	DPRINTK("clip_neigh_solicit (neigh %p, skb %p)\n", neigh, 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 ... */
 	/* parameters are copied from ARP ... */
 	.parms = {
 	.parms = {
 		.tbl 			= &clip_tbl,
 		.tbl 			= &clip_tbl,
-		.neigh_destructor	= clip_neigh_destroy,
 		.base_reachable_time 	= 30 * HZ,
 		.base_reachable_time 	= 30 * HZ,
 		.retrans_time 		= 1 * HZ,
 		.retrans_time 		= 1 * HZ,
 		.gc_staletime 		= 60 * HZ,
 		.gc_staletime 		= 60 * HZ,

+ 36 - 25
net/ax25/Kconfig

@@ -1,30 +1,27 @@
 #
 #
 # Amateur Radio protocols and AX.25 device configuration
 # 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
 menuconfig HAMRADIO
 	depends on NET
 	depends on NET
 	bool "Amateur Radio support"
 	bool "Amateur Radio support"
 	help
 	help
 	  If you want to connect your Linux box to an amateur radio, answer Y
 	  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
 	  Note that the answer to this question won't directly affect the
 	  kernel: saying N will just cause the configurator to skip all
 	  kernel: saying N will just cause the configurator to skip all
 	  the questions about amateur radio.
 	  the questions about amateur radio.
 
 
 comment "Packet Radio protocols"
 comment "Packet Radio protocols"
-	depends on HAMRADIO && NET
+	depends on HAMRADIO
 
 
 config AX25
 config AX25
 	tristate "Amateur Radio AX.25 Level 2 protocol"
 	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
 	  This is the protocol used for computer communication over amateur
 	  radio. It is either used by itself for point-to-point links, or to
 	  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
 	  carry other protocols such as tcp/ip. To use it, you need a device
@@ -52,6 +49,7 @@ config AX25
 
 
 config AX25_DAMA_SLAVE
 config AX25_DAMA_SLAVE
 	bool "AX.25 DAMA Slave support"
 	bool "AX.25 DAMA Slave support"
+	default y
 	depends on AX25
 	depends on AX25
 	help
 	help
 	  DAMA is a mechanism to prevent collisions when doing AX.25
 	  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.
 	  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
 	  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
 	  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
 config NETROM
 	tristate "Amateur Radio NET/ROM protocol"
 	tristate "Amateur Radio NET/ROM protocol"
 	depends on AX25
 	depends on AX25
-	---help---
+	help
 	  NET/ROM is a network layer protocol on top of AX.25 useful for
 	  NET/ROM is a network layer protocol on top of AX.25 useful for
 	  routing.
 	  routing.
 
 
 	  A comprehensive listing of all the software for Linux amateur radio
 	  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
 	  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>.
 	  <http://www.tapr.org/tapr/html/pkthome.html>.
 
 
 	  To compile this driver as a module, choose M here: the
 	  To compile this driver as a module, choose M here: the
@@ -84,27 +97,25 @@ config NETROM
 config ROSE
 config ROSE
 	tristate "Amateur Radio X.25 PLP (Rose)"
 	tristate "Amateur Radio X.25 PLP (Rose)"
 	depends on AX25
 	depends on AX25
-	---help---
+	help
 	  The Packet Layer Protocol (PLP) is a way to route packets over X.25
 	  The Packet Layer Protocol (PLP) is a way to route packets over X.25
 	  connections in general and amateur radio AX.25 connections in
 	  connections in general and amateur radio AX.25 connections in
 	  particular, essentially an alternative to NET/ROM.
 	  particular, essentially an alternative to NET/ROM.
 
 
 	  A comprehensive listing of all the software for Linux amateur radio
 	  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
 	  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>.
 	  <http://www.tapr.org/tapr/html/pkthome.html>.
 
 
 	  To compile this driver as a module, choose M here: the
 	  To compile this driver as a module, choose M here: the
 	  module will be called rose.
 	  module will be called rose.
 
 
-
 menu "AX.25 network device drivers"
 menu "AX.25 network device drivers"
-	depends on HAMRADIO && NET && AX25!=n
+	depends on HAMRADIO && AX25
 
 
 source "drivers/net/hamradio/Kconfig"
 source "drivers/net/hamradio/Kconfig"
 
 
 endmenu
 endmenu
-

+ 2 - 2
net/core/dev.c

@@ -1750,10 +1750,10 @@ static int ing_filter(struct sk_buff *skb)
 
 
 		skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_INGRESS);
 		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)
 		if ((q = dev->qdisc_ingress) != NULL)
 			result = q->enqueue(skb, q);
 			result = q->enqueue(skb, q);
-		spin_unlock(&dev->ingress_lock);
+		spin_unlock(&dev->queue_lock);
 
 
 	}
 	}
 
 

+ 30 - 0
net/core/fib_rules.c

@@ -152,6 +152,28 @@ out:
 
 
 EXPORT_SYMBOL_GPL(fib_rules_lookup);
 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)
 int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
 {
 {
 	struct fib_rule_hdr *frh = nlmsg_data(nlh);
 	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)
 	if (err < 0)
 		goto errout;
 		goto errout;
 
 
+	err = validate_rulemsg(frh, tb, ops);
+	if (err < 0)
+		goto errout;
+
 	rule = kzalloc(ops->rule_size, GFP_KERNEL);
 	rule = kzalloc(ops->rule_size, GFP_KERNEL);
 	if (rule == NULL) {
 	if (rule == NULL) {
 		err = -ENOMEM;
 		err = -ENOMEM;
@@ -260,6 +286,10 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
 	if (err < 0)
 	if (err < 0)
 		goto errout;
 		goto errout;
 
 
+	err = validate_rulemsg(frh, tb, ops);
+	if (err < 0)
+		goto errout;
+
 	list_for_each_entry(rule, ops->rules_list, list) {
 	list_for_each_entry(rule, ops->rules_list, list) {
 		if (frh->action && (frh->action != rule->action))
 		if (frh->action && (frh->action != rule->action))
 			continue;
 			continue;

+ 10 - 4
net/core/neighbour.c

@@ -140,6 +140,8 @@ static int neigh_forced_gc(struct neigh_table *tbl)
 				n->dead = 1;
 				n->dead = 1;
 				shrunk	= 1;
 				shrunk	= 1;
 				write_unlock(&n->lock);
 				write_unlock(&n->lock);
+				if (n->parms->neigh_cleanup)
+					n->parms->neigh_cleanup(n);
 				neigh_release(n);
 				neigh_release(n);
 				continue;
 				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);
 				NEIGH_PRINTK2("neigh %p is stray.\n", n);
 			}
 			}
 			write_unlock(&n->lock);
 			write_unlock(&n->lock);
+			if (n->parms->neigh_cleanup)
+				n->parms->neigh_cleanup(n);
 			neigh_release(n);
 			neigh_release(n);
 		}
 		}
 	}
 	}
@@ -582,9 +586,6 @@ void neigh_destroy(struct neighbour *neigh)
 			kfree(hh);
 			kfree(hh);
 	}
 	}
 
 
-	if (neigh->parms->neigh_destructor)
-		(neigh->parms->neigh_destructor)(neigh);
-
 	skb_queue_purge(&neigh->arp_queue);
 	skb_queue_purge(&neigh->arp_queue);
 
 
 	dev_put(neigh->dev);
 	dev_put(neigh->dev);
@@ -675,6 +676,8 @@ static void neigh_periodic_timer(unsigned long arg)
 			*np = n->next;
 			*np = n->next;
 			n->dead = 1;
 			n->dead = 1;
 			write_unlock(&n->lock);
 			write_unlock(&n->lock);
+			if (n->parms->neigh_cleanup)
+				n->parms->neigh_cleanup(n);
 			neigh_release(n);
 			neigh_release(n);
 			continue;
 			continue;
 		}
 		}
@@ -2088,8 +2091,11 @@ void __neigh_for_each_release(struct neigh_table *tbl,
 			} else
 			} else
 				np = &n->next;
 				np = &n->next;
 			write_unlock(&n->lock);
 			write_unlock(&n->lock);
-			if (release)
+			if (release) {
+				if (n->parms->neigh_cleanup)
+					n->parms->neigh_cleanup(n);
 				neigh_release(n);
 				neigh_release(n);
+			}
 		}
 		}
 	}
 	}
 }
 }

+ 0 - 1
net/dccp/dccp.h

@@ -191,7 +191,6 @@ extern void dccp_send_sync(struct sock *sk, const u64 seq,
 			   const enum dccp_pkt_type pkt_type);
 			   const enum dccp_pkt_type pkt_type);
 
 
 extern void dccp_write_xmit(struct sock *sk, int block);
 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_write_space(struct sock *sk);
 
 
 extern void dccp_init_xmit_timers(struct sock *sk);
 extern void dccp_init_xmit_timers(struct sock *sk);

+ 1 - 1
net/dccp/timer.c

@@ -262,7 +262,7 @@ out:
 }
 }
 
 
 /* Transmit-delay timer: used by the CCIDs to delay actual send time */
 /* 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 sock *sk = (struct sock *)data;
 	struct dccp_sock *dp = dccp_sk(sk);
 	struct dccp_sock *dp = dccp_sk(sk);

+ 4 - 1
net/decnet/dn_fib.c

@@ -63,7 +63,7 @@ static struct
 {
 {
 	int error;
 	int error;
 	u8 scope;
 	u8 scope;
-} dn_fib_props[RTA_MAX+1] = {
+} dn_fib_props[RTN_MAX+1] = {
 	[RTN_UNSPEC] =      { .error = 0,       .scope = RT_SCOPE_NOWHERE },
 	[RTN_UNSPEC] =      { .error = 0,       .scope = RT_SCOPE_NOWHERE },
 	[RTN_UNICAST] =     { .error = 0,       .scope = RT_SCOPE_UNIVERSE },
 	[RTN_UNICAST] =     { .error = 0,       .scope = RT_SCOPE_UNIVERSE },
 	[RTN_LOCAL] =       { .error = 0,       .scope = RT_SCOPE_HOST },
 	[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;
 	struct dn_fib_info *ofi;
 	int nhs = 1;
 	int nhs = 1;
 
 
+	if (r->rtm_type > RTN_MAX)
+		goto err_inval;
+
 	if (dn_fib_props[r->rtm_type].scope > r->rtm_scope)
 	if (dn_fib_props[r->rtm_type].scope > r->rtm_scope)
 		goto err_inval;
 		goto err_inval;
 
 

+ 6 - 7
net/decnet/dn_rules.c

@@ -109,8 +109,6 @@ errout:
 
 
 static struct nla_policy dn_fib_rule_policy[FRA_MAX+1] __read_mostly = {
 static struct nla_policy dn_fib_rule_policy[FRA_MAX+1] __read_mostly = {
 	FRA_GENERIC_POLICY,
 	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)
 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;
 	int err = -EINVAL;
 	struct dn_fib_rule *r = (struct dn_fib_rule *)rule;
 	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;
 		goto  errout;
 
 
 	if (rule->table == RT_TABLE_UNSPEC) {
 	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]);
 		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->dst = nla_get_le16(tb[FRA_DST]);
 
 
 	r->src_len = frh->src_len;
 	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))
 	if (frh->dst_len && (r->dst_len != frh->dst_len))
 		return 0;
 		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;
 		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 0;
 
 
 	return 1;
 	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 = {
 static struct fib_rules_ops dn_fib_rules_ops = {
 	.family		= AF_DECnet,
 	.family		= AF_DECnet,
 	.rule_size	= sizeof(struct dn_fib_rule),
 	.rule_size	= sizeof(struct dn_fib_rule),
+	.addr_size	= sizeof(u16),
 	.action		= dn_fib_rule_action,
 	.action		= dn_fib_rule_action,
 	.match		= dn_fib_rule_match,
 	.match		= dn_fib_rule_match,
 	.configure	= dn_fib_rule_configure,
 	.configure	= dn_fib_rule_configure,

+ 5 - 0
net/ipv4/fib_frontend.c

@@ -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.pid = NETLINK_CB(skb).pid;
 	cfg->fc_nlinfo.nlh = nlh;
 	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) {
 	nlmsg_for_each_attr(attr, nlh, sizeof(struct rtmsg), remaining) {
 		switch (attr->nla_type) {
 		switch (attr->nla_type) {
 		case RTA_DST:
 		case RTA_DST:

+ 6 - 8
net/ipv4/fib_rules.c

@@ -171,8 +171,6 @@ static struct fib_table *fib_empty_table(void)
 
 
 static struct nla_policy fib4_rule_policy[FRA_MAX+1] __read_mostly = {
 static struct nla_policy fib4_rule_policy[FRA_MAX+1] __read_mostly = {
 	FRA_GENERIC_POLICY,
 	FRA_GENERIC_POLICY,
-	[FRA_SRC]	= { .type = NLA_U32 },
-	[FRA_DST]	= { .type = NLA_U32 },
 	[FRA_FLOW]	= { .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;
 	int err = -EINVAL;
 	struct fib4_rule *rule4 = (struct fib4_rule *) rule;
 	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;
 		goto errout;
 
 
 	if (rule->table == RT_TABLE_UNSPEC) {
 	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]);
 		rule4->src = nla_get_be32(tb[FRA_SRC]);
 
 
-	if (tb[FRA_DST])
+	if (frh->dst_len)
 		rule4->dst = nla_get_be32(tb[FRA_DST]);
 		rule4->dst = nla_get_be32(tb[FRA_DST]);
 
 
 #ifdef CONFIG_NET_CLS_ROUTE
 #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;
 		return 0;
 #endif
 #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;
 		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 0;
 
 
 	return 1;
 	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 = {
 static struct fib_rules_ops fib4_rules_ops = {
 	.family		= AF_INET,
 	.family		= AF_INET,
 	.rule_size	= sizeof(struct fib4_rule),
 	.rule_size	= sizeof(struct fib4_rule),
+	.addr_size	= sizeof(u32),
 	.action		= fib4_rule_action,
 	.action		= fib4_rule_action,
 	.match		= fib4_rule_match,
 	.match		= fib4_rule_match,
 	.configure	= fib4_rule_configure,
 	.configure	= fib4_rule_configure,

+ 1 - 1
net/ipv4/fib_semantics.c

@@ -89,7 +89,7 @@ static const struct
 {
 {
 	int	error;
 	int	error;
 	u8	scope;
 	u8	scope;
-} fib_props[RTA_MAX + 1] = {
+} fib_props[RTN_MAX + 1] = {
 	{
 	{
 		.error	= 0,
 		.error	= 0,
 		.scope	= RT_SCOPE_NOWHERE,
 		.scope	= RT_SCOPE_NOWHERE,

+ 9 - 0
net/ipv4/fib_trie.c

@@ -1123,6 +1123,9 @@ err:
 	return fa_head;
 	return fa_head;
 }
 }
 
 
+/*
+ * Caller must hold RTNL.
+ */
 static int fn_trie_insert(struct fib_table *tb, struct fib_config *cfg)
 static int fn_trie_insert(struct fib_table *tb, struct fib_config *cfg)
 {
 {
 	struct trie *t = (struct trie *) tb->tb_data;
 	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;
 	return 1;
 }
 }
 
 
+/*
+ * Caller must hold RTNL.
+ */
 static int fn_trie_delete(struct fib_table *tb, struct fib_config *cfg)
 static int fn_trie_delete(struct fib_table *tb, struct fib_config *cfg)
 {
 {
 	struct trie *t = (struct trie *) tb->tb_data;
 	struct trie *t = (struct trie *) tb->tb_data;
@@ -1718,6 +1724,9 @@ up:
 	return NULL; /* Ready. Root of trie */
 	return NULL; /* Ready. Root of trie */
 }
 }
 
 
+/*
+ * Caller must hold RTNL.
+ */
 static int fn_trie_flush(struct fib_table *tb)
 static int fn_trie_flush(struct fib_table *tb)
 {
 {
 	struct trie *t = (struct trie *) tb->tb_data;
 	struct trie *t = (struct trie *) tb->tb_data;

+ 5 - 9
net/ipv6/fib6_rules.c

@@ -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 = {
 static struct nla_policy fib6_rule_policy[FRA_MAX+1] __read_mostly = {
 	FRA_GENERIC_POLICY,
 	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,
 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;
 	int err = -EINVAL;
 	struct fib6_rule *rule6 = (struct fib6_rule *) rule;
 	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->action == FR_ACT_TO_TBL) {
 		if (rule->table == RT6_TABLE_UNSPEC)
 		if (rule->table == RT6_TABLE_UNSPEC)
 			goto errout;
 			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],
 		nla_memcpy(&rule6->src.addr, tb[FRA_SRC],
 			   sizeof(struct in6_addr));
 			   sizeof(struct in6_addr));
 
 
-	if (tb[FRA_DST])
+	if (frh->dst_len)
 		nla_memcpy(&rule6->dst.addr, tb[FRA_DST],
 		nla_memcpy(&rule6->dst.addr, tb[FRA_DST],
 			   sizeof(struct in6_addr));
 			   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))
 	if (frh->tos && (rule6->tclass != frh->tos))
 		return 0;
 		return 0;
 
 
-	if (tb[FRA_SRC] &&
+	if (frh->src_len &&
 	    nla_memcmp(tb[FRA_SRC], &rule6->src.addr, sizeof(struct in6_addr)))
 	    nla_memcmp(tb[FRA_SRC], &rule6->src.addr, sizeof(struct in6_addr)))
 		return 0;
 		return 0;
 
 
-	if (tb[FRA_DST] &&
+	if (frh->dst_len &&
 	    nla_memcmp(tb[FRA_DST], &rule6->dst.addr, sizeof(struct in6_addr)))
 	    nla_memcmp(tb[FRA_DST], &rule6->dst.addr, sizeof(struct in6_addr)))
 		return 0;
 		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 = {
 static struct fib_rules_ops fib6_rules_ops = {
 	.family			= AF_INET6,
 	.family			= AF_INET6,
 	.rule_size		= sizeof(struct fib6_rule),
 	.rule_size		= sizeof(struct fib6_rule),
+	.addr_size		= sizeof(struct in6_addr),
 	.action			= fib6_rule_action,
 	.action			= fib6_rule_action,
 	.match			= fib6_rule_match,
 	.match			= fib6_rule_match,
 	.configure		= fib6_rule_configure,
 	.configure		= fib6_rule_configure,

+ 8 - 0
net/ipv6/ip6_fib.c

@@ -658,6 +658,10 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
 		ins = &iter->u.dst.rt6_next;
 		ins = &iter->u.dst.rt6_next;
 	}
 	}
 
 
+	/* Reset round-robin state, if necessary */
+	if (ins == &fn->leaf)
+		fn->rr_ptr = NULL;
+
 	/*
 	/*
 	 *	insert node
 	 *	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_rt_entries--;
 	rt6_stats.fib_discarded_routes++;
 	rt6_stats.fib_discarded_routes++;
 
 
+	/* Reset round-robin state, if necessary */
+	if (fn->rr_ptr == rt)
+		fn->rr_ptr = NULL;
+
 	/* Adjust walkers */
 	/* Adjust walkers */
 	read_lock(&fib6_walker_lock);
 	read_lock(&fib6_walker_lock);
 	FOR_WALKERS(w) {
 	FOR_WALKERS(w) {

+ 59 - 38
net/ipv6/route.c

@@ -363,55 +363,76 @@ static int rt6_score_route(struct rt6_info *rt, int oif,
 	return m;
 	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;
 	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 &&
 	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 */
 		/* 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);
 	return (match ? match : &ip6_null_entry);
 }
 }
@@ -657,7 +678,7 @@ restart_2:
 	fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
 	fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
 
 
 restart:
 restart:
-	rt = rt6_select(&fn->leaf, fl->iif, strict | reachable);
+	rt = rt6_select(fn, fl->iif, strict | reachable);
 	BACKTRACK(&fl->fl6_src);
 	BACKTRACK(&fl->fl6_src);
 	if (rt == &ip6_null_entry ||
 	if (rt == &ip6_null_entry ||
 	    rt->rt6i_flags & RTF_CACHE)
 	    rt->rt6i_flags & RTF_CACHE)
@@ -752,7 +773,7 @@ restart_2:
 	fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
 	fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
 
 
 restart:
 restart:
-	rt = rt6_select(&fn->leaf, fl->oif, strict | reachable);
+	rt = rt6_select(fn, fl->oif, strict | reachable);
 	BACKTRACK(&fl->fl6_src);
 	BACKTRACK(&fl->fl6_src);
 	if (rt == &ip6_null_entry ||
 	if (rt == &ip6_null_entry ||
 	    rt->rt6i_flags & RTF_CACHE)
 	    rt->rt6i_flags & RTF_CACHE)

+ 7 - 9
net/sched/cls_basic.c

@@ -81,6 +81,13 @@ static void basic_put(struct tcf_proto *tp, unsigned long f)
 
 
 static int basic_init(struct tcf_proto *tp)
 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;
 	return 0;
 }
 }
 
 
@@ -176,15 +183,6 @@ static int basic_change(struct tcf_proto *tp, unsigned long base, u32 handle,
 	}
 	}
 
 
 	err = -ENOBUFS;
 	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);
 	f = kzalloc(sizeof(*f), GFP_KERNEL);
 	if (f == NULL)
 	if (f == NULL)
 		goto errout;
 		goto errout;

+ 6 - 1
net/socket.c

@@ -1381,7 +1381,7 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,
 
 
 	err = sock_attach_fd(newsock, newfile);
 	err = sock_attach_fd(newsock, newfile);
 	if (err < 0)
 	if (err < 0)
-		goto out_fd;
+		goto out_fd_simple;
 
 
 	err = security_socket_accept(sock, newsock);
 	err = security_socket_accept(sock, newsock);
 	if (err)
 	if (err)
@@ -1414,6 +1414,11 @@ out_put:
 	fput_light(sock->file, fput_needed);
 	fput_light(sock->file, fput_needed);
 out:
 out:
 	return err;
 	return err;
+out_fd_simple:
+	sock_release(newsock);
+	put_filp(newfile);
+	put_unused_fd(newfd);
+	goto out_put;
 out_fd:
 out_fd:
 	fput(newfile);
 	fput(newfile);
 	put_unused_fd(newfd);
 	put_unused_fd(newfd);