aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-03-23 15:29:27 -0800
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-23 15:29:27 -0800
commit554f593d6c411e717a71ffdcb0cfb46bb2394502 (patch)
tree338e1629408a66cfc84d199c18deb22c6e682c22
parentdebf798b1ed82053689d900670eb27fb2f1b4bd3 (diff)
parent95381c893dd71a534ab56f09b12a4e2118aa0f32 (diff)
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: [TG3]: Update driver version and reldate. [TG3]: Add 5755 nvram support [TG3]: Add 5755 support [IPV6]: ip6_xmit: remove unnecessary NULL ptr check [NET_SCHED]: cls_u32: remove unnecessary NULL-ptr check [IPV4]: Add fib rule netlink notifications [BNX2]: Update version and reldate [BNX2]: Separate tx producer and consumer fields [BNX2]: Move .h files to bnx2.c [BNX2]: Combine small mem allocations [BNX2]: Fix link change handling [PKTGEN]: Add MPLS extension.
-rw-r--r--Documentation/networking/pktgen.txt20
-rw-r--r--drivers/net/bnx2.c108
-rw-r--r--drivers/net/bnx2.h62
-rw-r--r--drivers/net/tg3.c84
-rw-r--r--drivers/net/tg3.h9
-rw-r--r--include/linux/pci_ids.h2
-rw-r--r--include/linux/rtnetlink.h4
-rw-r--r--net/core/pktgen.c158
-rw-r--r--net/ipv4/fib_rules.c27
-rw-r--r--net/ipv6/ip6_output.c2
-rw-r--r--net/sched/cls_u32.c6
11 files changed, 371 insertions, 111 deletions
diff --git a/Documentation/networking/pktgen.txt b/Documentation/networking/pktgen.txt
index cc4b4d04129..278771c9ad9 100644
--- a/Documentation/networking/pktgen.txt
+++ b/Documentation/networking/pktgen.txt
@@ -109,6 +109,22 @@ Examples:
cycle through the port range.
pgset "udp_dst_max 9" set UDP destination port max.
+ pgset "mpls 0001000a,0002000a,0000000a" set MPLS labels (in this example
+ outer label=16,middle label=32,
+ inner label=0 (IPv4 NULL)) Note that
+ there must be no spaces between the
+ arguments. Leading zeros are required.
+ Do not set the bottom of stack bit,
+ thats done automatically. If you do
+ set the bottom of stack bit, that
+ indicates that you want to randomly
+ generate that address and the flag
+ MPLS_RND will be turned on. You
+ can have any mix of random and fixed
+ labels in the label stack.
+
+ pgset "mpls 0" turn off mpls (or any invalid argument works too!)
+
pgset stop aborts injection. Also, ^C aborts generator.
@@ -167,6 +183,8 @@ pkt_size
min_pkt_size
max_pkt_size
+mpls
+
udp_src_min
udp_src_max
@@ -211,4 +229,4 @@ Grant Grundler for testing on IA-64 and parisc, Harald Welte, Lennert Buytenhek
Stephen Hemminger, Andi Kleen, Dave Miller and many others.
-Good luck with the linux net-development. \ No newline at end of file
+Good luck with the linux net-development.
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 7d213707008..2671da20a49 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -9,13 +9,54 @@
* Written by: Michael Chan (mchan@broadcom.com)
*/
+#include <linux/config.h>
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/dma-mapping.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <linux/delay.h>
+#include <asm/byteorder.h>
+#include <linux/time.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#ifdef NETIF_F_HW_VLAN_TX
+#include <linux/if_vlan.h>
+#define BCM_VLAN 1
+#endif
+#ifdef NETIF_F_TSO
+#include <net/ip.h>
+#include <net/tcp.h>
+#include <net/checksum.h>
+#define BCM_TSO 1
+#endif
+#include <linux/workqueue.h>
+#include <linux/crc32.h>
+#include <linux/prefetch.h>
+#include <linux/cache.h>
+
#include "bnx2.h"
#include "bnx2_fw.h"
#define DRV_MODULE_NAME "bnx2"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "1.4.38"
-#define DRV_MODULE_RELDATE "February 10, 2006"
+#define DRV_MODULE_VERSION "1.4.39"
+#define DRV_MODULE_RELDATE "March 22, 2006"
#define RUN_AT(x) (jiffies + (x))
@@ -313,8 +354,6 @@ bnx2_disable_int(struct bnx2 *bp)
static void
bnx2_enable_int(struct bnx2 *bp)
{
- u32 val;
-
REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
BNX2_PCICFG_INT_ACK_CMD_MASK_INT | bp->last_status_idx);
@@ -322,8 +361,7 @@ bnx2_enable_int(struct bnx2 *bp)
REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | bp->last_status_idx);
- val = REG_RD(bp, BNX2_HC_COMMAND);
- REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW);
+ REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW);
}
static void
@@ -362,15 +400,11 @@ bnx2_free_mem(struct bnx2 *bp)
{
int i;
- if (bp->stats_blk) {
- pci_free_consistent(bp->pdev, sizeof(struct statistics_block),
- bp->stats_blk, bp->stats_blk_mapping);
- bp->stats_blk = NULL;
- }
if (bp->status_blk) {
- pci_free_consistent(bp->pdev, sizeof(struct status_block),
+ pci_free_consistent(bp->pdev, bp->status_stats_size,
bp->status_blk, bp->status_blk_mapping);
bp->status_blk = NULL;
+ bp->stats_blk = NULL;
}
if (bp->tx_desc_ring) {
pci_free_consistent(bp->pdev,
@@ -395,14 +429,13 @@ bnx2_free_mem(struct bnx2 *bp)
static int
bnx2_alloc_mem(struct bnx2 *bp)
{
- int i;
+ int i, status_blk_size;
- bp->tx_buf_ring = kmalloc(sizeof(struct sw_bd) * TX_DESC_CNT,
- GFP_KERNEL);
+ bp->tx_buf_ring = kzalloc(sizeof(struct sw_bd) * TX_DESC_CNT,
+ GFP_KERNEL);
if (bp->tx_buf_ring == NULL)
return -ENOMEM;
- memset(bp->tx_buf_ring, 0, sizeof(struct sw_bd) * TX_DESC_CNT);
bp->tx_desc_ring = pci_alloc_consistent(bp->pdev,
sizeof(struct tx_bd) *
TX_DESC_CNT,
@@ -428,21 +461,22 @@ bnx2_alloc_mem(struct bnx2 *bp)
}
- bp->status_blk = pci_alloc_consistent(bp->pdev,
- sizeof(struct status_block),
+ /* Combine status and statistics blocks into one allocation. */
+ status_blk_size = L1_CACHE_ALIGN(sizeof(struct status_block));
+ bp->status_stats_size = status_blk_size +
+ sizeof(struct statistics_block);
+
+ bp->status_blk = pci_alloc_consistent(bp->pdev, bp->status_stats_size,
&bp->status_blk_mapping);
if (bp->status_blk == NULL)
goto alloc_mem_err;
- memset(bp->status_blk, 0, sizeof(struct status_block));
+ memset(bp->status_blk, 0, bp->status_stats_size);
- bp->stats_blk = pci_alloc_consistent(bp->pdev,
- sizeof(struct statistics_block),
- &bp->stats_blk_mapping);
- if (bp->stats_blk == NULL)
- goto alloc_mem_err;
+ bp->stats_blk = (void *) ((unsigned long) bp->status_blk +
+ status_blk_size);
- memset(bp->stats_blk, 0, sizeof(struct statistics_block));
+ bp->stats_blk_mapping = bp->status_blk_mapping + status_blk_size;
return 0;
@@ -1926,6 +1960,13 @@ bnx2_poll(struct net_device *dev, int *budget)
spin_lock(&bp->phy_lock);
bnx2_phy_int(bp);
spin_unlock(&bp->phy_lock);
+
+ /* This is needed to take care of transient status
+ * during link changes.
+ */
+ REG_WR(bp, BNX2_HC_COMMAND,
+ bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
+ REG_RD(bp, BNX2_HC_COMMAND);
}
if (bp->status_blk->status_tx_quick_consumer_index0 != bp->hw_tx_cons)
@@ -3307,6 +3348,8 @@ bnx2_init_chip(struct bnx2 *bp)
udelay(20);
+ bp->hc_cmd = REG_RD(bp, BNX2_HC_COMMAND);
+
return rc;
}
@@ -3746,7 +3789,6 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
struct sk_buff *skb, *rx_skb;
unsigned char *packet;
u16 rx_start_idx, rx_idx;
- u32 val;
dma_addr_t map;
struct tx_bd *txbd;
struct sw_bd *rx_buf;
@@ -3777,8 +3819,9 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
map = pci_map_single(bp->pdev, skb->data, pkt_size,
PCI_DMA_TODEVICE);
- val = REG_RD(bp, BNX2_HC_COMMAND);
- REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
+ REG_WR(bp, BNX2_HC_COMMAND,
+ bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
+
REG_RD(bp, BNX2_HC_COMMAND);
udelay(5);
@@ -3802,8 +3845,9 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
udelay(100);
- val = REG_RD(bp, BNX2_HC_COMMAND);
- REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
+ REG_WR(bp, BNX2_HC_COMMAND,
+ bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
+
REG_RD(bp, BNX2_HC_COMMAND);
udelay(5);
@@ -3939,7 +3983,6 @@ static int
bnx2_test_intr(struct bnx2 *bp)
{
int i;
- u32 val;
u16 status_idx;
if (!netif_running(bp->dev))
@@ -3948,8 +3991,7 @@ bnx2_test_intr(struct bnx2 *bp)
status_idx = REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD) & 0xffff;
/* This register is not touched during run-time. */
- val = REG_RD(bp, BNX2_HC_COMMAND);
- REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW);
+ REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW);
REG_RD(bp, BNX2_HC_COMMAND);
for (i = 0; i < 10; i++) {
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index fd4b7f2eb47..b87925f6a22 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -13,46 +13,6 @@
#ifndef BNX2_H
#define BNX2_H
-#include <linux/config.h>
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-
-#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/dma-mapping.h>
-#include <asm/bitops.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <linux/delay.h>
-#include <asm/byteorder.h>
-#include <linux/time.h>
-#include <linux/ethtool.h>
-#include <linux/mii.h>
-#ifdef NETIF_F_HW_VLAN_TX
-#include <linux/if_vlan.h>
-#define BCM_VLAN 1
-#endif
-#ifdef NETIF_F_TSO
-#include <net/ip.h>
-#include <net/tcp.h>
-#include <net/checksum.h>
-#define BCM_TSO 1
-#endif
-#include <linux/workqueue.h>
-#include <linux/crc32.h>
-#include <linux/prefetch.h>
-
/* Hardware data structures and register definitions automatically
* generated from RTL code. Do not modify.
*/
@@ -3917,15 +3877,17 @@ struct bnx2 {
#define USING_MSI_FLAG 0x20
#define ASF_ENABLE_FLAG 0x40
- struct tx_bd *tx_desc_ring;
- struct sw_bd *tx_buf_ring;
- u32 tx_prod_bseq;
- u16 tx_prod;
- u16 tx_cons;
- int tx_ring_size;
+ /* Put tx producer and consumer fields in separate cache lines. */
- u16 hw_tx_cons;
- u16 hw_rx_cons;
+ u32 tx_prod_bseq __attribute__((aligned(L1_CACHE_BYTES)));
+ u16 tx_prod;
+
+ struct tx_bd *tx_desc_ring;
+ struct sw_bd *tx_buf_ring;
+ int tx_ring_size;
+
+ u16 tx_cons __attribute__((aligned(L1_CACHE_BYTES)));
+ u16 hw_tx_cons;
#ifdef BCM_VLAN
struct vlan_group *vlgrp;
@@ -3939,6 +3901,7 @@ struct bnx2 {
u32 rx_prod_bseq;
u16 rx_prod;
u16 rx_cons;
+ u16 hw_rx_cons;
u32 rx_csum;
@@ -4038,6 +4001,7 @@ struct bnx2 {
struct statistics_block *stats_blk;
dma_addr_t stats_blk_mapping;
+ u32 hc_cmd;
u32 rx_mode;
u16 req_line_speed;
@@ -4082,6 +4046,8 @@ struct bnx2 {
struct flash_spec *flash_info;
u32 flash_size;
+
+ int status_stats_size;
};
static u32 bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset);
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 88829eb9568..b5473325bff 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -69,8 +69,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "3.53"
-#define DRV_MODULE_RELDATE "Mar 22, 2006"
+#define DRV_MODULE_VERSION "3.54"
+#define DRV_MODULE_RELDATE "Mar 23, 2006"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
@@ -225,6 +225,10 @@ static struct pci_device_id tg3_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754M,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+ { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+ { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755M,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M,
@@ -4557,6 +4561,7 @@ static int tg3_chip_reset(struct tg3 *tp)
}
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
tw32(GRC_FASTBOOT_PC, 0);
@@ -6152,6 +6157,9 @@ static int tg3_reset_hw(struct tg3 *tp)
gpio_mask |= GRC_LCLCTRL_GPIO_OE3 |
GRC_LCLCTRL_GPIO_OUTPUT3;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
+ gpio_mask |= GRC_LCLCTRL_GPIO_UART_SEL;
+
tp->grc_local_ctrl |= tr32(GRC_LOCAL_CTRL) & gpio_mask;
/* GPIO1 must be driven high for eeprom write protect */
@@ -6191,7 +6199,8 @@ static int tg3_reset_hw(struct tg3 *tp)
}
/* Enable host coalescing bug fix */
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
+ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) ||
+ (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787))
val |= (1 << 29);
tw32_f(WDMAC_MODE, val);
@@ -6249,6 +6258,9 @@ static int tg3_reset_hw(struct tg3 *tp)
udelay(100);
tp->rx_mode = RX_MODE_ENABLE;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
+ tp->rx_mode |= RX_MODE_IPV6_CSUM_ENABLE;
+
tw32_f(MAC_RX_MODE, tp->rx_mode);
udelay(10);
@@ -7907,7 +7919,8 @@ static int tg3_set_tx_csum(struct net_device *dev, u32 data)
return 0;
}
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
ethtool_op_set_tx_hw_csum(dev, data);
else
ethtool_op_set_tx_csum(dev, data);
@@ -8332,7 +8345,8 @@ static int tg3_test_memory(struct tg3 *tp)
int i;
if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) {
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
mem_tbl = mem_tbl_5755;
else
mem_tbl = mem_tbl_5705;
@@ -8924,6 +8938,47 @@ static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp)
}
}
+static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp)
+{
+ u32 nvcfg1;
+
+ nvcfg1 = tr32(NVRAM_CFG1);
+
+ /* NVRAM protection for TPM */
+ if (nvcfg1 & (1 << 27))
+ tp->tg3_flags2 |= TG3_FLG2_PROTECTED_NVRAM;
+
+ switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
+ case FLASH_5755VENDOR_ATMEL_EEPROM_64KHZ:
+ case FLASH_5755VENDOR_ATMEL_EEPROM_376KHZ:
+ tp->nvram_jedecnum = JEDEC_ATMEL;
+ tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+ tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
+
+ nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS;
+ tw32(NVRAM_CFG1, nvcfg1);
+ break;
+ case FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED:
+ case FLASH_5755VENDOR_ATMEL_FLASH_1:
+ case FLASH_5755VENDOR_ATMEL_FLASH_2:
+ case FLASH_5755VENDOR_ATMEL_FLASH_3:
+ case FLASH_5755VENDOR_ATMEL_FLASH_4:
+ tp->nvram_jedecnum = JEDEC_ATMEL;
+ tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+ tp->tg3_flags2 |= TG3_FLG2_FLASH;
+ tp->nvram_pagesize = 264;
+ break;
+ case FLASH_5752VENDOR_ST_M45PE10:
+ case FLASH_5752VENDOR_ST_M45PE20:
+ case FLASH_5752VENDOR_ST_M45PE40:
+ tp->nvram_jedecnum = JEDEC_ST;
+ tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+ tp->tg3_flags2 |= TG3_FLG2_FLASH;
+ tp->nvram_pagesize = 256;
+ break;
+ }
+}
+
static void __devinit tg3_get_5787_nvram_info(struct tg3 *tp)
{
u32 nvcfg1;
@@ -8997,6 +9052,8 @@ static void __devinit tg3_nvram_init(struct tg3 *tp)
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752)
tg3_get_5752_nvram_info(tp);
+ else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
+ tg3_get_5755_nvram_info(tp);
else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
tg3_get_5787_nvram_info(tp);
else
@@ -9310,6 +9367,7 @@ static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len,
nvram_cmd |= NVRAM_CMD_LAST;
if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752) &&
+ (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5755) &&
(GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787) &&
(tp->nvram_jedecnum == JEDEC_ST) &&
(nvram_cmd & NVRAM_CMD_FIRST)) {
@@ -10044,6 +10102,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
(tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
tp->tg3_flags2 |= TG3_FLG2_5750_PLUS;
@@ -10053,7 +10112,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
tp->tg3_flags2 |= TG3_FLG2_5705_PLUS;
if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) {
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) {
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) {
tp->tg3_flags2 |= TG3_FLG2_HW_TSO_2;
tp->tg3_flags2 |= TG3_FLG2_1SHOT_MSI;
} else
@@ -10063,6 +10123,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750 &&
GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752 &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5755 &&
GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787)
tp->tg3_flags2 |= TG3_FLG2_JUMBO_CAPABLE;
@@ -10219,6 +10280,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752)
tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
+ tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL;
+
/* Force the chip into D0. */
err = tg3_set_power_state(tp, PCI_D0);
if (err) {
@@ -10274,6 +10338,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
tp->tg3_flags2 |= TG3_FLG2_PHY_5704_A0_BUG;
if ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) &&
+ (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5755) &&
(GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787))
tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG;
@@ -10413,7 +10478,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
/* All chips before 5787 can get confused if TX buffers
* straddle the 4GB address boundary in some cases.
*/
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
tp->dev->hard_start_xmit = tg3_start_xmit;
else
tp->dev->hard_start_xmit = tg3_start_xmit_dma_bug;
@@ -11002,6 +11068,7 @@ static char * __devinit tg3_phy_string(struct tg3 *tp)
case PHY_ID_BCM5752: return "5752";
case PHY_ID_BCM5714: return "5714";
case PHY_ID_BCM5780: return "5780";
+ case PHY_ID_BCM5755: return "5755";
case PHY_ID_BCM5787: return "5787";
case PHY_ID_BCM8002: return "8002/serdes";
case 0: return "serdes";
@@ -11350,7 +11417,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
* checksumming.
*/
if ((tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) == 0) {
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
dev->features |= NETIF_F_HW_CSUM;
else
dev->features |= NETIF_F_IP_CSUM;
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index baa34c4721d..c43cc326420 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -138,6 +138,7 @@
#define ASIC_REV_5752 0x06
#define ASIC_REV_5780 0x08
#define ASIC_REV_5714 0x09
+#define ASIC_REV_5755 0x0a
#define ASIC_REV_5787 0x0b
#define GET_CHIP_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 8)
#define CHIPREV_5700_AX 0x70
@@ -456,6 +457,7 @@
#define RX_MODE_PROMISC 0x00000100
#define RX_MODE_NO_CRC_CHECK 0x00000200
#define RX_MODE_KEEP_VLAN_TAG 0x00000400
+#define RX_MODE_IPV6_CSUM_ENABLE 0x01000000
#define MAC_RX_STATUS 0x0000046c
#define RX_STATUS_REMOTE_TX_XOFFED 0x00000001
#define RX_STATUS_XOFF_RCVD 0x00000002
@@ -1340,6 +1342,7 @@
#define GRC_LCLCTRL_CLEARINT 0x00000002
#define GRC_LCLCTRL_SETINT 0x00000004
#define GRC_LCLCTRL_INT_ON_ATTN 0x00000008
+#define GRC_LCLCTRL_GPIO_UART_SEL 0x00000010 /* 5755 only */
#define GRC_LCLCTRL_USE_SIG_DETECT 0x00000010 /* 5714/5780 only */
#define GRC_LCLCTRL_USE_EXT_SIG_DETECT 0x00000020 /* 5714/5780 only */
#define GRC_LCLCTRL_GPIO_INPUT3 0x00000020
@@ -1441,6 +1444,9 @@
#define FLASH_5755VENDOR_ATMEL_FLASH_1 0x03400001
#define FLASH_5755VENDOR_ATMEL_FLASH_2 0x03400002
#define FLASH_5755VENDOR_ATMEL_FLASH_3 0x03400000
+#define FLASH_5755VENDOR_ATMEL_FLASH_4 0x00000003
+#define FLASH_5755VENDOR_ATMEL_EEPROM_64KHZ 0x03c00003
+#define FLASH_5755VENDOR_ATMEL_EEPROM_376KHZ 0x03c00002
#define FLASH_5787VENDOR_ATMEL_EEPROM_64KHZ 0x03000003
#define FLASH_5787VENDOR_ATMEL_EEPROM_376KHZ 0x03000002
#define FLASH_5787VENDOR_MICRO_EEPROM_64KHZ 0x03000000
@@ -2259,6 +2265,7 @@ struct tg3 {
#define PHY_ID_BCM5752 0x60008100
#define PHY_ID_BCM5714 0x60008340
#define PHY_ID_BCM5780 0x60008350
+#define PHY_ID_BCM5755 0xbc050cc0
#define PHY_ID_BCM5787 0xbc050ce0
#define PHY_ID_BCM8002 0x60010140
#define PHY_ID_INVALID 0xffffffff
@@ -2286,7 +2293,7 @@ struct tg3 {
(X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \
(X) == PHY_ID_BCM5752 || (X) == PHY_ID_BCM5714 || \
(X) == PHY_ID_BCM5780 || (X) == PHY_ID_BCM5787 || \
- (X) == PHY_ID_BCM8002)
+ (X) == PHY_ID_BCM5755 || (X) == PHY_ID_BCM8002)
struct tg3_hw_stats *hw_stats;
dma_addr_t stats_mapping;
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index ec3c3293262..989a9d00dec 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1864,11 +1864,13 @@
#define PCI_DEVICE_ID_TIGON3_5780S 0x166b
#define PCI_DEVICE_ID_TIGON3_5705F 0x166e
#define PCI_DEVICE_ID_TIGON3_5754M 0x1672
+#define PCI_DEVICE_ID_TIGON3_5755M 0x1673
#define PCI_DEVICE_ID_TIGON3_5750 0x1676
#define PCI_DEVICE_ID_TIGON3_5751 0x1677
#define PCI_DEVICE_ID_TIGON3_5715 0x1678
#define PCI_DEVICE_ID_TIGON3_5715S 0x1679
#define PCI_DEVICE_ID_TIGON3_5754 0x167a
+#define PCI_DEVICE_ID_TIGON3_5755 0x167b
#define PCI_DEVICE_ID_TIGON3_5750M 0x167c
#define PCI_DEVICE_ID_TIGON3_5751M 0x167d
#define PCI_DEVICE_ID_TIGON3_5751F 0x167e
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index d572d537631..df0cdd41085 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -839,6 +839,7 @@ enum
#define RTMGRP_IPV4_IFADDR 0x10
#define RTMGRP_IPV4_MROUTE 0x20
#define RTMGRP_IPV4_ROUTE 0x40
+#define RTMGRP_IPV4_RULE 0x80
#define RTMGRP_IPV6_IFADDR 0x100
#define RTMGRP_IPV6_MROUTE 0x200
@@ -869,7 +870,8 @@ enum rtnetlink_groups {
#define RTNLGRP_IPV4_MROUTE RTNLGRP_IPV4_MROUTE
RTNLGRP_IPV4_ROUTE,
#define RTNLGRP_IPV4_ROUTE RTNLGRP_IPV4_ROUTE
- RTNLGRP_NOP1,
+ RTNLGRP_IPV4_RULE,
+#define RTNLGRP_IPV4_RULE RTNLGRP_IPV4_RULE
RTNLGRP_IPV6_IFADDR,
#define RTNLGRP_IPV6_IFADDR RTNLGRP_IPV6_IFADDR
RTNLGRP_IPV6_MROUTE,
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 8eedaedba74..c23e9c06ee2 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -106,6 +106,9 @@
*
* interruptible_sleep_on_timeout() replaced Nishanth Aravamudan <nacc@us.ibm.com>
* 050103
+ *
+ * MPLS support by Steven Whitehouse <steve@chygwyn.com>
+ *
*/
#include <linux/sys.h>
#include <linux/types.h>
@@ -154,7 +157,7 @@
#include <asm/div64.h> /* do_div */
#include <asm/timex.h>
-#define VERSION "pktgen v2.66: Packet Generator for packet performance testing.\n"
+#define VERSION "pktgen v2.67: Packet Generator for packet performance testing.\n"
/* #define PG_DEBUG(a) a */
#define PG_DEBUG(a)
@@ -162,6 +165,8 @@
/* The buckets are exponential in 'width' */
#define LAT_BUCKETS_MAX 32
#define IP_NAME_SZ 32
+#define MAX_MPLS_LABELS 16 /* This is the max label stack depth */
+#define MPLS_STACK_BOTTOM __constant_htonl(0x00000100)
/* Device flag bits */
#define F_IPSRC_RND (1<<0) /* IP-Src Random */
@@ -172,6 +177,7 @@
#define F_MACDST_RND (1<<5) /* MAC-Dst Random */
#define F_TXSIZE_RND (1<<6) /* Transmit size is random */
#define F_IPV6 (1<<7) /* Interface in IPV6 Mode */
+#define F_MPLS_RND (1<<8) /* Random MPLS labels */
/* Thread control flag bits */
#define T_TERMINATE (1<<0)
@@ -278,6 +284,10 @@ struct pktgen_dev {
__u16 udp_dst_min; /* inclusive, dest UDP port */
__u16 udp_dst_max; /* exclusive, dest UDP port */
+ /* MPLS */
+ unsigned nr_labels; /* Depth of stack, 0 = no MPLS */
+ __be32 labels[MAX_MPLS_LABELS];
+
__u32 src_mac_count; /* How many MACs to iterate through */
__u32 dst_mac_count; /* How many MACs to iterate through */
@@ -623,9 +633,19 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
pkt_dev->udp_dst_min, pkt_dev->udp_dst_max);
seq_printf(seq,
- " src_mac_count: %d dst_mac_count: %d \n Flags: ",
+ " src_mac_count: %d dst_mac_count: %d\n",
pkt_dev->src_mac_count, pkt_dev->dst_mac_count);
+ if (pkt_dev->nr_labels) {
+ unsigned i;
+ seq_printf(seq, " mpls: ");
+ for(i = 0; i < pkt_dev->nr_labels; i++)
+ seq_printf(seq, "%08x%s", ntohl(pkt_dev->labels[i]),
+ i == pkt_dev->nr_labels-1 ? "\n" : ", ");
+ }
+
+ seq_printf(seq, " Flags: ");
+
if (pkt_dev->flags & F_IPV6)
seq_printf(seq, "IPV6 ");
@@ -644,6 +664,9 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
if (pkt_dev->flags & F_UDPDST_RND)
seq_printf(seq, "UDPDST_RND ");
+ if (pkt_dev->flags & F_MPLS_RND)
+ seq_printf(seq, "MPLS_RND ");
+
if (pkt_dev->flags & F_MACSRC_RND)
seq_printf(seq, "MACSRC_RND ");
@@ -691,6 +714,29 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
return 0;
}
+
+static int hex32_arg(const char __user *user_buffer, __u32 *num)
+{
+ int i = 0;
+ *num = 0;
+
+ for(; i < 8; i++) {
+ char c;
+ *num <<= 4;
+ if (get_user(c, &user_buffer[i]))
+ return -EFAULT;
+ if ((c >= '0') && (c <= '9'))
+ *num |= c - '0';
+ else if ((c >= 'a') && (c <= 'f'))
+ *num |= c - 'a' + 10;
+ else if ((c >= 'A') && (c <= 'F'))
+ *num |= c - 'A' + 10;
+ else
+ break;
+ }
+ return i;
+}
+
static int count_trail_chars(const char __user * user_buffer,
unsigned int maxlen)
{
@@ -759,6 +805,35 @@ done_str:
return i;
}
+static ssize_t get_labels(const char __user *buffer, struct pktgen_dev *pkt_dev)
+{
+ unsigned n = 0;
+ char c;
+ ssize_t i = 0;
+ int len;
+
+ pkt_dev->nr_labels = 0;
+ do {
+ __u32 tmp;
+ len = hex32_arg(&buffer[i], &tmp);
+ if (len <= 0)
+ return len;
+ pkt_dev->labels[n] = htonl(tmp);
+ if (pkt_dev->labels[n] & MPLS_STACK_BOTTOM)
+ pkt_dev->flags |= F_MPLS_RND;
+ i += len;
+ if (get_user(c, &buffer[i]))
+ return -EFAULT;
+ i++;
+ n++;
+ if (n >= MAX_MPLS_LABELS)
+ return -E2BIG;
+ } while(c == ',');
+
+ pkt_dev->nr_labels = n;
+ return i;
+}
+
static ssize_t pktgen_if_write(struct file *file,
const char __user * user_buffer, size_t count,
loff_t * offset)
@@ -1059,6 +1134,12 @@ static ssize_t pktgen_if_write(struct file *file,
else if (strcmp(f, "!MACDST_RND") == 0)
pkt_dev->flags &= ~F_MACDST_RND;
+ else if (strcmp(f, "MPLS_RND") == 0)
+ pkt_dev->flags |= F_MPLS_RND;
+
+ else if (strcmp(f, "!MPLS_RND") == 0)
+ pkt_dev->flags &= ~F_MPLS_RND;
+
else {
sprintf(pg_result,
"Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s",
@@ -1354,6 +1435,19 @@ static ssize_t pktgen_if_write(struct file *file,
return count;
}
+ if (!strcmp(name, "mpls")) {
+ unsigned n, offset;
+ len = get_labels(&user_buffer[i], pkt_dev);
+ if (len < 0) { return len; }
+ i += len;
+ offset = sprintf(pg_result, "OK: mpls=");
+ for(n = 0; n < pkt_dev->nr_labels; n++)
+ offset += sprintf(pg_result + offset,
+ "%08x%s", ntohl(pkt_dev->labels[n]),
+ n == pkt_dev->nr_labels-1 ? "" : ",");
+ return count;
+ }
+
sprintf(pkt_dev->result, "No such parameter \"%s\"", name);
return -EINVAL;
}
@@ -1846,6 +1940,15 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
pkt_dev->hh[1] = tmp;
}
+ if (pkt_dev->flags & F_MPLS_RND) {
+ unsigned i;
+ for(i = 0; i < pkt_dev->nr_labels; i++)
+ if (pkt_dev->labels[i] & MPLS_STACK_BOTTOM)
+ pkt_dev->labels[i] = MPLS_STACK_BOTTOM |
+ (pktgen_random() &
+ htonl(0x000fffff));
+ }
+
if (pkt_dev->udp_src_min < pkt_dev->udp_src_max) {
if (pkt_dev->flags & F_UDPSRC_RND)
pkt_dev->cur_udp_src =
@@ -1968,6 +2071,16 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
pkt_dev->flows[flow].count++;
}
+static void mpls_push(__be32 *mpls, struct pktgen_dev *pkt_dev)
+{
+ unsigned i;
+ for(i = 0; i < pkt_dev->nr_labels; i++) {
+ *mpls++ = pkt_dev->labels[i] & ~MPLS_STACK_BOTTOM;
+ }
+ mpls--;
+ *mpls |= MPLS_STACK_BOTTOM;
+}
+
static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
struct pktgen_dev *pkt_dev)
{
@@ -1977,6 +2090,11 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
int datalen, iplen;
struct iphdr *iph;
struct pktgen_hdr *pgh = NULL;
+ __be16 protocol = __constant_htons(ETH_P_IP);
+ __be32 *mpls;
+
+ if (pkt_dev->nr_labels)
+ protocol = __constant_htons(ETH_P_MPLS_UC);
/* Update any of the values, used when we're incrementing various
* fields.
@@ -1984,7 +2102,8 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
mod_cur_headers(pkt_dev);
datalen = (odev->hard_header_len + 16) & ~0xf;
- skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + datalen, GFP_ATOMIC);
+ skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + datalen +
+ pkt_dev->nr_labels*sizeof(u32), GFP_ATOMIC);
if (!skb) {
sprintf(pkt_dev->result, "No memory");
return NULL;
@@ -1994,13 +2113,18 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
/* Reserve for ethernet and IP header */
eth = (__u8 *) skb_push(skb, 14);
+ mpls = (__be32 *)skb_put(skb, pkt_dev->nr_labels*sizeof(__u32));
+ if (pkt_dev->nr_labels)
+ mpls_push(mpls, pkt_dev);
iph = (struct iphdr *)skb_put(skb, sizeof(struct iphdr));
udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr));
memcpy(eth, pkt_dev->hh, 12);
- *(u16 *) & eth[12] = __constant_htons(ETH_P_IP);
+ *(u16 *) & eth[12] = protocol;
- datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8; /* Eth + IPh + UDPh */
+ /* Eth + IPh + UDPh + mpls */
+ datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8 -
+ pkt_dev->nr_labels*sizeof(u32);
if (datalen < sizeof(struct pktgen_hdr))
datalen = sizeof(struct pktgen_hdr);
@@ -2021,8 +2145,8 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
iph->tot_len = htons(iplen);
iph->check = 0;
iph->check = ip_fast_csum((void *)iph, iph->ihl);
- skb->protocol = __constant_htons(ETH_P_IP);
- skb->mac.raw = ((u8 *) iph) - 14;
+ skb->protocol = protocol;
+ skb->mac.raw = ((u8 *) iph) - 14 - pkt_dev->nr_labels*sizeof(u32);
skb->dev = odev;
skb->pkt_type = PACKET_HOST;
@@ -2274,13 +2398,19 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
int datalen;
struct ipv6hdr *iph;
struct pktgen_hdr *pgh = NULL;
+ __be16 protocol = __constant_htons(ETH_P_IPV6);
+ __be32 *mpls;
+
+ if (pkt_dev->nr_labels)
+ protocol = __constant_htons(ETH_P_MPLS_UC);
/* Update any of the values, used when we're incrementing various
* fields.
*/
mod_cur_headers(pkt_dev);
- skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + 16, GFP_ATOMIC);
+ skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + 16 +
+ pkt_dev->nr_labels*sizeof(u32), GFP_ATOMIC);
if (!skb) {
sprintf(pkt_dev->result, "No memory");
return NULL;
@@ -2290,13 +2420,19 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
/* Reserve for ethernet and IP header */
eth = (__u8 *) skb_push(skb, 14);
+ mpls = (__be32 *)skb_put(skb, pkt_dev->nr_labels*sizeof(__u32));
+ if (pkt_dev->nr_labels)
+ mpls_push(mpls, pkt_dev);
iph = (struct ipv6hdr *)skb_put(skb, sizeof(struct ipv6hdr));
udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr));
memcpy(eth, pkt_dev->hh, 12);
*(u16 *) & eth[12] = __constant_htons(ETH_P_IPV6);
- datalen = pkt_dev->cur_pkt_size - 14 - sizeof(struct ipv6hdr) - sizeof(struct udphdr); /* Eth + IPh + UDPh */
+ /* Eth + IPh + UDPh + mpls */
+ datalen = pkt_dev->cur_pkt_size - 14 -
+ sizeof(struct ipv6hdr) - sizeof(struct udphdr) -
+ pkt_dev->nr_labels*sizeof(u32);
if (datalen < sizeof(struct pktgen_hdr)) {
datalen = sizeof(struct pktgen_hdr);
@@ -2320,8 +2456,8 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
ipv6_addr_copy(&iph->daddr, &pkt_dev->cur_in6_daddr);
ipv6_addr_copy(&iph->saddr, &pkt_dev->cur_in6_saddr);
- skb->mac.raw = ((u8 *) iph) - 14;
- skb->protocol = __constant_htons(ETH_P_IPV6);
+ skb->mac.raw = ((u8 *) iph) - 14 - pkt_dev->nr_labels*sizeof(u32);
+ skb->protocol = protocol;
skb->dev = odev;
skb->pkt_type = PACKET_HOST;
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 768e8f5d7da..ec566f3e66c 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -104,6 +104,8 @@ static struct hlist_head fib_rules;
/* writer func called from netlink -- rtnl_sem hold*/
+static void rtmsg_rule(int, struct fib_rule *);
+
int inet_rtm_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
{
struct rtattr **rta = arg;
@@ -131,6 +133,7 @@ int inet_rtm_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
hlist_del_rcu(&r->hlist);
r->r_dead = 1;
+ rtmsg_rule(RTM_DELRULE, r);
fib_rule_put(r);
err = 0;
break;
@@ -253,6 +256,7 @@ int inet_rtm_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
else
hlist_add_before_rcu(&new_r->hlist, &r->hlist);
+ rtmsg_rule(RTM_NEWRULE, new_r);
return 0;
}
@@ -382,14 +386,14 @@ static struct notifier_block fib_rules_notifier = {
static __inline__ int inet_fill_rule(struct sk_buff *skb,
struct fib_rule *r,
- struct netlink_callback *cb,
+ u32 pid, u32 seq, int event,
unsigned int flags)
{
struct rtmsg *rtm;
struct nlmsghdr *nlh;
unsigned char *b = skb->tail;
- nlh = NLMSG_NEW_ANSWER(skb, cb, RTM_NEWRULE, sizeof(*rtm), flags);
+ nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*rtm), flags);
rtm = NLMSG_DATA(nlh);
rtm->rtm_family = AF_INET;
rtm->rtm_dst_len = r->r_dst_len;
@@ -430,6 +434,21 @@ rtattr_failure:
/* callers should hold rtnl semaphore */
+static void rtmsg_rule(int event, struct fib_rule *r)
+{
+ int size = NLMSG_SPACE(sizeof(struct rtmsg) + 128);
+ struct sk_buff *skb = alloc_skb(size, GFP_KERNEL);
+
+ if (!skb)
+ netlink_set_err(rtnl, 0, RTNLGRP_IPV4_RULE, ENOBUFS);
+ else if (inet_fill_rule(skb, r, 0, 0, event, 0) < 0) {
+ kfree_skb(skb);
+ netlink_set_err(rtnl, 0, RTNLGRP_IPV4_RULE, EINVAL);
+ } else {
+ netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV4_RULE, GFP_KERNEL);
+ }
+}
+
int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb)
{
int idx = 0;
@@ -442,7 +461,9 @@ int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb)
if (idx < s_idx)
continue;
- if (inet_fill_rule(skb, r, cb, NLM_F_MULTI) < 0)
+ if (inet_fill_rule(skb, r, NETLINK_CB(cb->skb).pid,
+ cb->nlh->nlmsg_seq,
+ RTM_NEWRULE, NLM_F_MULTI) < 0)
break;
idx++;
}
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 4fbc40b13f1..e46048974f3 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -161,7 +161,7 @@ int ip6_output(struct sk_buff *skb)
int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
struct ipv6_txoptions *opt, int ipfragok)
{
- struct ipv6_pinfo *np = sk ? inet6_sk(sk) : NULL;
+ struct ipv6_pinfo *np = inet6_sk(sk);
struct in6_addr *first_hop = &fl->fl6_dst;
struct dst_entry *dst = skb->dst;
struct ipv6hdr *hdr;
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 2b670479dde..78e052591fa 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -347,8 +347,7 @@ static int u32_destroy_key(struct tcf_proto *tp, struct tc_u_knode *n)
if (n->ht_down)
n->ht_down->refcnt--;
#ifdef CONFIG_CLS_U32_PERF
- if (n)
- kfree(n->pf);
+ kfree(n->pf);
#endif
kfree(n);
return 0;
@@ -680,8 +679,7 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
return 0;
}
#ifdef CONFIG_CLS_U32_PERF
- if (n)
- kfree(n->pf);
+ kfree(n->pf);
#endif
kfree(n);
return err;