提交 703071b5 编写于 作者: L Linus Torvalds

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
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.
......@@ -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
......
......@@ -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;
}
......
......@@ -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);
}
......
......@@ -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
......
......@@ -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",
......
......@@ -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;
......
#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
......@@ -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,
......
......@@ -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
......
......@@ -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;
......
......@@ -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,
......
#
# 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
......@@ -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);
}
......
......@@ -152,6 +152,28 @@ int fib_rules_lookup(struct fib_rules_ops *ops, struct flowi *fl,
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;
......
......@@ -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);
}
}
}
}
......
......@@ -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);
......
......@@ -262,7 +262,7 @@ static void dccp_delack_timer(unsigned long data)
}
/* 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);
......
......@@ -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;
......
......@@ -109,8 +109,6 @@ static int dn_fib_rule_action(struct fib_rule *rule, struct flowi *flp,
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,
......
......@@ -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:
......
......@@ -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,
......
......@@ -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,
......
......@@ -1123,6 +1123,9 @@ fib_insert_node(struct trie *t, int *err, u32 key, int plen)
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 @@ static struct leaf *nextleaf(struct trie *t, struct leaf *thisleaf)
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;
......
......@@ -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,
......
......@@ -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) {
......
......@@ -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 @@ static struct rt6_info *ip6_pol_route_input(struct fib6_table *table,
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 @@ static struct rt6_info *ip6_pol_route_output(struct fib6_table *table,
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)
......
......@@ -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;
......
......@@ -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 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,
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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册