kernel: remove imq support, refresh patches
authorFelix Fietkau <nbd@openwrt.org>
Mon, 21 Feb 2011 02:06:51 +0000 (02:06 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Mon, 21 Feb 2011 02:06:51 +0000 (02:06 +0000)
SVN-Revision: 25641

156 files changed:
include/netfilter.mk
package/kernel/modules/netfilter.mk
target/linux/ar71xx/Makefile
target/linux/ar71xx/patches-2.6.36/003-ar71xx_usb_host.patch
target/linux/ar71xx/patches-2.6.36/005-ar71xx_mac_driver.patch
target/linux/ar71xx/patches-2.6.36/102-mtd_m25p80_add_myloader_parser.patch
target/linux/ar71xx/patches-2.6.36/104-mtd_m25p80_add_redboot_parser.patch
target/linux/ar71xx/patches-2.6.36/107-mtd-SST39VF6401B-support.patch
target/linux/ar71xx/patches-2.6.36/108-mtd_fix_cfi_cmdset_0002_status_check.patch
target/linux/ar71xx/patches-2.6.36/109-mtd-wrt160nl-trx-parser.patch
target/linux/ar71xx/patches-2.6.36/110-usb-ehci-add-war-for-synopsys-hc-bug.patch
target/linux/ar71xx/patches-2.6.36/111-mtd-cfi_cmdset_0002-force-word-write.patch
target/linux/ar71xx/patches-2.6.36/400-2.6.35-fix-nand_scan_ident-options.patch
target/linux/ar71xx/patches-2.6.37/001-ar71xx_core.patch
target/linux/ar71xx/patches-2.6.37/003-ar71xx_usb_host.patch
target/linux/ar71xx/patches-2.6.37/005-ar71xx_mac_driver.patch
target/linux/ar71xx/patches-2.6.37/006-ar71xx_wdt_driver.patch
target/linux/ar71xx/patches-2.6.37/102-mtd_m25p80_add_myloader_parser.patch
target/linux/ar71xx/patches-2.6.37/104-mtd_m25p80_add_redboot_parser.patch
target/linux/ar71xx/patches-2.6.37/107-mtd-SST39VF6401B-support.patch
target/linux/ar71xx/patches-2.6.37/108-mtd_fix_cfi_cmdset_0002_status_check.patch
target/linux/ar71xx/patches-2.6.37/109-mtd-wrt160nl-trx-parser.patch
target/linux/ar71xx/patches-2.6.37/110-usb-ehci-add-war-for-synopsys-hc-bug.patch
target/linux/ar71xx/patches-2.6.37/111-mtd-cfi_cmdset_0002-force-word-write.patch
target/linux/ar71xx/patches-2.6.37/205-wndr3700-usb-led-driver.patch
target/linux/ar71xx/patches-2.6.37/207-rb750-led-driver.patch
target/linux/ar71xx/patches-2.6.37/300-mips_fw_myloader.patch
target/linux/ar71xx/patches-2.6.37/400-2.6.35-fix-nand_scan_ident-options.patch
target/linux/ar71xx/patches-2.6.37/901-get_c0_compare_irq_function.patch
target/linux/generic/config-2.6.30
target/linux/generic/config-2.6.31
target/linux/generic/config-2.6.32
target/linux/generic/config-2.6.34
target/linux/generic/config-2.6.35
target/linux/generic/config-2.6.36
target/linux/generic/config-2.6.37
target/linux/generic/config-2.6.38
target/linux/generic/patches-2.6.30/150-netfilter_imq.patch [deleted file]
target/linux/generic/patches-2.6.30/180-netfilter_depends.patch
target/linux/generic/patches-2.6.30/205-skb_padding.patch
target/linux/generic/patches-2.6.30/601-phy-add-aneg-done-function.patch
target/linux/generic/patches-2.6.30/680-phy_ar8216.patch
target/linux/generic/patches-2.6.30/690-phy_rtl8306.patch
target/linux/generic/patches-2.6.30/691-phy_rtl8366.patch
target/linux/generic/patches-2.6.30/940-wireless_mesh_header.patch
target/linux/generic/patches-2.6.30/971-ocf_20100325.patch
target/linux/generic/patches-2.6.31/150-netfilter_imq.patch [deleted file]
target/linux/generic/patches-2.6.32/014-cfi_fix_amd_extended_table_check.patch
target/linux/generic/patches-2.6.32/020-mips_multi_machine_support.patch
target/linux/generic/patches-2.6.32/040-arm-update-mach-types.patch
target/linux/generic/patches-2.6.32/100-netfilter_layer7_2.21.patch
target/linux/generic/patches-2.6.32/110-netfilter_match_speedup.patch
target/linux/generic/patches-2.6.32/150-netfilter_imq.patch [deleted file]
target/linux/generic/patches-2.6.32/180-netfilter_depends.patch
target/linux/generic/patches-2.6.32/202-mips_mem_functions_performance.patch
target/linux/generic/patches-2.6.32/203-slab_maxsize.patch
target/linux/generic/patches-2.6.32/205-skb_padding.patch
target/linux/generic/patches-2.6.32/210-mini_fo_2.6.25_fixes.patch
target/linux/generic/patches-2.6.32/212-mini_fo_2.6.26_fixes.patch
target/linux/generic/patches-2.6.32/223-kobject-add-broadcast_uevent.patch
target/linux/generic/patches-2.6.32/400-ledtrig_morse.patch
target/linux/generic/patches-2.6.32/402-ledtrig_netdev.patch
target/linux/generic/patches-2.6.32/511-yaffs-cvs-2009-04-24.patch
target/linux/generic/patches-2.6.32/903-hostap_txpower.patch
target/linux/generic/patches-2.6.32/930-kmsg_dump_backport.patch
target/linux/generic/patches-2.6.32/971-ocf_20100325.patch
target/linux/generic/patches-2.6.32/975-ssb_update.patch
target/linux/generic/patches-2.6.32/998-openwrt_lzma_options.patch
target/linux/generic/patches-2.6.34/014-cfi_fix_amd_extended_table_check.patch
target/linux/generic/patches-2.6.34/020-mips_multi_machine_support.patch
target/linux/generic/patches-2.6.34/100-netfilter_layer7_2.21.patch
target/linux/generic/patches-2.6.34/110-netfilter_match_speedup.patch
target/linux/generic/patches-2.6.34/150-netfilter_imq.patch [deleted file]
target/linux/generic/patches-2.6.34/180-netfilter_depends.patch
target/linux/generic/patches-2.6.34/202-mips_mem_functions_performance.patch
target/linux/generic/patches-2.6.34/203-slab_maxsize.patch
target/linux/generic/patches-2.6.34/205-skb_padding.patch
target/linux/generic/patches-2.6.34/210-mini_fo_2.6.25_fixes.patch
target/linux/generic/patches-2.6.34/212-mini_fo_2.6.26_fixes.patch
target/linux/generic/patches-2.6.34/223-kobject-add-broadcast_uevent.patch
target/linux/generic/patches-2.6.34/280-sched_act_connmark.patch
target/linux/generic/patches-2.6.34/400-ledtrig_morse.patch
target/linux/generic/patches-2.6.34/402-ledtrig_netdev.patch
target/linux/generic/patches-2.6.34/511-yaffs-cvs-2009-04-24.patch
target/linux/generic/patches-2.6.34/903-hostap_txpower.patch
target/linux/generic/patches-2.6.34/971-ocf_20100325.patch
target/linux/generic/patches-2.6.34/975-ssb_update.patch
target/linux/generic/patches-2.6.34/998-openwrt_lzma_options.patch
target/linux/generic/patches-2.6.35/014-cfi_fix_amd_extended_table_check.patch
target/linux/generic/patches-2.6.35/020-mips_multi_machine_support.patch
target/linux/generic/patches-2.6.35/040-arm-update-mach-types.patch
target/linux/generic/patches-2.6.35/065-rootfs_split.patch
target/linux/generic/patches-2.6.35/100-netfilter_layer7_2.21.patch
target/linux/generic/patches-2.6.35/110-netfilter_match_speedup.patch
target/linux/generic/patches-2.6.35/150-netfilter_imq.patch [deleted file]
target/linux/generic/patches-2.6.35/180-netfilter_depends.patch
target/linux/generic/patches-2.6.35/202-mips_mem_functions_performance.patch
target/linux/generic/patches-2.6.35/203-slab_maxsize.patch
target/linux/generic/patches-2.6.35/210-mini_fo_2.6.25_fixes.patch
target/linux/generic/patches-2.6.35/212-mini_fo_2.6.26_fixes.patch
target/linux/generic/patches-2.6.35/223-kobject-add-broadcast_uevent.patch
target/linux/generic/patches-2.6.35/290-sched_act_connmark.patch
target/linux/generic/patches-2.6.35/400-ledtrig_morse.patch
target/linux/generic/patches-2.6.35/402-ledtrig_netdev.patch
target/linux/generic/patches-2.6.35/511-yaffs-cvs-2009-04-24.patch
target/linux/generic/patches-2.6.35/903-hostap_txpower.patch
target/linux/generic/patches-2.6.35/971-ocf_20100325.patch
target/linux/generic/patches-2.6.35/975-ssb_update.patch
target/linux/generic/patches-2.6.35/998-openwrt_lzma_options.patch
target/linux/generic/patches-2.6.36/014-cfi_show_amd_extended_table_version.patch
target/linux/generic/patches-2.6.36/020-mips_multi_machine_support.patch
target/linux/generic/patches-2.6.36/040-arm-update-mach-types.patch
target/linux/generic/patches-2.6.36/065-rootfs_split.patch
target/linux/generic/patches-2.6.36/089-mtd-samsung-flash.patch
target/linux/generic/patches-2.6.36/100-netfilter_layer7_2.22.patch
target/linux/generic/patches-2.6.36/110-netfilter_match_speedup.patch
target/linux/generic/patches-2.6.36/150-netfilter_imq.patch [deleted file]
target/linux/generic/patches-2.6.36/180-netfilter_depends.patch
target/linux/generic/patches-2.6.36/202-mips_mem_functions_performance.patch
target/linux/generic/patches-2.6.36/203-slab_maxsize.patch
target/linux/generic/patches-2.6.36/210-mini_fo_2.6.25_fixes.patch
target/linux/generic/patches-2.6.36/212-mini_fo_2.6.26_fixes.patch
target/linux/generic/patches-2.6.36/223-kobject-add-broadcast_uevent.patch
target/linux/generic/patches-2.6.36/290-sched_act_connmark.patch
target/linux/generic/patches-2.6.36/400-ledtrig_morse.patch
target/linux/generic/patches-2.6.36/402-ledtrig_netdev.patch
target/linux/generic/patches-2.6.36/411-gpio_ioctl.patch
target/linux/generic/patches-2.6.36/511-yaffs-cvs-2009-04-24.patch
target/linux/generic/patches-2.6.36/511-yaffs-git-2010-10-20.patch
target/linux/generic/patches-2.6.36/903-hostap_txpower.patch
target/linux/generic/patches-2.6.36/971-ocf_20100325.patch
target/linux/generic/patches-2.6.36/990-arm_export_dma_set_coherent_mask.patch
target/linux/generic/patches-2.6.36/998-openwrt_lzma_options.patch
target/linux/generic/patches-2.6.37/014-cfi_show_amd_extended_table_version.patch
target/linux/generic/patches-2.6.37/020-mips_multi_machine_support.patch
target/linux/generic/patches-2.6.37/040-arm-update-mach-types.patch
target/linux/generic/patches-2.6.37/065-rootfs_split.patch
target/linux/generic/patches-2.6.37/089-mtd-samsung-flash.patch
target/linux/generic/patches-2.6.37/100-netfilter_layer7_2.22.patch
target/linux/generic/patches-2.6.37/150-netfilter_imq.patch [deleted file]
target/linux/generic/patches-2.6.37/180-netfilter_depends.patch
target/linux/generic/patches-2.6.37/202-mips_mem_functions_performance.patch
target/linux/generic/patches-2.6.37/203-slab_maxsize.patch
target/linux/generic/patches-2.6.37/210-mini_fo_2.6.25_fixes.patch
target/linux/generic/patches-2.6.37/212-mini_fo_2.6.26_fixes.patch
target/linux/generic/patches-2.6.37/223-kobject-add-broadcast_uevent.patch
target/linux/generic/patches-2.6.37/290-sched_act_connmark.patch
target/linux/generic/patches-2.6.37/400-ledtrig_morse.patch
target/linux/generic/patches-2.6.37/402-ledtrig_netdev.patch
target/linux/generic/patches-2.6.37/411-gpio_ioctl.patch
target/linux/generic/patches-2.6.37/511-yaffs-cvs-2009-04-24.patch
target/linux/generic/patches-2.6.37/511-yaffs-git-2010-10-20.patch
target/linux/generic/patches-2.6.37/903-hostap_txpower.patch
target/linux/generic/patches-2.6.37/971-ocf_20100325.patch
target/linux/generic/patches-2.6.37/998-openwrt_lzma_options.patch
target/linux/generic/patches-2.6.38/150-netfilter_imq.patch [deleted file]

index 3f892bb2ec2e4034881019b4f41885aa0f825c30..424cf551a4befa0d2561a6d384d7999ce199359b 100644 (file)
@@ -107,12 +107,6 @@ $(eval $(call nf_add,IPT_FILTER,CONFIG_IP_NF_MATCH_STRING, $(P_V4)ipt_string))
 $(eval $(call nf_add,IPT_FILTER,CONFIG_NETFILTER_XT_MATCH_STRING, $(P_XT)xt_string))
 
 
-# imq
-
-$(eval $(call nf_add,IPT_IMQ,CONFIG_IP_NF_TARGET_IMQ, $(P_V4)ipt_IMQ))
-$(eval $(call nf_add,IPT_IMQ,CONFIG_NETFILTER_XT_TARGET_IMQ, $(P_XT)xt_IMQ))
-
-
 # ipopt
 
 $(eval $(call nf_add,IPT_IPOPT,CONFIG_IP_NF_TARGET_DSCP, $(P_V4)ipt_DSCP))
@@ -200,7 +194,6 @@ $(eval $(call nf_add,IPT_IPV6,CONFIG_IP6_NF_MATCH_OWNER, $(P_V6)ip6t_owner))
 $(eval $(call nf_add,IPT_IPV6,CONFIG_IP6_NF_MATCH_OPTS, $(P_V6)ip6t_hbh))
 $(eval $(call nf_add,IPT_IPV6,CONFIG_IP6_NF_MATCH_RT, $(P_V6)ip6t_rt))
 
-$(eval $(call nf_add,IPT_IPV6,CONFIG_IP6_NF_TARGET_IMQ, $(P_V6)ip6t_IMQ))
 $(eval $(call nf_add,IPT_IPV6,CONFIG_IP6_NF_TARGET_LOG, $(P_V6)ip6t_LOG))
 $(eval $(call nf_add,IPT_IPV6,CONFIG_IP6_NF_TARGET_REJECT, $(P_V6)ip6t_REJECT))
 $(eval $(call nf_add,IPT_IPV6,CONFIG_IP6_NF_TARGET_ROUTE, $(P_V6)ip6t_ROUTE))
@@ -331,7 +324,6 @@ IPT_BUILTIN += $(IPT_CONNTRACK-y)
 IPT_BUILTIN += $(IPT_CONNTRACK_EXTRA-y)
 IPT_BUILTIN += $(IPT_EXTRA-y)
 IPT_BUILTIN += $(IPT_FILTER-y)
-IPT_BUILTIN += $(IPT_IMQ-y)
 IPT_BUILTIN += $(IPT_IPOPT-y)
 IPT_BUILTIN += $(IPT_IPRANGE-y)
 IPT_BUILTIN += $(IPT_IPSEC-y)
index e2361af6ae7bd27a6bb41602a2de7a3197f14800..2393d70a682edee49cb310f2d4f04a0414f06466 100644 (file)
@@ -228,30 +228,6 @@ endef
 $(eval $(call KernelPackage,ipt-nathelper-extra))
 
 
-define KernelPackage/ipt-imq
-  TITLE:=Intermediate Queueing support
-  KCONFIG:= \
-       CONFIG_IMQ \
-       CONFIG_IMQ_BEHAVIOR_BA=y \
-       CONFIG_IMQ_NUM_DEVS=2 \
-       CONFIG_NETFILTER_XT_TARGET_IMQ
-  FILES:= \
-       $(LINUX_DIR)/drivers/net/imq.ko \
-       $(foreach mod,$(IPT_IMQ-m),$(LINUX_DIR)/net/$(mod).ko)
-  AUTOLOAD:=$(call AutoLoad,46,$(notdir \
-       imq \
-       $(IPT_IMQ-m) \
-  ))
-  $(call AddDepends/ipt)
-endef
-
-define KernelPackage/ipt-imq/description
- Kernel support for Intermediate Queueing devices
-endef
-
-$(eval $(call KernelPackage,ipt-imq))
-
-
 define KernelPackage/ipt-queue
   TITLE:=Module for user-space packet queueing
   KCONFIG:=$(KCONFIG_IPT_QUEUE)
index b05ad6de3015aa149f6907136c19ce0d4cdcc0cc..b0b096a2fe449dda8fb0543dbb97a6e4625fe3b1 100644 (file)
@@ -13,7 +13,7 @@ FEATURES:=squashfs jffs2 targz
 CFLAGS:=-Os -pipe -mips32r2 -mtune=mips32r2 -funit-at-a-time
 SUBTARGETS:=generic nand
 
-LINUX_VERSION:=2.6.32.29
+LINUX_VERSION:=2.6.37.1
 
 include $(INCLUDE_DIR)/target.mk
 
index 9fea1b4b6c61f9cb4f55f42f5e0cfa75ec9ba3ac..a75ed524ba58cf19911dbafc366477bc87036e8d 100644 (file)
@@ -30,7 +30,7 @@
        depends on USB_OHCI_HCD && (STB03xxx || PPC_MPC52xx)
 --- a/drivers/usb/host/ehci-hcd.c
 +++ b/drivers/usb/host/ehci-hcd.c
-@@ -1197,6 +1197,11 @@ MODULE_LICENSE ("GPL");
+@@ -1210,6 +1210,11 @@ MODULE_LICENSE ("GPL");
  #define       PLATFORM_DRIVER         ehci_atmel_driver
  #endif
  
index 1f27e84dcd7baf17427d5373129b4de8b68ddf2d..01b7a2e14304586f739035f542f270c56badc2ff 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/Kconfig
 +++ b/drivers/net/Kconfig
-@@ -2168,6 +2168,8 @@ config ACENIC_OMIT_TIGON_I
+@@ -2045,6 +2045,8 @@ config ACENIC_OMIT_TIGON_I
  
          The safe and default value for this is N.
  
index dcf7a6deff04a1bca038fbb96dc73922fff08413..fb4eed4b871ab60e519b08094cc7bd318c36959a 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/mtd/devices/m25p80.c
 +++ b/drivers/mtd/devices/m25p80.c
-@@ -933,6 +933,16 @@ static int __devinit m25p_probe(struct s
+@@ -929,6 +929,16 @@ static int __devinit m25p_probe(struct s
                                        part_probes, &parts, 0);
                }
  
index bb0ff7d3f8b8703812f33a026ec45658a534d8b8..643b2df24d69f134062587f7801041c868c165f1 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/mtd/devices/m25p80.c
 +++ b/drivers/mtd/devices/m25p80.c
-@@ -943,6 +943,15 @@ static int __devinit m25p_probe(struct s
+@@ -939,6 +939,15 @@ static int __devinit m25p_probe(struct s
                }
  #endif
  
index 246abd5dc0832fbd61322d08cb7f3b56041a72b9..0c3814c1fcbdcb195ccc00746ff22896e9c1cd30 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/mtd/chips/jedec_probe.c
 +++ b/drivers/mtd/chips/jedec_probe.c
-@@ -148,6 +148,7 @@
+@@ -149,6 +149,7 @@
  #define SST39LF160    0x2782
  #define SST39VF1601   0x234b
  #define SST39VF3201   0x235b
@@ -8,7 +8,7 @@
  #define SST39WF1601   0x274b
  #define SST39WF1602   0x274a
  #define SST39LF512    0x00D4
-@@ -1568,6 +1569,18 @@ static const struct amd_flash_info jedec
+@@ -1582,6 +1583,18 @@ static const struct amd_flash_info jedec
                        ERASEINFO(0x10000,64),
                }
        }, {
index 64e52b31c11389a503a4768ba7443a6c76c8f24a..e753285ab9b39a51a84d7948e405b60b1603ad1a 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/mtd/chips/cfi_cmdset_0002.c
 +++ b/drivers/mtd/chips/cfi_cmdset_0002.c
-@@ -1218,8 +1218,8 @@ static int __xipram do_write_oneword(str
+@@ -1215,8 +1215,8 @@ static int __xipram do_write_oneword(str
                        break;
                }
  
@@ -11,7 +11,7 @@
  
                /* Latency issues. Drop the lock, wait a while and retry */
                UDELAY(map, chip, adr, 1);
-@@ -1235,6 +1235,8 @@ static int __xipram do_write_oneword(str
+@@ -1232,6 +1232,8 @@ static int __xipram do_write_oneword(str
  
                ret = -EIO;
        }
@@ -20,7 +20,7 @@
        xip_enable(map, chip, adr);
   op_done:
        chip->state = FL_READY;
-@@ -1581,7 +1583,6 @@ static int cfi_amdstd_write_buffers(stru
+@@ -1578,7 +1580,6 @@ static int cfi_amdstd_write_buffers(stru
        return 0;
  }
  
@@ -28,7 +28,7 @@
  /*
   * Handle devices with one erase region, that only implement
   * the chip erase command.
-@@ -1645,8 +1646,8 @@ static int __xipram do_erase_chip(struct
+@@ -1642,8 +1643,8 @@ static int __xipram do_erase_chip(struct
                        chip->erase_suspended = 0;
                }
  
@@ -39,7 +39,7 @@
  
                if (time_after(jiffies, timeo)) {
                        printk(KERN_WARNING "MTD %s(): software timeout\n",
-@@ -1666,6 +1667,7 @@ static int __xipram do_erase_chip(struct
+@@ -1663,6 +1664,7 @@ static int __xipram do_erase_chip(struct
                ret = -EIO;
        }
  
@@ -47,7 +47,7 @@
        chip->state = FL_READY;
        xip_enable(map, chip, adr);
        put_chip(map, chip, adr);
-@@ -1733,9 +1735,9 @@ static int __xipram do_erase_oneblock(st
+@@ -1730,9 +1732,9 @@ static int __xipram do_erase_oneblock(st
                        chip->erase_suspended = 0;
                }
  
@@ -59,7 +59,7 @@
                }
  
                if (time_after(jiffies, timeo)) {
-@@ -1757,6 +1759,7 @@ static int __xipram do_erase_oneblock(st
+@@ -1754,6 +1756,7 @@ static int __xipram do_erase_oneblock(st
                ret = -EIO;
        }
  
index c8012f57d6a4f44da445f736c76ed561b5cab0b4..62b414ee53c8baef58e5f58e9c30e969ec69fae7 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/mtd/devices/m25p80.c
 +++ b/drivers/mtd/devices/m25p80.c
-@@ -952,6 +952,16 @@ static int __devinit m25p_probe(struct s
+@@ -948,6 +948,16 @@ static int __devinit m25p_probe(struct s
                                        part_probes, &parts, 0);
                }
  #endif
index 047239d5ccc5fe1060f35cb4f2c63a6da456dc88..5d2c02ec7cac198ae78dc04d567ca94c0f2d6b8e 100644 (file)
@@ -12,9 +12,9 @@
  /* makes sure the async qh will become idle */
 --- a/drivers/usb/host/ehci.h
 +++ b/drivers/usb/host/ehci.h
-@@ -131,6 +131,7 @@ struct ehci_hcd {                  /* one per controlle
-       unsigned                need_io_watchdog:1;
+@@ -132,6 +132,7 @@ struct ehci_hcd {                  /* one per controlle
        unsigned                broken_periodic:1;
+       unsigned                amd_l1_fix:1;
        unsigned                fs_i_thresh:1;  /* Intel iso scheduling */
 +      unsigned                has_synopsys_hc_bug:1; /* Synopsys HC */
  
index 969cd1aaeefbab082b7edffe154d1d031d8b5e52..8333d0db5fbf7c29b7ba174dc30269e3d6265073 100644 (file)
@@ -35,7 +35,7 @@
  
  /* Atmel chips don't use the same PRI format as AMD chips */
  static void fixup_convert_atmel_pri(struct mtd_info *mtd, void *param)
-@@ -1392,6 +1396,7 @@ static int cfi_amdstd_write_words(struct
+@@ -1389,6 +1393,7 @@ static int cfi_amdstd_write_words(struct
  /*
   * FIXME: interleaved mode not tested, and probably not supported!
   */
@@ -43,7 +43,7 @@
  static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
                                    unsigned long adr, const u_char *buf,
                                    int len)
-@@ -1503,7 +1508,6 @@ static int __xipram do_write_buffer(stru
+@@ -1500,7 +1505,6 @@ static int __xipram do_write_buffer(stru
        return ret;
  }
  
@@ -51,7 +51,7 @@
  static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len,
                                    size_t *retlen, const u_char *buf)
  {
-@@ -1582,6 +1586,7 @@ static int cfi_amdstd_write_buffers(stru
+@@ -1579,6 +1583,7 @@ static int cfi_amdstd_write_buffers(stru
  
        return 0;
  }
index 696094fdd854b4611ffe3033fb64baf7bda7766e..0b36217b6e0a1b526c6dc6adfab78483780adca8 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/mtd/nand/rb4xx_nand.c
 +++ b/drivers/mtd/nand/rb4xx_nand.c
-@@ -220,7 +220,7 @@ static int __init rb4xx_nand_probe(struc
+@@ -223,7 +223,7 @@ static int __init rb4xx_nand_probe(struc
  
        platform_set_drvdata(pdev, info);
  
index 4c0d395eb18f74f0bf098e1a70f695caba72ce5d..0adb2189aa0abbbec315f557f25cf6c4a8b9b8b0 100644 (file)
@@ -16,7 +16,7 @@
  cflags-$(CONFIG_CPU_DADDI_WORKAROUNDS)        += $(call cc-option,-mno-daddi,)
 --- a/arch/mips/Kconfig
 +++ b/arch/mips/Kconfig
-@@ -63,6 +63,23 @@ config AR7
+@@ -65,6 +65,23 @@ config AR7
          Support for the Texas Instruments AR7 System-on-a-Chip
          family: TNETD7100, 7200 and 7300.
  
@@ -40,7 +40,7 @@
  config BCM47XX
        bool "Broadcom BCM47XX based boards"
        select CEVT_R4K
-@@ -715,6 +732,7 @@ config CAVIUM_OCTEON_REFERENCE_BOARD
+@@ -717,6 +734,7 @@ config CAVIUM_OCTEON_REFERENCE_BOARD
  endchoice
  
  source "arch/mips/alchemy/Kconfig"
index 0551442b99b72f6b25f8ff9db19ede19fd9180dc..be2e5451d06e754328efe243c3f02ad2f292a4c2 100644 (file)
@@ -30,7 +30,7 @@
        depends on USB_OHCI_HCD && (STB03xxx || PPC_MPC52xx)
 --- a/drivers/usb/host/ehci-hcd.c
 +++ b/drivers/usb/host/ehci-hcd.c
-@@ -1216,6 +1216,11 @@ MODULE_LICENSE ("GPL");
+@@ -1229,6 +1229,11 @@ MODULE_LICENSE ("GPL");
  #define PLATFORM_DRIVER               ehci_octeon_driver
  #endif
  
index 5664463771e2c09d732659ec73bcd8377f1a5637..909f2ed9cd94277f18fabaafd701711202e84ac2 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/Kconfig
 +++ b/drivers/net/Kconfig
-@@ -2191,6 +2191,8 @@ config ACENIC_OMIT_TIGON_I
+@@ -2068,6 +2068,8 @@ config ACENIC_OMIT_TIGON_I
  
          The safe and default value for this is N.
  
index ad5807e1914095aab2bb719203e69b11307a6a4e..5f5c4986ea79c617512344eccbd4dbd9cceef050 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/watchdog/Kconfig
 +++ b/drivers/watchdog/Kconfig
-@@ -927,6 +927,13 @@ config BCM63XX_WDT
+@@ -930,6 +930,13 @@ config BCM63XX_WDT
          To compile this driver as a loadable module, choose M here.
          The module will be called bcm63xx_wdt.
  
index 17a3bc28b06054985276a6790c8e025daeb52a7c..dcf7a6deff04a1bca038fbb96dc73922fff08413 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/mtd/devices/m25p80.c
 +++ b/drivers/mtd/devices/m25p80.c
-@@ -937,6 +937,16 @@ static int __devinit m25p_probe(struct s
+@@ -933,6 +933,16 @@ static int __devinit m25p_probe(struct s
                                        part_probes, &parts, 0);
                }
  
index 2b10acbd07dc2af8cb3e4fba82afcb5dbc318a1e..bb0ff7d3f8b8703812f33a026ec45658a534d8b8 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/mtd/devices/m25p80.c
 +++ b/drivers/mtd/devices/m25p80.c
-@@ -947,6 +947,15 @@ static int __devinit m25p_probe(struct s
+@@ -943,6 +943,15 @@ static int __devinit m25p_probe(struct s
                }
  #endif
  
index 246abd5dc0832fbd61322d08cb7f3b56041a72b9..0c3814c1fcbdcb195ccc00746ff22896e9c1cd30 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/mtd/chips/jedec_probe.c
 +++ b/drivers/mtd/chips/jedec_probe.c
-@@ -148,6 +148,7 @@
+@@ -149,6 +149,7 @@
  #define SST39LF160    0x2782
  #define SST39VF1601   0x234b
  #define SST39VF3201   0x235b
@@ -8,7 +8,7 @@
  #define SST39WF1601   0x274b
  #define SST39WF1602   0x274a
  #define SST39LF512    0x00D4
-@@ -1568,6 +1569,18 @@ static const struct amd_flash_info jedec
+@@ -1582,6 +1583,18 @@ static const struct amd_flash_info jedec
                        ERASEINFO(0x10000,64),
                }
        }, {
index dc1bada6ba52ac4933b69d6c5dd1e865e2661d62..e8e1ec0024d909b483808765032f359d38135097 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/mtd/chips/cfi_cmdset_0002.c
 +++ b/drivers/mtd/chips/cfi_cmdset_0002.c
-@@ -1231,8 +1231,8 @@ static int __xipram do_write_oneword(str
+@@ -1228,8 +1228,8 @@ static int __xipram do_write_oneword(str
                        break;
                }
  
@@ -11,7 +11,7 @@
  
                /* Latency issues. Drop the lock, wait a while and retry */
                UDELAY(map, chip, adr, 1);
-@@ -1248,6 +1248,8 @@ static int __xipram do_write_oneword(str
+@@ -1245,6 +1245,8 @@ static int __xipram do_write_oneword(str
  
                ret = -EIO;
        }
@@ -20,7 +20,7 @@
        xip_enable(map, chip, adr);
   op_done:
        chip->state = FL_READY;
-@@ -1579,7 +1581,6 @@ static int cfi_amdstd_write_buffers(stru
+@@ -1576,7 +1578,6 @@ static int cfi_amdstd_write_buffers(stru
        return 0;
  }
  
@@ -28,7 +28,7 @@
  /*
   * Handle devices with one erase region, that only implement
   * the chip erase command.
-@@ -1643,8 +1644,8 @@ static int __xipram do_erase_chip(struct
+@@ -1640,8 +1641,8 @@ static int __xipram do_erase_chip(struct
                        chip->erase_suspended = 0;
                }
  
@@ -39,7 +39,7 @@
  
                if (time_after(jiffies, timeo)) {
                        printk(KERN_WARNING "MTD %s(): software timeout\n",
-@@ -1664,6 +1665,7 @@ static int __xipram do_erase_chip(struct
+@@ -1661,6 +1662,7 @@ static int __xipram do_erase_chip(struct
                ret = -EIO;
        }
  
@@ -47,7 +47,7 @@
        chip->state = FL_READY;
        xip_enable(map, chip, adr);
        put_chip(map, chip, adr);
-@@ -1731,9 +1733,9 @@ static int __xipram do_erase_oneblock(st
+@@ -1728,9 +1730,9 @@ static int __xipram do_erase_oneblock(st
                        chip->erase_suspended = 0;
                }
  
@@ -59,7 +59,7 @@
                }
  
                if (time_after(jiffies, timeo)) {
-@@ -1755,6 +1757,7 @@ static int __xipram do_erase_oneblock(st
+@@ -1752,6 +1754,7 @@ static int __xipram do_erase_oneblock(st
                ret = -EIO;
        }
  
index 7cd961dcb575f8a25b96d257d1f3764ee51961a6..c8012f57d6a4f44da445f736c76ed561b5cab0b4 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/mtd/devices/m25p80.c
 +++ b/drivers/mtd/devices/m25p80.c
-@@ -956,6 +956,16 @@ static int __devinit m25p_probe(struct s
+@@ -952,6 +952,16 @@ static int __devinit m25p_probe(struct s
                                        part_probes, &parts, 0);
                }
  #endif
index edd9e4e02629d4f3ebb77501b282fe8aa9beff0a..905206d7bb7af8c30e1e9ccb22c15a40705503c8 100644 (file)
@@ -12,8 +12,8 @@
  /* makes sure the async qh will become idle */
 --- a/drivers/usb/host/ehci.h
 +++ b/drivers/usb/host/ehci.h
-@@ -133,6 +133,7 @@ struct ehci_hcd {                  /* one per controlle
-       unsigned                broken_periodic:1;
+@@ -134,6 +134,7 @@ struct ehci_hcd {                  /* one per controlle
+       unsigned                amd_l1_fix:1;
        unsigned                fs_i_thresh:1;  /* Intel iso scheduling */
        unsigned                use_dummy_qh:1; /* AMD Frame List table quirk*/
 +      unsigned                has_synopsys_hc_bug:1; /* Synopsys HC */
index 9dca6eabd997cf8b6b1f003251be6ddc10e2fd52..a972f8f5101a99c9dc3680b77215749818c42538 100644 (file)
@@ -35,7 +35,7 @@
  
  /* Atmel chips don't use the same PRI format as AMD chips */
  static void fixup_convert_atmel_pri(struct mtd_info *mtd, void *param)
-@@ -1391,6 +1395,7 @@ static int cfi_amdstd_write_words(struct
+@@ -1388,6 +1392,7 @@ static int cfi_amdstd_write_words(struct
  /*
   * FIXME: interleaved mode not tested, and probably not supported!
   */
@@ -43,7 +43,7 @@
  static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
                                    unsigned long adr, const u_char *buf,
                                    int len)
-@@ -1501,7 +1506,6 @@ static int __xipram do_write_buffer(stru
+@@ -1498,7 +1503,6 @@ static int __xipram do_write_buffer(stru
        return ret;
  }
  
@@ -51,7 +51,7 @@
  static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len,
                                    size_t *retlen, const u_char *buf)
  {
-@@ -1580,6 +1584,7 @@ static int cfi_amdstd_write_buffers(stru
+@@ -1577,6 +1581,7 @@ static int cfi_amdstd_write_buffers(stru
  
        return 0;
  }
index cfbea70c53d8c0b7a9ec66cf245afd655e3b20c1..9fb5ffa02efd8911b2c0e2354f1936dc2a0d85b5 100644 (file)
@@ -1,8 +1,8 @@
 --- a/drivers/leds/Kconfig
 +++ b/drivers/leds/Kconfig
-@@ -347,6 +347,13 @@ config LEDS_TRIGGERS
- if LEDS_TRIGGERS
+@@ -377,6 +377,13 @@ config LEDS_TRIGGERS
+         These triggers allow kernel events to drive the LEDs and can
+         be configured via sysfs. If unsure, say Y.
  
 +config LEDS_WNDR3700_USB
 +      tristate "NETGEAR WNDR3700 USB LED driver"
index 6614fb933149ee144b2ab4272dcce715efb30cac..34ec66d283ad2f0be67a97850a2195b35d99db6f 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/leds/Kconfig
 +++ b/drivers/leds/Kconfig
-@@ -354,6 +354,10 @@ config LEDS_WNDR3700_USB
+@@ -384,6 +384,10 @@ config LEDS_WNDR3700_USB
          This option enables support for the USB LED found on the
          NETGEAR WNDR3700 board.
  
index 26e24c0698cc6b6b55c76c58e7ab2b8e5bf3dfd6..aaefb7112d5fe088e9ee0c2821b9771516e247c9 100644 (file)
@@ -10,7 +10,7 @@
  
 --- a/arch/mips/Kconfig
 +++ b/arch/mips/Kconfig
-@@ -907,6 +907,9 @@ config MIPS_NILE4
+@@ -909,6 +909,9 @@ config MIPS_NILE4
  config MIPS_DISABLE_OBSOLETE_IDE
        bool
  
index 696094fdd854b4611ffe3033fb64baf7bda7766e..0b36217b6e0a1b526c6dc6adfab78483780adca8 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/mtd/nand/rb4xx_nand.c
 +++ b/drivers/mtd/nand/rb4xx_nand.c
-@@ -220,7 +220,7 @@ static int __init rb4xx_nand_probe(struc
+@@ -223,7 +223,7 @@ static int __init rb4xx_nand_probe(struc
  
        platform_set_drvdata(pdev, info);
  
index 895d3ce888e60cfdaa0bf5a1368fc2904741f60b..38d997ef68da1cff73a979937982444e9504e6e8 100644 (file)
@@ -8,7 +8,7 @@
  
  extern void check_wait(void);
  extern asmlinkage void r4k_wait(void);
-@@ -1552,6 +1553,8 @@ void __cpuinit per_cpu_trap_init(void)
+@@ -1578,6 +1579,8 @@ void __cpuinit per_cpu_trap_init(void)
        if (cpu_has_mips_r2) {
                cp0_compare_irq_shift = CAUSEB_TI - CAUSEB_IP;
                cp0_compare_irq = (read_c0_intctl() >> INTCTLB_IPTI) & 7;
index 4ccd3764aec2d5e8615cc684fe149a36ba775607..1fe64837caf71c7d4f0b12203379d597f5acafce 100644 (file)
@@ -805,12 +805,6 @@ CONFIG_IDE_PROC_FS=y
 # CONFIG_IKCONFIG is not set
 # CONFIG_IKCONFIG_PROC is not set
 # CONFIG_IMAGE_CMDLINE_HACK is not set
-# CONFIG_IMQ is not set
-# CONFIG_IMQ_BEHAVIOR_AA is not set
-# CONFIG_IMQ_BEHAVIOR_AB is not set
-# CONFIG_IMQ_BEHAVIOR_BA is not set
-# CONFIG_IMQ_BEHAVIOR_BB is not set
-CONFIG_IMQ_NUM_DEVS=2
 CONFIG_INET=y
 # CONFIG_INET6_AH is not set
 # CONFIG_INET6_ESP is not set
index d54c1d221a735f3929ce6e7754663fe727893250..c31b4ddea4d80a1630facb5cdf76e2b2c20533f2 100644 (file)
@@ -799,12 +799,6 @@ CONFIG_IDE_PROC_FS=y
 # CONFIG_IKCONFIG is not set
 # CONFIG_IKCONFIG_PROC is not set
 # CONFIG_IMAGE_CMDLINE_HACK is not set
-# CONFIG_IMQ is not set
-# CONFIG_IMQ_BEHAVIOR_AA is not set
-# CONFIG_IMQ_BEHAVIOR_AB is not set
-# CONFIG_IMQ_BEHAVIOR_BA is not set
-# CONFIG_IMQ_BEHAVIOR_BB is not set
-CONFIG_IMQ_NUM_DEVS=2
 CONFIG_INET=y
 # CONFIG_INET6_AH is not set
 # CONFIG_INET6_ESP is not set
index 0bb2b663984c38a731c0f23ff565c7ed19e0eb59..b035981294281ee0276441fa314b4e700ff63e06 100644 (file)
@@ -857,12 +857,6 @@ CONFIG_IDE_PROC_FS=y
 # CONFIG_IKCONFIG is not set
 # CONFIG_IKCONFIG_PROC is not set
 # CONFIG_IMAGE_CMDLINE_HACK is not set
-# CONFIG_IMQ is not set
-# CONFIG_IMQ_BEHAVIOR_AA is not set
-# CONFIG_IMQ_BEHAVIOR_AB is not set
-# CONFIG_IMQ_BEHAVIOR_BA is not set
-# CONFIG_IMQ_BEHAVIOR_BB is not set
-CONFIG_IMQ_NUM_DEVS=2
 CONFIG_INET=y
 # CONFIG_INET6_AH is not set
 # CONFIG_INET6_ESP is not set
index c14a3402d3de5f6c7365eb346d7bda48fbe8ed55..64c76f12ec2d2e8ccb9686d77d285f97e588f1b7 100644 (file)
@@ -894,12 +894,6 @@ CONFIG_IDE_PROC_FS=y
 # CONFIG_IKCONFIG is not set
 # CONFIG_IKCONFIG_PROC is not set
 # CONFIG_IMAGE_CMDLINE_HACK is not set
-# CONFIG_IMQ is not set
-# CONFIG_IMQ_BEHAVIOR_AA is not set
-# CONFIG_IMQ_BEHAVIOR_AB is not set
-# CONFIG_IMQ_BEHAVIOR_BA is not set
-# CONFIG_IMQ_BEHAVIOR_BB is not set
-CONFIG_IMQ_NUM_DEVS=2
 CONFIG_INET=y
 # CONFIG_INET6_AH is not set
 # CONFIG_INET6_ESP is not set
index d416c6d2792699884abcc4ec1a2026a7d5cd4a9e..bf813965d2431b34d2bee319793f4bb2ece6f7e2 100644 (file)
@@ -929,12 +929,6 @@ CONFIG_IDE_PROC_FS=y
 # CONFIG_IKCONFIG is not set
 # CONFIG_IKCONFIG_PROC is not set
 # CONFIG_IMAGE_CMDLINE_HACK is not set
-# CONFIG_IMQ is not set
-# CONFIG_IMQ_BEHAVIOR_AA is not set
-# CONFIG_IMQ_BEHAVIOR_AB is not set
-# CONFIG_IMQ_BEHAVIOR_BA is not set
-# CONFIG_IMQ_BEHAVIOR_BB is not set
-CONFIG_IMQ_NUM_DEVS=2
 CONFIG_INET=y
 # CONFIG_INET6_AH is not set
 # CONFIG_INET6_ESP is not set
index d3138fcac8c3276d22d8003b7c9c9d50d64ba642..47a35aa74733b4236f21a1e5892d4b7608e574ce 100644 (file)
@@ -877,12 +877,6 @@ CONFIG_IDE_PROC_FS=y
 # CONFIG_IKCONFIG is not set
 # CONFIG_IKCONFIG_PROC is not set
 # CONFIG_IMAGE_CMDLINE_HACK is not set
-# CONFIG_IMQ is not set
-# CONFIG_IMQ_BEHAVIOR_AA is not set
-# CONFIG_IMQ_BEHAVIOR_AB is not set
-# CONFIG_IMQ_BEHAVIOR_BA is not set
-# CONFIG_IMQ_BEHAVIOR_BB is not set
-CONFIG_IMQ_NUM_DEVS=2
 CONFIG_INET=y
 # CONFIG_INET6_AH is not set
 # CONFIG_INET6_ESP is not set
index 472c3a4e46754c534803c5545c8cfc40662478d0..1899da76c8986deefc101e5156d046c646552090 100644 (file)
@@ -897,12 +897,6 @@ CONFIG_IDE_PROC_FS=y
 # CONFIG_IKCONFIG is not set
 # CONFIG_IKCONFIG_PROC is not set
 # CONFIG_IMAGE_CMDLINE_HACK is not set
-# CONFIG_IMQ is not set
-# CONFIG_IMQ_BEHAVIOR_AA is not set
-# CONFIG_IMQ_BEHAVIOR_AB is not set
-# CONFIG_IMQ_BEHAVIOR_BA is not set
-# CONFIG_IMQ_BEHAVIOR_BB is not set
-CONFIG_IMQ_NUM_DEVS=2
 CONFIG_INET=y
 # CONFIG_INET6_AH is not set
 # CONFIG_INET6_ESP is not set
index 499bec06d395bb210450ccfce4cda6959741aeeb..dad054e2659f7a037c004c2ee6a02f282b770e64 100644 (file)
@@ -903,12 +903,6 @@ CONFIG_IDE_PROC_FS=y
 # CONFIG_IKCONFIG is not set
 # CONFIG_IKCONFIG_PROC is not set
 # CONFIG_IMAGE_CMDLINE_HACK is not set
-# CONFIG_IMQ_BEHAVIOR_AA is not set
-# CONFIG_IMQ_BEHAVIOR_AB is not set
-# CONFIG_IMQ_BEHAVIOR_BA is not set
-# CONFIG_IMQ_BEHAVIOR_BB is not set
-# CONFIG_IMQ is not set
-CONFIG_IMQ_NUM_DEVS=2
 # CONFIG_INET6_AH is not set
 # CONFIG_INET6_ESP is not set
 # CONFIG_INET6_IPCOMP is not set
diff --git a/target/linux/generic/patches-2.6.30/150-netfilter_imq.patch b/target/linux/generic/patches-2.6.30/150-netfilter_imq.patch
deleted file mode 100644 (file)
index 3bd7a8f..0000000
+++ /dev/null
@@ -1,1260 +0,0 @@
---- /dev/null
-+++ b/drivers/net/imq.c
-@@ -0,0 +1,571 @@
-+/*
-+ *             Pseudo-driver for the intermediate queue device.
-+ *
-+ *             This program is free software; you can redistribute it and/or
-+ *             modify it under the terms of the GNU General Public License
-+ *             as published by the Free Software Foundation; either version
-+ *             2 of the License, or (at your option) any later version.
-+ *
-+ * Authors:    Patrick McHardy, <kaber@trash.net>
-+ *
-+ *            The first version was written by Martin Devera, <devik@cdi.cz>
-+ *
-+ * Credits:    Jan Rafaj <imq2t@cedric.vabo.cz>
-+ *              - Update patch to 2.4.21
-+ *             Sebastian Strollo <sstrollo@nortelnetworks.com>
-+ *              - Fix "Dead-loop on netdevice imq"-issue
-+ *             Marcel Sebek <sebek64@post.cz>
-+ *              - Update to 2.6.2-rc1
-+ *
-+ *           After some time of inactivity there is a group taking care
-+ *           of IMQ again: http://www.linuximq.net
-+ *
-+ *
-+ *           2004/06/30 - New version of IMQ patch to kernels <=2.6.7
-+ *             including the following changes:
-+ *
-+ *           - Correction of ipv6 support "+"s issue (Hasso Tepper)
-+ *           - Correction of imq_init_devs() issue that resulted in
-+ *           kernel OOPS unloading IMQ as module (Norbert Buchmuller)
-+ *           - Addition of functionality to choose number of IMQ devices
-+ *           during kernel config (Andre Correa)
-+ *           - Addition of functionality to choose how IMQ hooks on
-+ *           PRE and POSTROUTING (after or before NAT) (Andre Correa)
-+ *           - Cosmetic corrections (Norbert Buchmuller) (Andre Correa)
-+ *
-+ *
-+ *             2005/12/16 - IMQ versions between 2.6.7 and 2.6.13 were
-+ *             released with almost no problems. 2.6.14-x was released
-+ *             with some important changes: nfcache was removed; After
-+ *             some weeks of trouble we figured out that some IMQ fields
-+ *             in skb were missing in skbuff.c - skb_clone and copy_skb_header.
-+ *             These functions are correctly patched by this new patch version.
-+ *
-+ *             Thanks for all who helped to figure out all the problems with
-+ *             2.6.14.x: Patrick McHardy, Rune Kock, VeNoMouS, Max CtRiX,
-+ *             Kevin Shanahan, Richard Lucassen, Valery Dachev (hopefully
-+ *             I didn't forget anybody). I apologize again for my lack of time.
-+ *
-+ *
-+ *             2008/06/17 - 2.6.25 - Changed imq.c to use qdisc_run() instead
-+ *             of qdisc_restart() and moved qdisc_run() to tasklet to avoid
-+ *             recursive locking. New initialization routines to fix 'rmmod' not
-+ *             working anymore. Used code from ifb.c. (Jussi Kivilinna)
-+ *
-+ *             2008/08/06 - 2.6.26 - (JK)
-+ *              - Replaced tasklet with 'netif_schedule()'.
-+ *              - Cleaned up and added comments for imq_nf_queue().
-+ *
-+ *             2009/04/12
-+ *              - Add skb_save_cb/skb_restore_cb helper functions for backuping
-+ *                control buffer. This is needed because qdisc-layer on kernels
-+ *                2.6.27 and newer overwrite control buffer. (Jussi Kivilinna)
-+ *              - Add better locking for IMQ device. Hopefully this will solve
-+ *                SMP issues. (Jussi Kivilinna)
-+ *              - Port to 2.6.27
-+ *              - Port to 2.6.28
-+ *              - Port to 2.6.29 + fix rmmod not working
-+ *
-+ *             2009/04/20 - (Jussi Kivilinna)
-+ *              - Use netdevice feature flags to avoid extra packet handling
-+ *                by core networking layer and possibly increase performance.
-+ *
-+ *           Also, many thanks to pablo Sebastian Greco for making the initial
-+ *           patch and to those who helped the testing.
-+ *
-+ *             More info at: http://www.linuximq.net/ (Andre Correa)
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/moduleparam.h>
-+#include <linux/list.h>
-+#include <linux/skbuff.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/rtnetlink.h>
-+#include <linux/if_arp.h>
-+#include <linux/netfilter.h>
-+#include <linux/netfilter_ipv4.h>
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+      #include <linux/netfilter_ipv6.h>
-+#endif
-+#include <linux/imq.h>
-+#include <net/pkt_sched.h>
-+#include <net/netfilter/nf_queue.h>
-+
-+static nf_hookfn imq_nf_hook;
-+
-+static struct nf_hook_ops imq_ingress_ipv4 = {
-+      .hook           = imq_nf_hook,
-+      .owner          = THIS_MODULE,
-+      .pf             = PF_INET,
-+      .hooknum        = NF_INET_PRE_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+      .priority       = NF_IP_PRI_MANGLE + 1
-+#else
-+      .priority       = NF_IP_PRI_NAT_DST + 1
-+#endif
-+};
-+
-+static struct nf_hook_ops imq_egress_ipv4 = {
-+      .hook           = imq_nf_hook,
-+      .owner          = THIS_MODULE,
-+      .pf             = PF_INET,
-+      .hooknum        = NF_INET_POST_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
-+      .priority       = NF_IP_PRI_LAST
-+#else
-+      .priority       = NF_IP_PRI_NAT_SRC - 1
-+#endif
-+};
-+
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+static struct nf_hook_ops imq_ingress_ipv6 = {
-+      .hook           = imq_nf_hook,
-+      .owner          = THIS_MODULE,
-+      .pf             = PF_INET6,
-+      .hooknum        = NF_INET_PRE_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+      .priority       = NF_IP6_PRI_MANGLE + 1
-+#else
-+      .priority       = NF_IP6_PRI_NAT_DST + 1
-+#endif
-+};
-+
-+static struct nf_hook_ops imq_egress_ipv6 = {
-+      .hook           = imq_nf_hook,
-+      .owner          = THIS_MODULE,
-+      .pf             = PF_INET6,
-+      .hooknum        = NF_INET_POST_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
-+      .priority       = NF_IP6_PRI_LAST
-+#else
-+      .priority       = NF_IP6_PRI_NAT_SRC - 1
-+#endif
-+};
-+#endif
-+
-+#if defined(CONFIG_IMQ_NUM_DEVS)
-+static unsigned int numdevs = CONFIG_IMQ_NUM_DEVS;
-+#else
-+static unsigned int numdevs = IMQ_MAX_DEVS;
-+#endif
-+
-+static DEFINE_SPINLOCK(imq_nf_queue_lock);
-+
-+static struct net_device *imq_devs_cache[IMQ_MAX_DEVS];
-+
-+
-+static struct net_device_stats *imq_get_stats(struct net_device *dev)
-+{
-+      return &dev->stats;
-+}
-+
-+/* called for packets kfree'd in qdiscs at places other than enqueue */
-+static void imq_skb_destructor(struct sk_buff *skb)
-+{
-+      struct nf_queue_entry *entry = skb->nf_queue_entry;
-+
-+      if (entry) {
-+              nf_queue_entry_release_refs(entry);
-+              kfree(entry);
-+      }
-+
-+      skb_restore_cb(skb); /* kfree backup */
-+}
-+
-+static void imq_nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
-+{
-+      int status;
-+
-+      if (!entry->next_outfn) {
-+              spin_lock_bh(&imq_nf_queue_lock);
-+              nf_reinject(entry, verdict);
-+              spin_unlock_bh(&imq_nf_queue_lock);
-+              return;
-+      }
-+
-+      rcu_read_lock();
-+      local_bh_disable();
-+      status = entry->next_outfn(entry, entry->next_queuenum);
-+      local_bh_enable();
-+      if (status < 0) {
-+              nf_queue_entry_release_refs(entry);
-+              kfree_skb(entry->skb);
-+              kfree(entry);
-+      }
-+
-+      rcu_read_unlock();
-+}
-+
-+static int imq_dev_xmit(struct sk_buff *skb, struct net_device *dev)
-+{
-+      dev->stats.tx_bytes += skb->len;
-+      dev->stats.tx_packets++;
-+
-+      skb->imq_flags = 0;
-+      skb->destructor = NULL;
-+
-+      skb_restore_cb(skb); /* restore skb->cb */
-+
-+      dev->trans_start = jiffies;
-+      imq_nf_reinject(skb->nf_queue_entry, NF_ACCEPT);
-+      return 0;
-+}
-+
-+static int imq_nf_queue(struct nf_queue_entry *entry, unsigned queue_num)
-+{
-+      struct net_device *dev;
-+      struct sk_buff *skb_orig, *skb, *skb_shared;
-+      struct Qdisc *q;
-+      struct netdev_queue *txq;
-+      int users, index;
-+      int retval = -EINVAL;
-+
-+      index = entry->skb->imq_flags & IMQ_F_IFMASK;
-+      if (unlikely(index > numdevs - 1)) {
-+              if (net_ratelimit())
-+                      printk(KERN_WARNING
-+                             "IMQ: invalid device specified, highest is %u\n",
-+                             numdevs - 1);
-+              retval = -EINVAL;
-+              goto out;
-+      }
-+
-+      /* check for imq device by index from cache */
-+      dev = imq_devs_cache[index];
-+      if (unlikely(!dev)) {
-+              char buf[8];
-+
-+              /* get device by name and cache result */
-+              snprintf(buf, sizeof(buf), "imq%d", index);
-+              dev = dev_get_by_name(&init_net, buf);
-+              if (!dev) {
-+                      /* not found ?!*/
-+                      BUG();
-+                      retval = -ENODEV;
-+                      goto out;
-+              }
-+
-+              imq_devs_cache[index] = dev;
-+              dev_put(dev);
-+      }
-+
-+      if (unlikely(!(dev->flags & IFF_UP))) {
-+              entry->skb->imq_flags = 0;
-+              imq_nf_reinject(entry, NF_ACCEPT);
-+              retval = 0;
-+              goto out;
-+      }
-+      dev->last_rx = jiffies;
-+
-+      skb = entry->skb;
-+      skb_orig = NULL;
-+
-+      /* skb has owner? => make clone */
-+      if (unlikely(skb->destructor)) {
-+              skb_orig = skb;
-+              skb = skb_clone(skb, GFP_ATOMIC);
-+              if (!skb) {
-+                      retval = -ENOMEM;
-+                      goto out;
-+              }
-+              entry->skb = skb;
-+      }
-+
-+      skb->nf_queue_entry = entry;
-+
-+      dev->stats.rx_bytes += skb->len;
-+      dev->stats.rx_packets++;
-+
-+      txq = dev_pick_tx(dev, skb);
-+
-+      q = rcu_dereference(txq->qdisc);
-+      if (unlikely(!q->enqueue))
-+              goto packet_not_eaten_by_imq_dev;
-+
-+      spin_lock_bh(qdisc_lock(q));
-+
-+      users = atomic_read(&skb->users);
-+
-+      skb_shared = skb_get(skb); /* increase reference count by one */
-+      skb_save_cb(skb_shared); /* backup skb->cb, as qdisc layer will
-+                                      overwrite it */
-+      qdisc_enqueue_root(skb_shared, q); /* might kfree_skb */
-+
-+      if (likely(atomic_read(&skb_shared->users) == users + 1)) {
-+              kfree_skb(skb_shared); /* decrease reference count by one */
-+
-+              skb->destructor = &imq_skb_destructor;
-+
-+              /* cloned? */
-+              if (skb_orig)
-+                      kfree_skb(skb_orig); /* free original */
-+
-+              spin_unlock_bh(qdisc_lock(q));
-+
-+              /* schedule qdisc dequeue */
-+              __netif_schedule(q);
-+
-+              retval = 0;
-+              goto out;
-+      } else {
-+              skb_restore_cb(skb_shared); /* restore skb->cb */
-+              /* qdisc dropped packet and decreased skb reference count of
-+               * skb, so we don't really want to and try refree as that would
-+               * actually destroy the skb. */
-+              spin_unlock_bh(qdisc_lock(q));
-+              goto packet_not_eaten_by_imq_dev;
-+      }
-+
-+packet_not_eaten_by_imq_dev:
-+      /* cloned? restore original */
-+      if (skb_orig) {
-+              kfree_skb(skb);
-+              entry->skb = skb_orig;
-+      }
-+      retval = -1;
-+out:
-+      return retval;
-+}
-+
-+static struct nf_queue_handler nfqh = {
-+      .name  = "imq",
-+      .outfn = imq_nf_queue,
-+};
-+
-+static unsigned int imq_nf_hook(unsigned int hook, struct sk_buff *pskb,
-+                              const struct net_device *indev,
-+                              const struct net_device *outdev,
-+                              int (*okfn)(struct sk_buff *))
-+{
-+      if (pskb->imq_flags & IMQ_F_ENQUEUE)
-+              return NF_QUEUE;
-+
-+      return NF_ACCEPT;
-+}
-+
-+static int imq_close(struct net_device *dev)
-+{
-+      netif_stop_queue(dev);
-+      return 0;
-+}
-+
-+static int imq_open(struct net_device *dev)
-+{
-+      netif_start_queue(dev);
-+      return 0;
-+}
-+
-+static const struct net_device_ops imq_netdev_ops = {
-+      .ndo_open               = imq_open,
-+      .ndo_stop               = imq_close,
-+      .ndo_start_xmit         = imq_dev_xmit,
-+      .ndo_get_stats          = imq_get_stats,
-+};
-+
-+static void imq_setup(struct net_device *dev)
-+{
-+      dev->netdev_ops         = &imq_netdev_ops;
-+      dev->type               = ARPHRD_VOID;
-+      dev->mtu                = 16000;
-+      dev->tx_queue_len       = 11000;
-+      dev->flags              = IFF_NOARP;
-+      dev->features           = NETIF_F_SG | NETIF_F_FRAGLIST |
-+                                NETIF_F_GSO | NETIF_F_HW_CSUM |
-+                                NETIF_F_HIGHDMA;
-+}
-+
-+static int imq_validate(struct nlattr *tb[], struct nlattr *data[])
-+{
-+      int ret = 0;
-+
-+      if (tb[IFLA_ADDRESS]) {
-+              if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) {
-+                      ret = -EINVAL;
-+                      goto end;
-+              }
-+              if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) {
-+                      ret = -EADDRNOTAVAIL;
-+                      goto end;
-+              }
-+      }
-+      return 0;
-+end:
-+      printk(KERN_WARNING "IMQ: imq_validate failed (%d)\n", ret);
-+      return ret;
-+}
-+
-+static struct rtnl_link_ops imq_link_ops __read_mostly = {
-+      .kind           = "imq",
-+      .priv_size      = 0,
-+      .setup          = imq_setup,
-+      .validate       = imq_validate,
-+};
-+
-+static int __init imq_init_hooks(void)
-+{
-+      int err;
-+
-+      nf_register_queue_imq_handler(&nfqh);
-+
-+      err = nf_register_hook(&imq_ingress_ipv4);
-+      if (err)
-+              goto err1;
-+
-+      err = nf_register_hook(&imq_egress_ipv4);
-+      if (err)
-+              goto err2;
-+
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+      err = nf_register_hook(&imq_ingress_ipv6);
-+      if (err)
-+              goto err3;
-+
-+      err = nf_register_hook(&imq_egress_ipv6);
-+      if (err)
-+              goto err4;
-+#endif
-+
-+      return 0;
-+
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+err4:
-+      nf_unregister_hook(&imq_ingress_ipv6);
-+err3:
-+      nf_unregister_hook(&imq_egress_ipv4);
-+#endif
-+err2:
-+      nf_unregister_hook(&imq_ingress_ipv4);
-+err1:
-+      nf_unregister_queue_imq_handler();
-+      return err;
-+}
-+
-+static int __init imq_init_one(int index)
-+{
-+      struct net_device *dev;
-+      int ret;
-+
-+      dev = alloc_netdev(0, "imq%d", imq_setup);
-+      if (!dev)
-+              return -ENOMEM;
-+
-+      ret = dev_alloc_name(dev, dev->name);
-+      if (ret < 0)
-+              goto fail;
-+
-+      dev->rtnl_link_ops = &imq_link_ops;
-+      ret = register_netdevice(dev);
-+      if (ret < 0)
-+              goto fail;
-+
-+      return 0;
-+fail:
-+      free_netdev(dev);
-+      return ret;
-+}
-+
-+static int __init imq_init_devs(void)
-+{
-+      int err, i;
-+
-+      if (numdevs < 1 || numdevs > IMQ_MAX_DEVS) {
-+              printk(KERN_ERR "IMQ: numdevs has to be betweed 1 and %u\n",
-+                     IMQ_MAX_DEVS);
-+              return -EINVAL;
-+      }
-+
-+      rtnl_lock();
-+      err = __rtnl_link_register(&imq_link_ops);
-+
-+      for (i = 0; i < numdevs && !err; i++)
-+              err = imq_init_one(i);
-+
-+      if (err) {
-+              __rtnl_link_unregister(&imq_link_ops);
-+              memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
-+      }
-+      rtnl_unlock();
-+
-+      return err;
-+}
-+
-+static int __init imq_init_module(void)
-+{
-+      int err;
-+
-+#if defined(CONFIG_IMQ_NUM_DEVS)
-+      BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS > 16);
-+      BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS < 2);
-+      BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS - 1 > IMQ_F_IFMASK);
-+#endif
-+
-+      err = imq_init_devs();
-+      if (err) {
-+              printk(KERN_ERR "IMQ: Error trying imq_init_devs(net)\n");
-+              return err;
-+      }
-+
-+      err = imq_init_hooks();
-+      if (err) {
-+              printk(KERN_ERR "IMQ: Error trying imq_init_hooks()\n");
-+              rtnl_link_unregister(&imq_link_ops);
-+              memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
-+              return err;
-+      }
-+
-+      printk(KERN_INFO "IMQ driver loaded successfully.\n");
-+
-+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+      printk(KERN_INFO "\tHooking IMQ before NAT on PREROUTING.\n");
-+#else
-+      printk(KERN_INFO "\tHooking IMQ after NAT on PREROUTING.\n");
-+#endif
-+#if defined(CONFIG_IMQ_BEHAVIOR_AB) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+      printk(KERN_INFO "\tHooking IMQ before NAT on POSTROUTING.\n");
-+#else
-+      printk(KERN_INFO "\tHooking IMQ after NAT on POSTROUTING.\n");
-+#endif
-+
-+      return 0;
-+}
-+
-+static void __exit imq_unhook(void)
-+{
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+      nf_unregister_hook(&imq_ingress_ipv6);
-+      nf_unregister_hook(&imq_egress_ipv6);
-+#endif
-+      nf_unregister_hook(&imq_ingress_ipv4);
-+      nf_unregister_hook(&imq_egress_ipv4);
-+
-+      nf_unregister_queue_imq_handler();
-+}
-+
-+static void __exit imq_cleanup_devs(void)
-+{
-+      rtnl_link_unregister(&imq_link_ops);
-+      memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
-+}
-+
-+static void __exit imq_exit_module(void)
-+{
-+      imq_unhook();
-+      imq_cleanup_devs();
-+      printk(KERN_INFO "IMQ driver unloaded successfully.\n");
-+}
-+
-+module_init(imq_init_module);
-+module_exit(imq_exit_module);
-+
-+module_param(numdevs, int, 0);
-+MODULE_PARM_DESC(numdevs, "number of IMQ devices (how many imq* devices will "
-+                      "be created)");
-+MODULE_AUTHOR("http://www.linuximq.net");
-+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See "
-+                      "http://www.linuximq.net/ for more information.");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS_RTNL_LINK("imq");
-+
---- a/drivers/net/Kconfig
-+++ b/drivers/net/Kconfig
-@@ -119,6 +119,129 @@ config EQUALIZER
-         To compile this driver as a module, choose M here: the module
-         will be called eql.  If unsure, say N.
-+config IMQ
-+      tristate "IMQ (intermediate queueing device) support"
-+      depends on NETDEVICES && NETFILTER
-+      ---help---
-+        The IMQ device(s) is used as placeholder for QoS queueing
-+        disciplines. Every packet entering/leaving the IP stack can be
-+        directed through the IMQ device where it's enqueued/dequeued to the
-+        attached qdisc. This allows you to treat network devices as classes
-+        and distribute bandwidth among them. Iptables is used to specify
-+        through which IMQ device, if any, packets travel.
-+
-+        More information at: http://www.linuximq.net/
-+
-+        To compile this driver as a module, choose M here: the module
-+        will be called imq.  If unsure, say N.
-+
-+choice
-+      prompt "IMQ behavior (PRE/POSTROUTING)"
-+      depends on IMQ
-+      default IMQ_BEHAVIOR_AB
-+      help
-+
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              IMQ can work in any of the following ways:
-+
-+                  PREROUTING   |      POSTROUTING
-+              -----------------|-------------------
-+              #1  After NAT    |      After NAT
-+              #2  After NAT    |      Before NAT
-+              #3  Before NAT   |      After NAT
-+              #4  Before NAT   |      Before NAT
-+
-+              The default behavior is to hook before NAT on PREROUTING
-+              and after NAT on POSTROUTING (#3).
-+
-+              This settings are specially usefull when trying to use IMQ
-+              to shape NATed clients.
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_AA
-+      bool "IMQ AA"
-+      help
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              Choosing this option will make IMQ hook like this:
-+
-+              PREROUTING:   After NAT
-+              POSTROUTING:  After NAT
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_AB
-+      bool "IMQ AB"
-+      help
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              Choosing this option will make IMQ hook like this:
-+
-+              PREROUTING:   After NAT
-+              POSTROUTING:  Before NAT
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_BA
-+      bool "IMQ BA"
-+      help
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              Choosing this option will make IMQ hook like this:
-+
-+              PREROUTING:   Before NAT
-+              POSTROUTING:  After NAT
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_BB
-+      bool "IMQ BB"
-+      help
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              Choosing this option will make IMQ hook like this:
-+
-+              PREROUTING:   Before NAT
-+              POSTROUTING:  Before NAT
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+endchoice
-+
-+config IMQ_NUM_DEVS
-+
-+      int "Number of IMQ devices"
-+      range 2 16
-+      depends on IMQ
-+      default "16"
-+      help
-+
-+              This settings defines how many IMQ devices will be
-+              created.
-+
-+              The default value is 16.
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
- config TUN
-       tristate "Universal TUN/TAP device driver support"
-       select CRC32
---- a/drivers/net/Makefile
-+++ b/drivers/net/Makefile
-@@ -152,6 +152,7 @@ obj-$(CONFIG_SLHC) += slhc.o
- obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o
- obj-$(CONFIG_DUMMY) += dummy.o
-+obj-$(CONFIG_IMQ) += imq.o
- obj-$(CONFIG_IFB) += ifb.o
- obj-$(CONFIG_MACVLAN) += macvlan.o
- obj-$(CONFIG_DE600) += de600.o
---- /dev/null
-+++ b/include/linux/imq.h
-@@ -0,0 +1,13 @@
-+#ifndef _IMQ_H
-+#define _IMQ_H
-+
-+/* IFMASK (16 device indexes, 0 to 15) and flag(s) fit in 5 bits */
-+#define IMQ_F_BITS    5
-+
-+#define IMQ_F_IFMASK  0x0f
-+#define IMQ_F_ENQUEUE 0x10
-+
-+#define IMQ_MAX_DEVS  (IMQ_F_IFMASK + 1)
-+
-+#endif /* _IMQ_H */
-+
---- /dev/null
-+++ b/include/linux/netfilter_ipv4/ipt_IMQ.h
-@@ -0,0 +1,10 @@
-+#ifndef _IPT_IMQ_H
-+#define _IPT_IMQ_H
-+
-+/* Backwards compatibility for old userspace */
-+#include <linux/netfilter/xt_IMQ.h>
-+
-+#define ipt_imq_info xt_imq_info
-+
-+#endif /* _IPT_IMQ_H */
-+
---- /dev/null
-+++ b/include/linux/netfilter_ipv6/ip6t_IMQ.h
-@@ -0,0 +1,10 @@
-+#ifndef _IP6T_IMQ_H
-+#define _IP6T_IMQ_H
-+
-+/* Backwards compatibility for old userspace */
-+#include <linux/netfilter/xt_IMQ.h>
-+
-+#define ip6t_imq_info xt_imq_info
-+
-+#endif /* _IP6T_IMQ_H */
-+
---- a/include/linux/skbuff.h
-+++ b/include/linux/skbuff.h
-@@ -28,6 +28,9 @@
- #include <linux/rcupdate.h>
- #include <linux/dmaengine.h>
- #include <linux/hrtimer.h>
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+#include <linux/imq.h>
-+#endif
- /* Don't change this without changing skb_csum_unnecessary! */
- #define CHECKSUM_NONE 0
-@@ -333,6 +336,9 @@ struct sk_buff {
-        * first. This is owned by whoever has the skb queued ATM.
-        */
-       char                    cb[48];
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      void                    *cb_next;
-+#endif
-       unsigned int            len,
-                               data_len;
-@@ -363,6 +369,9 @@ struct sk_buff {
-       struct nf_conntrack     *nfct;
-       struct sk_buff          *nfct_reasm;
- #endif
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      struct nf_queue_entry   *nf_queue_entry;
-+#endif
- #ifdef CONFIG_BRIDGE_NETFILTER
-       struct nf_bridge_info   *nf_bridge;
- #endif
-@@ -383,6 +392,9 @@ struct sk_buff {
-       __u8                    requeue:1;
- #endif
-       /* 0/13/14 bit hole */
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      __u8                    imq_flags:IMQ_F_BITS;
-+#endif
- #ifdef CONFIG_NET_DMA
-       dma_cookie_t            dma_cookie;
-@@ -423,6 +435,12 @@ extern void skb_dma_unmap(struct device 
-                         enum dma_data_direction dir);
- #endif
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+extern int skb_save_cb(struct sk_buff *skb);
-+extern int skb_restore_cb(struct sk_buff *skb);
-+#endif
-+
- extern void kfree_skb(struct sk_buff *skb);
- extern void consume_skb(struct sk_buff *skb);
- extern void          __kfree_skb(struct sk_buff *skb);
-@@ -1931,6 +1949,10 @@ static inline void __nf_copy(struct sk_b
-       dst->nfct_reasm = src->nfct_reasm;
-       nf_conntrack_get_reasm(src->nfct_reasm);
- #endif
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      dst->imq_flags = src->imq_flags;
-+      dst->nf_queue_entry = src->nf_queue_entry;
-+#endif
- #ifdef CONFIG_BRIDGE_NETFILTER
-       dst->nf_bridge  = src->nf_bridge;
-       nf_bridge_get(src->nf_bridge);
---- a/net/core/dev.c
-+++ b/net/core/dev.c
-@@ -96,6 +96,9 @@
- #include <net/net_namespace.h>
- #include <net/sock.h>
- #include <linux/rtnetlink.h>
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+#include <linux/imq.h>
-+#endif
- #include <linux/proc_fs.h>
- #include <linux/seq_file.h>
- #include <linux/stat.h>
-@@ -1678,7 +1681,11 @@ int dev_hard_start_xmit(struct sk_buff *
-       int rc;
-       if (likely(!skb->next)) {
--              if (!list_empty(&ptype_all))
-+              if (!list_empty(&ptype_all)
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+                  && !(skb->imq_flags & IMQ_F_ENQUEUE)
-+#endif
-+                  )
-                       dev_queue_xmit_nit(skb, dev);
-               if (netif_needs_gso(dev, skb)) {
-@@ -1749,8 +1756,7 @@ u16 skb_tx_hash(const struct net_device 
- }
- EXPORT_SYMBOL(skb_tx_hash);
--static struct netdev_queue *dev_pick_tx(struct net_device *dev,
--                                      struct sk_buff *skb)
-+struct netdev_queue *dev_pick_tx(struct net_device *dev, struct sk_buff *skb)
- {
-       const struct net_device_ops *ops = dev->netdev_ops;
-       u16 queue_index = 0;
-@@ -1763,6 +1769,7 @@ static struct netdev_queue *dev_pick_tx(
-       skb_set_queue_mapping(skb, queue_index);
-       return netdev_get_tx_queue(dev, queue_index);
- }
-+EXPORT_SYMBOL(dev_pick_tx);
- /**
-  *    dev_queue_xmit - transmit a buffer
---- a/include/linux/netdevice.h
-+++ b/include/linux/netdevice.h
-@@ -1102,6 +1102,7 @@ extern int               dev_alloc_name(struct net_de
- extern int            dev_open(struct net_device *dev);
- extern int            dev_close(struct net_device *dev);
- extern void           dev_disable_lro(struct net_device *dev);
-+extern struct netdev_queue *dev_pick_tx(struct net_device *dev, struct sk_buff *skb);
- extern int            dev_queue_xmit(struct sk_buff *skb);
- extern int            register_netdevice(struct net_device *dev);
- extern void           unregister_netdevice(struct net_device *dev);
---- /dev/null
-+++ b/include/linux/netfilter/xt_IMQ.h
-@@ -0,0 +1,9 @@
-+#ifndef _XT_IMQ_H
-+#define _XT_IMQ_H
-+
-+struct xt_imq_info {
-+      unsigned int todev;     /* target imq device */
-+};
-+
-+#endif /* _XT_IMQ_H */
-+
---- a/include/net/netfilter/nf_queue.h
-+++ b/include/net/netfilter/nf_queue.h
-@@ -13,6 +13,12 @@ struct nf_queue_entry {
-       struct net_device       *indev;
-       struct net_device       *outdev;
-       int                     (*okfn)(struct sk_buff *);
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      int                     (*next_outfn)(struct nf_queue_entry *entry,
-+                                            unsigned int queuenum);
-+      unsigned int            next_queuenum;
-+#endif
- };
- #define nf_queue_entry_reroute(x) ((void *)x + sizeof(struct nf_queue_entry))
-@@ -30,5 +36,11 @@ extern int nf_unregister_queue_handler(u
-                                      const struct nf_queue_handler *qh);
- extern void nf_unregister_queue_handlers(const struct nf_queue_handler *qh);
- extern void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
-+extern void nf_queue_entry_release_refs(struct nf_queue_entry *entry);
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+extern void nf_register_queue_imq_handler(const struct nf_queue_handler *qh);
-+extern void nf_unregister_queue_imq_handler(void);
-+#endif
- #endif /* _NF_QUEUE_H */
---- a/net/core/skbuff.c
-+++ b/net/core/skbuff.c
-@@ -71,6 +71,9 @@
- static struct kmem_cache *skbuff_head_cache __read_mostly;
- static struct kmem_cache *skbuff_fclone_cache __read_mostly;
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+static struct kmem_cache *skbuff_cb_store_cache __read_mostly;
-+#endif
- static void sock_pipe_buf_release(struct pipe_inode_info *pipe,
-                                 struct pipe_buffer *buf)
-@@ -90,6 +93,80 @@ static int sock_pipe_buf_steal(struct pi
-       return 1;
- }
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+/* Control buffer save/restore for IMQ devices */
-+struct skb_cb_table {
-+      void                    *cb_next;
-+      atomic_t                refcnt;
-+      char                    cb[48];
-+};
-+
-+static DEFINE_SPINLOCK(skb_cb_store_lock);
-+
-+int skb_save_cb(struct sk_buff *skb)
-+{
-+      struct skb_cb_table *next;
-+
-+      next = kmem_cache_alloc(skbuff_cb_store_cache, GFP_ATOMIC);
-+      if (!next)
-+              return -ENOMEM;
-+
-+      BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb));
-+
-+      memcpy(next->cb, skb->cb, sizeof(skb->cb));
-+      next->cb_next = skb->cb_next;
-+
-+      atomic_set(&next->refcnt, 1);
-+
-+      skb->cb_next = next;
-+      return 0;
-+}
-+EXPORT_SYMBOL(skb_save_cb);
-+
-+int skb_restore_cb(struct sk_buff *skb)
-+{
-+      struct skb_cb_table *next;
-+
-+      if (!skb->cb_next)
-+              return 0;
-+
-+      next = skb->cb_next;
-+
-+      BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb));
-+
-+      memcpy(skb->cb, next->cb, sizeof(skb->cb));
-+      skb->cb_next = next->cb_next;
-+
-+      spin_lock(&skb_cb_store_lock);
-+
-+      if (atomic_dec_and_test(&next->refcnt)) {
-+              kmem_cache_free(skbuff_cb_store_cache, next);
-+      }
-+
-+      spin_unlock(&skb_cb_store_lock);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL(skb_restore_cb);
-+
-+static void skb_copy_stored_cb(struct sk_buff *new, struct sk_buff *old)
-+{
-+      struct skb_cb_table *next;
-+
-+      if (!old->cb_next) {
-+              new->cb_next = 0;
-+              return;
-+      }
-+
-+      spin_lock(&skb_cb_store_lock);
-+
-+      next = old->cb_next;
-+      atomic_inc(&next->refcnt);
-+      new->cb_next = next;
-+
-+      spin_unlock(&skb_cb_store_lock);
-+}
-+#endif
- /* Pipe buffer operations for a socket. */
- static struct pipe_buf_operations sock_pipe_buf_ops = {
-@@ -389,6 +466,15 @@ static void skb_release_head_state(struc
-               WARN_ON(in_irq());
-               skb->destructor(skb);
-       }
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      /* This should not happen. When it does, avoid memleak by restoring
-+      the chain of cb-backups. */
-+      while(skb->cb_next != NULL) {
-+              printk(KERN_WARNING "kfree_skb: skb->cb_next: %08x\n",
-+                      skb->cb_next);
-+              skb_restore_cb(skb);
-+      }
-+#endif
- #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
-       nf_conntrack_put(skb->nfct);
-       nf_conntrack_put_reasm(skb->nfct_reasm);
-@@ -526,6 +612,9 @@ static void __copy_skb_header(struct sk_
-       new->sp                 = secpath_get(old->sp);
- #endif
-       memcpy(new->cb, old->cb, sizeof(old->cb));
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      skb_copy_stored_cb(new, old);
-+#endif
-       new->csum_start         = old->csum_start;
-       new->csum_offset        = old->csum_offset;
-       new->local_df           = old->local_df;
-@@ -2769,6 +2858,13 @@ void __init skb_init(void)
-                                               0,
-                                               SLAB_HWCACHE_ALIGN|SLAB_PANIC,
-                                               NULL);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      skbuff_cb_store_cache = kmem_cache_create("skbuff_cb_store_cache",
-+                                                sizeof(struct skb_cb_table),
-+                                                0,
-+                                                SLAB_HWCACHE_ALIGN|SLAB_PANIC,
-+                                                NULL);
-+#endif
- }
- /**
---- a/net/netfilter/Kconfig
-+++ b/net/netfilter/Kconfig
-@@ -396,6 +396,18 @@ config NETFILTER_XT_TARGET_LED
-         For more information on the LEDs available on your system, see
-         Documentation/leds-class.txt
-+config NETFILTER_XT_TARGET_IMQ
-+        tristate '"IMQ" target support'
-+      depends on NETFILTER_XTABLES
-+      depends on IP_NF_MANGLE || IP6_NF_MANGLE
-+      select IMQ
-+      default m if NETFILTER_ADVANCED=n
-+        help
-+          This option adds a `IMQ' target which is used to specify if and
-+          to which imq device packets should get enqueued/dequeued.
-+
-+          To compile it as a module, choose M here.  If unsure, say N.
-+
- config NETFILTER_XT_TARGET_MARK
-       tristate '"MARK" target support'
-       default m if NETFILTER_ADVANCED=n
---- a/net/netfilter/Makefile
-+++ b/net/netfilter/Makefile
-@@ -46,6 +46,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMAR
- obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o
-+obj-$(CONFIG_NETFILTER_XT_TARGET_IMQ) += xt_IMQ.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
---- a/net/netfilter/nf_queue.c
-+++ b/net/netfilter/nf_queue.c
-@@ -20,6 +20,26 @@ static const struct nf_queue_handler *qu
- static DEFINE_MUTEX(queue_handler_mutex);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+static const struct nf_queue_handler *queue_imq_handler;
-+
-+void nf_register_queue_imq_handler(const struct nf_queue_handler *qh)
-+{
-+      mutex_lock(&queue_handler_mutex);
-+      rcu_assign_pointer(queue_imq_handler, qh);
-+      mutex_unlock(&queue_handler_mutex);
-+}
-+EXPORT_SYMBOL(nf_register_queue_imq_handler);
-+
-+void nf_unregister_queue_imq_handler(void)
-+{
-+      mutex_lock(&queue_handler_mutex);
-+      rcu_assign_pointer(queue_imq_handler, NULL);
-+      mutex_unlock(&queue_handler_mutex);
-+}
-+EXPORT_SYMBOL(nf_unregister_queue_imq_handler);
-+#endif
-+
- /* return EBUSY when somebody else is registered, return EEXIST if the
-  * same handler is registered, return 0 in case of success. */
- int nf_register_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh)
-@@ -80,7 +100,7 @@ void nf_unregister_queue_handlers(const 
- }
- EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers);
--static void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
-+void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
- {
-       /* Release those devices we held, or Alexey will kill me. */
-       if (entry->indev)
-@@ -100,6 +120,7 @@ static void nf_queue_entry_release_refs(
-       /* Drop reference to owner of hook which queued us. */
-       module_put(entry->elem->owner);
- }
-+EXPORT_SYMBOL_GPL(nf_queue_entry_release_refs);
- /*
-  * Any packet that leaves via this function must come back
-@@ -121,12 +142,26 @@ static int __nf_queue(struct sk_buff *sk
- #endif
-       const struct nf_afinfo *afinfo;
-       const struct nf_queue_handler *qh;
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      const struct nf_queue_handler *qih = NULL;
-+#endif
-       /* QUEUE == DROP if noone is waiting, to be safe. */
-       rcu_read_lock();
-       qh = rcu_dereference(queue_handler[pf]);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+      if (pf == PF_INET || pf == PF_INET6)
-+#else
-+      if (pf == PF_INET)
-+#endif
-+              qih = rcu_dereference(queue_imq_handler);
-+
-+      if (!qh && !qih)
-+#else /* !IMQ */
-       if (!qh)
-+#endif
-               goto err_unlock;
-       afinfo = nf_get_afinfo(pf);
-@@ -145,6 +180,10 @@ static int __nf_queue(struct sk_buff *sk
-               .indev  = indev,
-               .outdev = outdev,
-               .okfn   = okfn,
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+              .next_outfn = qh ? qh->outfn : NULL,
-+              .next_queuenum = queuenum,
-+#endif
-       };
-       /* If it's going away, ignore hook. */
-@@ -170,8 +209,19 @@ static int __nf_queue(struct sk_buff *sk
-       }
- #endif
-       afinfo->saveroute(skb, entry);
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      if (qih) {
-+              status = qih->outfn(entry, queuenum);
-+              goto imq_skip_queue;
-+      }
-+#endif
-+
-       status = qh->outfn(entry, queuenum);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+imq_skip_queue:
-+#endif
-       rcu_read_unlock();
-       if (status < 0) {
---- /dev/null
-+++ b/net/netfilter/xt_IMQ.c
-@@ -0,0 +1,73 @@
-+/*
-+ * This target marks packets to be enqueued to an imq device
-+ */
-+#include <linux/module.h>
-+#include <linux/skbuff.h>
-+#include <linux/netfilter/x_tables.h>
-+#include <linux/netfilter/xt_IMQ.h>
-+#include <linux/imq.h>
-+
-+static unsigned int imq_target(struct sk_buff *pskb,
-+                              const struct xt_target_param *par)
-+{
-+      const struct xt_imq_info *mr = par->targinfo;
-+
-+      pskb->imq_flags = (mr->todev & IMQ_F_IFMASK) | IMQ_F_ENQUEUE;
-+
-+      return XT_CONTINUE;
-+}
-+
-+static bool imq_checkentry(const struct xt_tgchk_param *par)
-+{
-+      struct xt_imq_info *mr = par->targinfo;
-+
-+      if (mr->todev > IMQ_MAX_DEVS - 1) {
-+              printk(KERN_WARNING
-+                     "IMQ: invalid device specified, highest is %u\n",
-+                     IMQ_MAX_DEVS - 1);
-+              return 0;
-+      }
-+
-+      return 1;
-+}
-+
-+static struct xt_target xt_imq_reg[] __read_mostly = {
-+      {
-+              .name           = "IMQ",
-+              .family         = AF_INET,
-+              .checkentry     = imq_checkentry,
-+              .target         = imq_target,
-+              .targetsize     = sizeof(struct xt_imq_info),
-+              .table          = "mangle",
-+              .me             = THIS_MODULE
-+      },
-+      {
-+              .name           = "IMQ",
-+              .family         = AF_INET6,
-+              .checkentry     = imq_checkentry,
-+              .target         = imq_target,
-+              .targetsize     = sizeof(struct xt_imq_info),
-+              .table          = "mangle",
-+              .me             = THIS_MODULE
-+      },
-+};
-+
-+static int __init imq_init(void)
-+{
-+      return xt_register_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg));
-+}
-+
-+static void __exit imq_fini(void)
-+{
-+      xt_unregister_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg));
-+}
-+
-+module_init(imq_init);
-+module_exit(imq_fini);
-+
-+MODULE_AUTHOR("http://www.linuximq.net");
-+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information.");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS("ipt_IMQ");
-+MODULE_ALIAS("ip6t_IMQ");
-+
index fc00d159c3dcef3b85fe260ade1de66023c14c9f..e05ec77514e1a2f8a97c545c96012855f3b01e89 100644 (file)
@@ -8,7 +8,7 @@
        depends on NETFILTER_ADVANCED
        help
          H.323 is a VoIP signalling protocol from ITU-T. As one of the most
-@@ -505,7 +504,6 @@ config NETFILTER_XT_TARGET_SECMARK
+@@ -493,7 +492,6 @@ config NETFILTER_XT_TARGET_SECMARK
  
  config NETFILTER_XT_TARGET_TCPMSS
        tristate '"TCPMSS" target support'
index 06b494b91be273ddf7d7a140690674b8fe76656d..cc35dcf8880404ae76e56ed66d0053760dd9f44e 100644 (file)
@@ -1,6 +1,6 @@
 --- a/include/linux/skbuff.h
 +++ b/include/linux/skbuff.h
-@@ -1369,11 +1369,18 @@ static inline int skb_network_offset(con
+@@ -1351,11 +1351,18 @@ static inline int skb_network_offset(con
   *
   * Various parts of the networking layer expect at least 32 bytes of
   * headroom, you should not reduce this.
@@ -19,7 +19,7 @@
  extern int ___pskb_trim(struct sk_buff *skb, unsigned int len);
  
  static inline void __skb_trim(struct sk_buff *skb, unsigned int len)
-@@ -1463,9 +1470,9 @@ static inline void __skb_queue_purge(str
+@@ -1445,9 +1452,9 @@ static inline void __skb_queue_purge(str
  static inline struct sk_buff *__dev_alloc_skb(unsigned int length,
                                              gfp_t gfp_mask)
  {
@@ -31,7 +31,7 @@
        return skb;
  }
  
-@@ -1538,7 +1545,7 @@ static inline int __skb_cow(struct sk_bu
+@@ -1520,7 +1527,7 @@ static inline int __skb_cow(struct sk_bu
                delta = headroom - skb_headroom(skb);
  
        if (delta || cloned)
@@ -42,7 +42,7 @@
  }
 --- a/net/core/skbuff.c
 +++ b/net/core/skbuff.c
-@@ -327,9 +327,9 @@ struct sk_buff *__netdev_alloc_skb(struc
+@@ -250,9 +250,9 @@ struct sk_buff *__netdev_alloc_skb(struc
        int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1;
        struct sk_buff *skb;
  
index aac38ff2e78cf7e8f30f63de9d40ef9d7583b62b..4031a7e460039e048f4b3a16724223a2114f6a82 100644 (file)
@@ -1,6 +1,6 @@
 --- a/include/linux/phy.h
 +++ b/include/linux/phy.h
-@@ -393,9 +393,18 @@ struct phy_driver {
+@@ -379,9 +379,18 @@ struct phy_driver {
         */
        int (*config_aneg)(struct phy_device *phydev);
  
@@ -21,7 +21,7 @@
  
 --- a/drivers/net/phy/phy_device.c
 +++ b/drivers/net/phy/phy_device.c
-@@ -695,6 +695,9 @@ int genphy_update_link(struct phy_device
+@@ -590,6 +590,9 @@ int genphy_update_link(struct phy_device
  {
        int status;
  
index d9d3ce7721ff626ada2ad8e1770ff57da8061c51..caa69d6e0e64aa5467c7540cc69143d144580cf6 100644 (file)
@@ -1,7 +1,7 @@
 --- a/drivers/net/phy/Kconfig
 +++ b/drivers/net/phy/Kconfig
-@@ -100,6 +100,10 @@ config IP175C_PHY
-       tristate "Driver for IC+ IP175C/IP178C switches"
+@@ -100,6 +100,10 @@ config IP17XX_PHY
+       tristate "Driver for IC+ IP17xx switches"
        select SWCONFIG
  
 +config AR8216_PHY
@@ -15,7 +15,7 @@
 +++ b/drivers/net/phy/Makefile
 @@ -17,6 +17,7 @@ obj-$(CONFIG_ADM6996_PHY)    += adm6996.o
  obj-$(CONFIG_MVSWITCH_PHY)    += mvswitch.o
- obj-$(CONFIG_IP175C_PHY)      += ip175c.o
+ obj-$(CONFIG_IP17XX_PHY)      += ip17xx.o
  obj-$(CONFIG_REALTEK_PHY)     += realtek.o
 +obj-$(CONFIG_AR8216_PHY)      += ar8216.o
  obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o
index bfebbcff5176f63bc9fcbc73a9905fd5b43cad24..259f7ec6e675ff8dec668a8e66a072eed25d3ed4 100644 (file)
@@ -14,7 +14,7 @@
 --- a/drivers/net/phy/Makefile
 +++ b/drivers/net/phy/Makefile
 @@ -18,6 +18,7 @@ obj-$(CONFIG_MVSWITCH_PHY)   += mvswitch.o
- obj-$(CONFIG_IP175C_PHY)      += ip175c.o
+ obj-$(CONFIG_IP17XX_PHY)      += ip17xx.o
  obj-$(CONFIG_REALTEK_PHY)     += realtek.o
  obj-$(CONFIG_AR8216_PHY)      += ar8216.o
 +obj-$(CONFIG_RTL8306_PHY)     += rtl8306.o
index 4ce0520b11a8f6bfcca9a0c820b7a43b9d8a1e96..62a6430b867b2d92badc8bf2f8f537b82bfe5f24 100644 (file)
@@ -32,7 +32,7 @@
  endif # PHYLIB
 --- a/drivers/net/phy/Makefile
 +++ b/drivers/net/phy/Makefile
-@@ -19,6 +19,9 @@ obj-$(CONFIG_IP175C_PHY)     += ip175c.o
+@@ -19,6 +19,9 @@ obj-$(CONFIG_IP17XX_PHY)     += ip17xx.o
  obj-$(CONFIG_REALTEK_PHY)     += realtek.o
  obj-$(CONFIG_AR8216_PHY)      += ar8216.o
  obj-$(CONFIG_RTL8306_PHY)     += rtl8306.o
index 202f998dde25708fd48a82baf6deac4033256900..581105ccb0a6503497f73931bf8840b458d5e1d8 100644 (file)
@@ -11,7 +11,7 @@
  #  define LL_MAX_HEADER 96
 --- a/include/linux/skbuff.h
 +++ b/include/linux/skbuff.h
-@@ -387,7 +387,7 @@ struct sk_buff {
+@@ -378,7 +378,7 @@ struct sk_buff {
  #ifdef CONFIG_IPV6_NDISC_NODETYPE
        __u8                    ndisc_nodetype:2;
  #endif
index ff23af8a0b75eb648127aec6090903f3e01a6bcb..c1bc4495684e233ac410a542363418f146933a1f 100644 (file)
@@ -1,7 +1,5 @@
-Index: linux-2.6.30.10/drivers/char/random.c
-===================================================================
---- linux-2.6.30.10.orig/drivers/char/random.c 2009-12-04 07:00:07.000000000 +0100
-+++ linux-2.6.30.10/drivers/char/random.c      2010-05-15 15:44:19.000000000 +0200
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
 @@ -129,6 +129,9 @@
   *                                unsigned int value);
   *    void add_interrupt_randomness(int irq);
@@ -26,7 +24,7 @@ Index: linux-2.6.30.10/drivers/char/random.c
   * All of these routines try to estimate how many bits of randomness a
   * particular randomness source.  They do this by keeping track of the
   * first and second order deltas of the event timings.
-@@ -712,6 +722,61 @@
+@@ -712,6 +722,61 @@ void add_disk_randomness(struct gendisk 
  }
  #endif
  
@@ -88,11 +86,9 @@ Index: linux-2.6.30.10/drivers/char/random.c
  #define EXTRACT_SIZE 10
  
  /*********************************************************************
-Index: linux-2.6.30.10/fs/fcntl.c
-===================================================================
---- linux-2.6.30.10.orig/fs/fcntl.c    2009-12-04 07:00:07.000000000 +0100
-+++ linux-2.6.30.10/fs/fcntl.c 2010-05-15 15:44:19.000000000 +0200
-@@ -142,6 +142,7 @@
+--- a/fs/fcntl.c
++++ b/fs/fcntl.c
+@@ -142,6 +142,7 @@ SYSCALL_DEFINE1(dup, unsigned int, filde
        }
        return ret;
  }
@@ -100,10 +96,8 @@ Index: linux-2.6.30.10/fs/fcntl.c
  
  #define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME)
  
-Index: linux-2.6.30.10/include/linux/miscdevice.h
-===================================================================
---- linux-2.6.30.10.orig/include/linux/miscdevice.h    2009-12-04 07:00:07.000000000 +0100
-+++ linux-2.6.30.10/include/linux/miscdevice.h 2010-05-15 15:44:19.000000000 +0200
+--- a/include/linux/miscdevice.h
++++ b/include/linux/miscdevice.h
 @@ -12,6 +12,7 @@
  #define APOLLO_MOUSE_MINOR    7
  #define PC110PAD_MINOR                9
@@ -112,10 +106,8 @@ Index: linux-2.6.30.10/include/linux/miscdevice.h
  #define WATCHDOG_MINOR                130     /* Watchdog timer     */
  #define TEMP_MINOR            131     /* Temperature Sensor */
  #define RTC_MINOR             135
-Index: linux-2.6.30.10/include/linux/random.h
-===================================================================
---- linux-2.6.30.10.orig/include/linux/random.h        2009-12-04 07:00:07.000000000 +0100
-+++ linux-2.6.30.10/include/linux/random.h     2010-05-15 15:44:19.000000000 +0200
+--- a/include/linux/random.h
++++ b/include/linux/random.h
 @@ -9,6 +9,7 @@
  
  #include <linux/types.h>
@@ -155,7 +147,7 @@ Index: linux-2.6.30.10/include/linux/random.h
  struct rand_pool_info {
        int     entropy_count;
        int     buf_size;
-@@ -50,6 +75,10 @@
+@@ -50,6 +75,10 @@ extern void add_input_randomness(unsigne
                                 unsigned int value);
  extern void add_interrupt_randomness(int irq);
  
diff --git a/target/linux/generic/patches-2.6.31/150-netfilter_imq.patch b/target/linux/generic/patches-2.6.31/150-netfilter_imq.patch
deleted file mode 100644 (file)
index ffe80b3..0000000
+++ /dev/null
@@ -1,1260 +0,0 @@
---- /dev/null
-+++ b/drivers/net/imq.c
-@@ -0,0 +1,571 @@
-+/*
-+ *             Pseudo-driver for the intermediate queue device.
-+ *
-+ *             This program is free software; you can redistribute it and/or
-+ *             modify it under the terms of the GNU General Public License
-+ *             as published by the Free Software Foundation; either version
-+ *             2 of the License, or (at your option) any later version.
-+ *
-+ * Authors:    Patrick McHardy, <kaber@trash.net>
-+ *
-+ *            The first version was written by Martin Devera, <devik@cdi.cz>
-+ *
-+ * Credits:    Jan Rafaj <imq2t@cedric.vabo.cz>
-+ *              - Update patch to 2.4.21
-+ *             Sebastian Strollo <sstrollo@nortelnetworks.com>
-+ *              - Fix "Dead-loop on netdevice imq"-issue
-+ *             Marcel Sebek <sebek64@post.cz>
-+ *              - Update to 2.6.2-rc1
-+ *
-+ *           After some time of inactivity there is a group taking care
-+ *           of IMQ again: http://www.linuximq.net
-+ *
-+ *
-+ *           2004/06/30 - New version of IMQ patch to kernels <=2.6.7
-+ *             including the following changes:
-+ *
-+ *           - Correction of ipv6 support "+"s issue (Hasso Tepper)
-+ *           - Correction of imq_init_devs() issue that resulted in
-+ *           kernel OOPS unloading IMQ as module (Norbert Buchmuller)
-+ *           - Addition of functionality to choose number of IMQ devices
-+ *           during kernel config (Andre Correa)
-+ *           - Addition of functionality to choose how IMQ hooks on
-+ *           PRE and POSTROUTING (after or before NAT) (Andre Correa)
-+ *           - Cosmetic corrections (Norbert Buchmuller) (Andre Correa)
-+ *
-+ *
-+ *             2005/12/16 - IMQ versions between 2.6.7 and 2.6.13 were
-+ *             released with almost no problems. 2.6.14-x was released
-+ *             with some important changes: nfcache was removed; After
-+ *             some weeks of trouble we figured out that some IMQ fields
-+ *             in skb were missing in skbuff.c - skb_clone and copy_skb_header.
-+ *             These functions are correctly patched by this new patch version.
-+ *
-+ *             Thanks for all who helped to figure out all the problems with
-+ *             2.6.14.x: Patrick McHardy, Rune Kock, VeNoMouS, Max CtRiX,
-+ *             Kevin Shanahan, Richard Lucassen, Valery Dachev (hopefully
-+ *             I didn't forget anybody). I apologize again for my lack of time.
-+ *
-+ *
-+ *             2008/06/17 - 2.6.25 - Changed imq.c to use qdisc_run() instead
-+ *             of qdisc_restart() and moved qdisc_run() to tasklet to avoid
-+ *             recursive locking. New initialization routines to fix 'rmmod' not
-+ *             working anymore. Used code from ifb.c. (Jussi Kivilinna)
-+ *
-+ *             2008/08/06 - 2.6.26 - (JK)
-+ *              - Replaced tasklet with 'netif_schedule()'.
-+ *              - Cleaned up and added comments for imq_nf_queue().
-+ *
-+ *             2009/04/12
-+ *              - Add skb_save_cb/skb_restore_cb helper functions for backuping
-+ *                control buffer. This is needed because qdisc-layer on kernels
-+ *                2.6.27 and newer overwrite control buffer. (Jussi Kivilinna)
-+ *              - Add better locking for IMQ device. Hopefully this will solve
-+ *                SMP issues. (Jussi Kivilinna)
-+ *              - Port to 2.6.27
-+ *              - Port to 2.6.28
-+ *              - Port to 2.6.29 + fix rmmod not working
-+ *
-+ *             2009/04/20 - (Jussi Kivilinna)
-+ *              - Use netdevice feature flags to avoid extra packet handling
-+ *                by core networking layer and possibly increase performance.
-+ *
-+ *           Also, many thanks to pablo Sebastian Greco for making the initial
-+ *           patch and to those who helped the testing.
-+ *
-+ *             More info at: http://www.linuximq.net/ (Andre Correa)
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/moduleparam.h>
-+#include <linux/list.h>
-+#include <linux/skbuff.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/rtnetlink.h>
-+#include <linux/if_arp.h>
-+#include <linux/netfilter.h>
-+#include <linux/netfilter_ipv4.h>
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+      #include <linux/netfilter_ipv6.h>
-+#endif
-+#include <linux/imq.h>
-+#include <net/pkt_sched.h>
-+#include <net/netfilter/nf_queue.h>
-+
-+static nf_hookfn imq_nf_hook;
-+
-+static struct nf_hook_ops imq_ingress_ipv4 = {
-+      .hook           = imq_nf_hook,
-+      .owner          = THIS_MODULE,
-+      .pf             = PF_INET,
-+      .hooknum        = NF_INET_PRE_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+      .priority       = NF_IP_PRI_MANGLE + 1
-+#else
-+      .priority       = NF_IP_PRI_NAT_DST + 1
-+#endif
-+};
-+
-+static struct nf_hook_ops imq_egress_ipv4 = {
-+      .hook           = imq_nf_hook,
-+      .owner          = THIS_MODULE,
-+      .pf             = PF_INET,
-+      .hooknum        = NF_INET_POST_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
-+      .priority       = NF_IP_PRI_LAST
-+#else
-+      .priority       = NF_IP_PRI_NAT_SRC - 1
-+#endif
-+};
-+
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+static struct nf_hook_ops imq_ingress_ipv6 = {
-+      .hook           = imq_nf_hook,
-+      .owner          = THIS_MODULE,
-+      .pf             = PF_INET6,
-+      .hooknum        = NF_INET_PRE_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+      .priority       = NF_IP6_PRI_MANGLE + 1
-+#else
-+      .priority       = NF_IP6_PRI_NAT_DST + 1
-+#endif
-+};
-+
-+static struct nf_hook_ops imq_egress_ipv6 = {
-+      .hook           = imq_nf_hook,
-+      .owner          = THIS_MODULE,
-+      .pf             = PF_INET6,
-+      .hooknum        = NF_INET_POST_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
-+      .priority       = NF_IP6_PRI_LAST
-+#else
-+      .priority       = NF_IP6_PRI_NAT_SRC - 1
-+#endif
-+};
-+#endif
-+
-+#if defined(CONFIG_IMQ_NUM_DEVS)
-+static unsigned int numdevs = CONFIG_IMQ_NUM_DEVS;
-+#else
-+static unsigned int numdevs = IMQ_MAX_DEVS;
-+#endif
-+
-+static DEFINE_SPINLOCK(imq_nf_queue_lock);
-+
-+static struct net_device *imq_devs_cache[IMQ_MAX_DEVS];
-+
-+
-+static struct net_device_stats *imq_get_stats(struct net_device *dev)
-+{
-+      return &dev->stats;
-+}
-+
-+/* called for packets kfree'd in qdiscs at places other than enqueue */
-+static void imq_skb_destructor(struct sk_buff *skb)
-+{
-+      struct nf_queue_entry *entry = skb->nf_queue_entry;
-+
-+      if (entry) {
-+              nf_queue_entry_release_refs(entry);
-+              kfree(entry);
-+      }
-+
-+      skb_restore_cb(skb); /* kfree backup */
-+}
-+
-+static void imq_nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
-+{
-+      int status;
-+
-+      if (!entry->next_outfn) {
-+              spin_lock_bh(&imq_nf_queue_lock);
-+              nf_reinject(entry, verdict);
-+              spin_unlock_bh(&imq_nf_queue_lock);
-+              return;
-+      }
-+
-+      rcu_read_lock();
-+      local_bh_disable();
-+      status = entry->next_outfn(entry, entry->next_queuenum);
-+      local_bh_enable();
-+      if (status < 0) {
-+              nf_queue_entry_release_refs(entry);
-+              kfree_skb(entry->skb);
-+              kfree(entry);
-+      }
-+
-+      rcu_read_unlock();
-+}
-+
-+static int imq_dev_xmit(struct sk_buff *skb, struct net_device *dev)
-+{
-+      dev->stats.tx_bytes += skb->len;
-+      dev->stats.tx_packets++;
-+
-+      skb->imq_flags = 0;
-+      skb->destructor = NULL;
-+
-+      skb_restore_cb(skb); /* restore skb->cb */
-+
-+      dev->trans_start = jiffies;
-+      imq_nf_reinject(skb->nf_queue_entry, NF_ACCEPT);
-+      return 0;
-+}
-+
-+static int imq_nf_queue(struct nf_queue_entry *entry, unsigned queue_num)
-+{
-+      struct net_device *dev;
-+      struct sk_buff *skb_orig, *skb, *skb_shared;
-+      struct Qdisc *q;
-+      struct netdev_queue *txq;
-+      int users, index;
-+      int retval = -EINVAL;
-+
-+      index = entry->skb->imq_flags & IMQ_F_IFMASK;
-+      if (unlikely(index > numdevs - 1)) {
-+              if (net_ratelimit())
-+                      printk(KERN_WARNING
-+                             "IMQ: invalid device specified, highest is %u\n",
-+                             numdevs - 1);
-+              retval = -EINVAL;
-+              goto out;
-+      }
-+
-+      /* check for imq device by index from cache */
-+      dev = imq_devs_cache[index];
-+      if (unlikely(!dev)) {
-+              char buf[8];
-+
-+              /* get device by name and cache result */
-+              snprintf(buf, sizeof(buf), "imq%d", index);
-+              dev = dev_get_by_name(&init_net, buf);
-+              if (!dev) {
-+                      /* not found ?!*/
-+                      BUG();
-+                      retval = -ENODEV;
-+                      goto out;
-+              }
-+
-+              imq_devs_cache[index] = dev;
-+              dev_put(dev);
-+      }
-+
-+      if (unlikely(!(dev->flags & IFF_UP))) {
-+              entry->skb->imq_flags = 0;
-+              imq_nf_reinject(entry, NF_ACCEPT);
-+              retval = 0;
-+              goto out;
-+      }
-+      dev->last_rx = jiffies;
-+
-+      skb = entry->skb;
-+      skb_orig = NULL;
-+
-+      /* skb has owner? => make clone */
-+      if (unlikely(skb->destructor)) {
-+              skb_orig = skb;
-+              skb = skb_clone(skb, GFP_ATOMIC);
-+              if (!skb) {
-+                      retval = -ENOMEM;
-+                      goto out;
-+              }
-+              entry->skb = skb;
-+      }
-+
-+      skb->nf_queue_entry = entry;
-+
-+      dev->stats.rx_bytes += skb->len;
-+      dev->stats.rx_packets++;
-+
-+      txq = dev_pick_tx(dev, skb);
-+
-+      q = rcu_dereference(txq->qdisc);
-+      if (unlikely(!q->enqueue))
-+              goto packet_not_eaten_by_imq_dev;
-+
-+      spin_lock_bh(qdisc_lock(q));
-+
-+      users = atomic_read(&skb->users);
-+
-+      skb_shared = skb_get(skb); /* increase reference count by one */
-+      skb_save_cb(skb_shared); /* backup skb->cb, as qdisc layer will
-+                                      overwrite it */
-+      qdisc_enqueue_root(skb_shared, q); /* might kfree_skb */
-+
-+      if (likely(atomic_read(&skb_shared->users) == users + 1)) {
-+              kfree_skb(skb_shared); /* decrease reference count by one */
-+
-+              skb->destructor = &imq_skb_destructor;
-+
-+              /* cloned? */
-+              if (skb_orig)
-+                      kfree_skb(skb_orig); /* free original */
-+
-+              spin_unlock_bh(qdisc_lock(q));
-+
-+              /* schedule qdisc dequeue */
-+              __netif_schedule(q);
-+
-+              retval = 0;
-+              goto out;
-+      } else {
-+              skb_restore_cb(skb_shared); /* restore skb->cb */
-+              /* qdisc dropped packet and decreased skb reference count of
-+               * skb, so we don't really want to and try refree as that would
-+               * actually destroy the skb. */
-+              spin_unlock_bh(qdisc_lock(q));
-+              goto packet_not_eaten_by_imq_dev;
-+      }
-+
-+packet_not_eaten_by_imq_dev:
-+      /* cloned? restore original */
-+      if (skb_orig) {
-+              kfree_skb(skb);
-+              entry->skb = skb_orig;
-+      }
-+      retval = -1;
-+out:
-+      return retval;
-+}
-+
-+static struct nf_queue_handler nfqh = {
-+      .name  = "imq",
-+      .outfn = imq_nf_queue,
-+};
-+
-+static unsigned int imq_nf_hook(unsigned int hook, struct sk_buff *pskb,
-+                              const struct net_device *indev,
-+                              const struct net_device *outdev,
-+                              int (*okfn)(struct sk_buff *))
-+{
-+      if (pskb->imq_flags & IMQ_F_ENQUEUE)
-+              return NF_QUEUE;
-+
-+      return NF_ACCEPT;
-+}
-+
-+static int imq_close(struct net_device *dev)
-+{
-+      netif_stop_queue(dev);
-+      return 0;
-+}
-+
-+static int imq_open(struct net_device *dev)
-+{
-+      netif_start_queue(dev);
-+      return 0;
-+}
-+
-+static const struct net_device_ops imq_netdev_ops = {
-+      .ndo_open               = imq_open,
-+      .ndo_stop               = imq_close,
-+      .ndo_start_xmit         = imq_dev_xmit,
-+      .ndo_get_stats          = imq_get_stats,
-+};
-+
-+static void imq_setup(struct net_device *dev)
-+{
-+      dev->netdev_ops         = &imq_netdev_ops;
-+      dev->type               = ARPHRD_VOID;
-+      dev->mtu                = 16000;
-+      dev->tx_queue_len       = 11000;
-+      dev->flags              = IFF_NOARP;
-+      dev->features           = NETIF_F_SG | NETIF_F_FRAGLIST |
-+                                NETIF_F_GSO | NETIF_F_HW_CSUM |
-+                                NETIF_F_HIGHDMA;
-+}
-+
-+static int imq_validate(struct nlattr *tb[], struct nlattr *data[])
-+{
-+      int ret = 0;
-+
-+      if (tb[IFLA_ADDRESS]) {
-+              if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) {
-+                      ret = -EINVAL;
-+                      goto end;
-+              }
-+              if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) {
-+                      ret = -EADDRNOTAVAIL;
-+                      goto end;
-+              }
-+      }
-+      return 0;
-+end:
-+      printk(KERN_WARNING "IMQ: imq_validate failed (%d)\n", ret);
-+      return ret;
-+}
-+
-+static struct rtnl_link_ops imq_link_ops __read_mostly = {
-+      .kind           = "imq",
-+      .priv_size      = 0,
-+      .setup          = imq_setup,
-+      .validate       = imq_validate,
-+};
-+
-+static int __init imq_init_hooks(void)
-+{
-+      int err;
-+
-+      nf_register_queue_imq_handler(&nfqh);
-+
-+      err = nf_register_hook(&imq_ingress_ipv4);
-+      if (err)
-+              goto err1;
-+
-+      err = nf_register_hook(&imq_egress_ipv4);
-+      if (err)
-+              goto err2;
-+
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+      err = nf_register_hook(&imq_ingress_ipv6);
-+      if (err)
-+              goto err3;
-+
-+      err = nf_register_hook(&imq_egress_ipv6);
-+      if (err)
-+              goto err4;
-+#endif
-+
-+      return 0;
-+
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+err4:
-+      nf_unregister_hook(&imq_ingress_ipv6);
-+err3:
-+      nf_unregister_hook(&imq_egress_ipv4);
-+#endif
-+err2:
-+      nf_unregister_hook(&imq_ingress_ipv4);
-+err1:
-+      nf_unregister_queue_imq_handler();
-+      return err;
-+}
-+
-+static int __init imq_init_one(int index)
-+{
-+      struct net_device *dev;
-+      int ret;
-+
-+      dev = alloc_netdev(0, "imq%d", imq_setup);
-+      if (!dev)
-+              return -ENOMEM;
-+
-+      ret = dev_alloc_name(dev, dev->name);
-+      if (ret < 0)
-+              goto fail;
-+
-+      dev->rtnl_link_ops = &imq_link_ops;
-+      ret = register_netdevice(dev);
-+      if (ret < 0)
-+              goto fail;
-+
-+      return 0;
-+fail:
-+      free_netdev(dev);
-+      return ret;
-+}
-+
-+static int __init imq_init_devs(void)
-+{
-+      int err, i;
-+
-+      if (numdevs < 1 || numdevs > IMQ_MAX_DEVS) {
-+              printk(KERN_ERR "IMQ: numdevs has to be betweed 1 and %u\n",
-+                     IMQ_MAX_DEVS);
-+              return -EINVAL;
-+      }
-+
-+      rtnl_lock();
-+      err = __rtnl_link_register(&imq_link_ops);
-+
-+      for (i = 0; i < numdevs && !err; i++)
-+              err = imq_init_one(i);
-+
-+      if (err) {
-+              __rtnl_link_unregister(&imq_link_ops);
-+              memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
-+      }
-+      rtnl_unlock();
-+
-+      return err;
-+}
-+
-+static int __init imq_init_module(void)
-+{
-+      int err;
-+
-+#if defined(CONFIG_IMQ_NUM_DEVS)
-+      BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS > 16);
-+      BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS < 2);
-+      BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS - 1 > IMQ_F_IFMASK);
-+#endif
-+
-+      err = imq_init_devs();
-+      if (err) {
-+              printk(KERN_ERR "IMQ: Error trying imq_init_devs(net)\n");
-+              return err;
-+      }
-+
-+      err = imq_init_hooks();
-+      if (err) {
-+              printk(KERN_ERR "IMQ: Error trying imq_init_hooks()\n");
-+              rtnl_link_unregister(&imq_link_ops);
-+              memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
-+              return err;
-+      }
-+
-+      printk(KERN_INFO "IMQ driver loaded successfully.\n");
-+
-+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+      printk(KERN_INFO "\tHooking IMQ before NAT on PREROUTING.\n");
-+#else
-+      printk(KERN_INFO "\tHooking IMQ after NAT on PREROUTING.\n");
-+#endif
-+#if defined(CONFIG_IMQ_BEHAVIOR_AB) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+      printk(KERN_INFO "\tHooking IMQ before NAT on POSTROUTING.\n");
-+#else
-+      printk(KERN_INFO "\tHooking IMQ after NAT on POSTROUTING.\n");
-+#endif
-+
-+      return 0;
-+}
-+
-+static void __exit imq_unhook(void)
-+{
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+      nf_unregister_hook(&imq_ingress_ipv6);
-+      nf_unregister_hook(&imq_egress_ipv6);
-+#endif
-+      nf_unregister_hook(&imq_ingress_ipv4);
-+      nf_unregister_hook(&imq_egress_ipv4);
-+
-+      nf_unregister_queue_imq_handler();
-+}
-+
-+static void __exit imq_cleanup_devs(void)
-+{
-+      rtnl_link_unregister(&imq_link_ops);
-+      memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
-+}
-+
-+static void __exit imq_exit_module(void)
-+{
-+      imq_unhook();
-+      imq_cleanup_devs();
-+      printk(KERN_INFO "IMQ driver unloaded successfully.\n");
-+}
-+
-+module_init(imq_init_module);
-+module_exit(imq_exit_module);
-+
-+module_param(numdevs, int, 0);
-+MODULE_PARM_DESC(numdevs, "number of IMQ devices (how many imq* devices will "
-+                      "be created)");
-+MODULE_AUTHOR("http://www.linuximq.net");
-+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See "
-+                      "http://www.linuximq.net/ for more information.");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS_RTNL_LINK("imq");
-+
---- a/drivers/net/Kconfig
-+++ b/drivers/net/Kconfig
-@@ -109,6 +109,129 @@ config EQUALIZER
-         To compile this driver as a module, choose M here: the module
-         will be called eql.  If unsure, say N.
-+config IMQ
-+      tristate "IMQ (intermediate queueing device) support"
-+      depends on NETDEVICES && NETFILTER
-+      ---help---
-+        The IMQ device(s) is used as placeholder for QoS queueing
-+        disciplines. Every packet entering/leaving the IP stack can be
-+        directed through the IMQ device where it's enqueued/dequeued to the
-+        attached qdisc. This allows you to treat network devices as classes
-+        and distribute bandwidth among them. Iptables is used to specify
-+        through which IMQ device, if any, packets travel.
-+
-+        More information at: http://www.linuximq.net/
-+
-+        To compile this driver as a module, choose M here: the module
-+        will be called imq.  If unsure, say N.
-+
-+choice
-+      prompt "IMQ behavior (PRE/POSTROUTING)"
-+      depends on IMQ
-+      default IMQ_BEHAVIOR_AB
-+      help
-+
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              IMQ can work in any of the following ways:
-+
-+                  PREROUTING   |      POSTROUTING
-+              -----------------|-------------------
-+              #1  After NAT    |      After NAT
-+              #2  After NAT    |      Before NAT
-+              #3  Before NAT   |      After NAT
-+              #4  Before NAT   |      Before NAT
-+
-+              The default behavior is to hook before NAT on PREROUTING
-+              and after NAT on POSTROUTING (#3).
-+
-+              This settings are specially usefull when trying to use IMQ
-+              to shape NATed clients.
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_AA
-+      bool "IMQ AA"
-+      help
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              Choosing this option will make IMQ hook like this:
-+
-+              PREROUTING:   After NAT
-+              POSTROUTING:  After NAT
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_AB
-+      bool "IMQ AB"
-+      help
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              Choosing this option will make IMQ hook like this:
-+
-+              PREROUTING:   After NAT
-+              POSTROUTING:  Before NAT
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_BA
-+      bool "IMQ BA"
-+      help
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              Choosing this option will make IMQ hook like this:
-+
-+              PREROUTING:   Before NAT
-+              POSTROUTING:  After NAT
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_BB
-+      bool "IMQ BB"
-+      help
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              Choosing this option will make IMQ hook like this:
-+
-+              PREROUTING:   Before NAT
-+              POSTROUTING:  Before NAT
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+endchoice
-+
-+config IMQ_NUM_DEVS
-+
-+      int "Number of IMQ devices"
-+      range 2 16
-+      depends on IMQ
-+      default "16"
-+      help
-+
-+              This settings defines how many IMQ devices will be
-+              created.
-+
-+              The default value is 16.
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
- config TUN
-       tristate "Universal TUN/TAP device driver support"
-       select CRC32
---- a/drivers/net/Makefile
-+++ b/drivers/net/Makefile
-@@ -160,6 +160,7 @@ obj-$(CONFIG_SLHC) += slhc.o
- obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o
- obj-$(CONFIG_DUMMY) += dummy.o
-+obj-$(CONFIG_IMQ) += imq.o
- obj-$(CONFIG_IFB) += ifb.o
- obj-$(CONFIG_MACVLAN) += macvlan.o
- obj-$(CONFIG_DE600) += de600.o
---- /dev/null
-+++ b/include/linux/imq.h
-@@ -0,0 +1,13 @@
-+#ifndef _IMQ_H
-+#define _IMQ_H
-+
-+/* IFMASK (16 device indexes, 0 to 15) and flag(s) fit in 5 bits */
-+#define IMQ_F_BITS    5
-+
-+#define IMQ_F_IFMASK  0x0f
-+#define IMQ_F_ENQUEUE 0x10
-+
-+#define IMQ_MAX_DEVS  (IMQ_F_IFMASK + 1)
-+
-+#endif /* _IMQ_H */
-+
---- /dev/null
-+++ b/include/linux/netfilter_ipv4/ipt_IMQ.h
-@@ -0,0 +1,10 @@
-+#ifndef _IPT_IMQ_H
-+#define _IPT_IMQ_H
-+
-+/* Backwards compatibility for old userspace */
-+#include <linux/netfilter/xt_IMQ.h>
-+
-+#define ipt_imq_info xt_imq_info
-+
-+#endif /* _IPT_IMQ_H */
-+
---- /dev/null
-+++ b/include/linux/netfilter_ipv6/ip6t_IMQ.h
-@@ -0,0 +1,10 @@
-+#ifndef _IP6T_IMQ_H
-+#define _IP6T_IMQ_H
-+
-+/* Backwards compatibility for old userspace */
-+#include <linux/netfilter/xt_IMQ.h>
-+
-+#define ip6t_imq_info xt_imq_info
-+
-+#endif /* _IP6T_IMQ_H */
-+
---- a/include/linux/skbuff.h
-+++ b/include/linux/skbuff.h
-@@ -29,6 +29,9 @@
- #include <linux/rcupdate.h>
- #include <linux/dmaengine.h>
- #include <linux/hrtimer.h>
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+#include <linux/imq.h>
-+#endif
- /* Don't change this without changing skb_csum_unnecessary! */
- #define CHECKSUM_NONE 0
-@@ -331,6 +334,9 @@ struct sk_buff {
-        * first. This is owned by whoever has the skb queued ATM.
-        */
-       char                    cb[48];
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      void                    *cb_next;
-+#endif
-       unsigned int            len,
-                               data_len;
-@@ -363,6 +369,9 @@ struct sk_buff {
-       struct nf_conntrack     *nfct;
-       struct sk_buff          *nfct_reasm;
- #endif
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      struct nf_queue_entry   *nf_queue_entry;
-+#endif
- #ifdef CONFIG_BRIDGE_NETFILTER
-       struct nf_bridge_info   *nf_bridge;
- #endif
-@@ -386,6 +395,9 @@ struct sk_buff {
-       kmemcheck_bitfield_end(flags2);
-       /* 0/13/14 bit hole */
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      __u8                    imq_flags:IMQ_F_BITS;
-+#endif
- #ifdef CONFIG_NET_DMA
-       dma_cookie_t            dma_cookie;
-@@ -441,6 +453,12 @@ static inline struct rtable *skb_rtable(
-       return (struct rtable *)skb_dst(skb);
- }
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+extern int skb_save_cb(struct sk_buff *skb);
-+extern int skb_restore_cb(struct sk_buff *skb);
-+#endif
-+
- extern void kfree_skb(struct sk_buff *skb);
- extern void consume_skb(struct sk_buff *skb);
- extern void          __kfree_skb(struct sk_buff *skb);
-@@ -1976,6 +1994,10 @@ static inline void __nf_copy(struct sk_b
-       dst->nfct_reasm = src->nfct_reasm;
-       nf_conntrack_get_reasm(src->nfct_reasm);
- #endif
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      dst->imq_flags = src->imq_flags;
-+      dst->nf_queue_entry = src->nf_queue_entry;
-+#endif
- #ifdef CONFIG_BRIDGE_NETFILTER
-       dst->nf_bridge  = src->nf_bridge;
-       nf_bridge_get(src->nf_bridge);
---- a/net/core/dev.c
-+++ b/net/core/dev.c
-@@ -96,6 +96,9 @@
- #include <net/net_namespace.h>
- #include <net/sock.h>
- #include <linux/rtnetlink.h>
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+#include <linux/imq.h>
-+#endif
- #include <linux/proc_fs.h>
- #include <linux/seq_file.h>
- #include <linux/stat.h>
-@@ -1687,7 +1690,11 @@ int dev_hard_start_xmit(struct sk_buff *
-       int rc;
-       if (likely(!skb->next)) {
--              if (!list_empty(&ptype_all))
-+              if (!list_empty(&ptype_all)
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+                  && !(skb->imq_flags & IMQ_F_ENQUEUE)
-+#endif
-+                  )
-                       dev_queue_xmit_nit(skb, dev);
-               if (netif_needs_gso(dev, skb)) {
-@@ -1772,8 +1779,7 @@ u16 skb_tx_hash(const struct net_device
- }
- EXPORT_SYMBOL(skb_tx_hash);
--static struct netdev_queue *dev_pick_tx(struct net_device *dev,
--                                      struct sk_buff *skb)
-+struct netdev_queue *dev_pick_tx(struct net_device *dev, struct sk_buff *skb)
- {
-       const struct net_device_ops *ops = dev->netdev_ops;
-       u16 queue_index = 0;
-@@ -1786,6 +1792,7 @@ static struct netdev_queue *dev_pick_tx(
-       skb_set_queue_mapping(skb, queue_index);
-       return netdev_get_tx_queue(dev, queue_index);
- }
-+EXPORT_SYMBOL(dev_pick_tx);
- /**
-  *    dev_queue_xmit - transmit a buffer
---- a/include/linux/netdevice.h
-+++ b/include/linux/netdevice.h
-@@ -1102,6 +1102,7 @@ extern int               dev_alloc_name(struct net_de
- extern int            dev_open(struct net_device *dev);
- extern int            dev_close(struct net_device *dev);
- extern void           dev_disable_lro(struct net_device *dev);
-+extern struct netdev_queue *dev_pick_tx(struct net_device *dev, struct sk_buff *skb);
- extern int            dev_queue_xmit(struct sk_buff *skb);
- extern int            register_netdevice(struct net_device *dev);
- extern void           unregister_netdevice(struct net_device *dev);
---- /dev/null
-+++ b/include/linux/netfilter/xt_IMQ.h
-@@ -0,0 +1,9 @@
-+#ifndef _XT_IMQ_H
-+#define _XT_IMQ_H
-+
-+struct xt_imq_info {
-+      unsigned int todev;     /* target imq device */
-+};
-+
-+#endif /* _XT_IMQ_H */
-+
---- a/include/net/netfilter/nf_queue.h
-+++ b/include/net/netfilter/nf_queue.h
-@@ -13,6 +13,12 @@ struct nf_queue_entry {
-       struct net_device       *indev;
-       struct net_device       *outdev;
-       int                     (*okfn)(struct sk_buff *);
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      int                     (*next_outfn)(struct nf_queue_entry *entry,
-+                                            unsigned int queuenum);
-+      unsigned int            next_queuenum;
-+#endif
- };
- #define nf_queue_entry_reroute(x) ((void *)x + sizeof(struct nf_queue_entry))
-@@ -30,5 +36,11 @@ extern int nf_unregister_queue_handler(u
-                                      const struct nf_queue_handler *qh);
- extern void nf_unregister_queue_handlers(const struct nf_queue_handler *qh);
- extern void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
-+extern void nf_queue_entry_release_refs(struct nf_queue_entry *entry);
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+extern void nf_register_queue_imq_handler(const struct nf_queue_handler *qh);
-+extern void nf_unregister_queue_imq_handler(void);
-+#endif
- #endif /* _NF_QUEUE_H */
---- a/net/core/skbuff.c
-+++ b/net/core/skbuff.c
-@@ -72,6 +72,9 @@
- static struct kmem_cache *skbuff_head_cache __read_mostly;
- static struct kmem_cache *skbuff_fclone_cache __read_mostly;
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+static struct kmem_cache *skbuff_cb_store_cache __read_mostly;
-+#endif
- static void sock_pipe_buf_release(struct pipe_inode_info *pipe,
-                                 struct pipe_buffer *buf)
-@@ -91,6 +94,80 @@ static int sock_pipe_buf_steal(struct pi
-       return 1;
- }
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+/* Control buffer save/restore for IMQ devices */
-+struct skb_cb_table {
-+      void                    *cb_next;
-+      atomic_t                refcnt;
-+      char                    cb[48];
-+};
-+
-+static DEFINE_SPINLOCK(skb_cb_store_lock);
-+
-+int skb_save_cb(struct sk_buff *skb)
-+{
-+      struct skb_cb_table *next;
-+
-+      next = kmem_cache_alloc(skbuff_cb_store_cache, GFP_ATOMIC);
-+      if (!next)
-+              return -ENOMEM;
-+
-+      BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb));
-+
-+      memcpy(next->cb, skb->cb, sizeof(skb->cb));
-+      next->cb_next = skb->cb_next;
-+
-+      atomic_set(&next->refcnt, 1);
-+
-+      skb->cb_next = next;
-+      return 0;
-+}
-+EXPORT_SYMBOL(skb_save_cb);
-+
-+int skb_restore_cb(struct sk_buff *skb)
-+{
-+      struct skb_cb_table *next;
-+
-+      if (!skb->cb_next)
-+              return 0;
-+
-+      next = skb->cb_next;
-+
-+      BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb));
-+
-+      memcpy(skb->cb, next->cb, sizeof(skb->cb));
-+      skb->cb_next = next->cb_next;
-+
-+      spin_lock(&skb_cb_store_lock);
-+
-+      if (atomic_dec_and_test(&next->refcnt)) {
-+              kmem_cache_free(skbuff_cb_store_cache, next);
-+      }
-+
-+      spin_unlock(&skb_cb_store_lock);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL(skb_restore_cb);
-+
-+static void skb_copy_stored_cb(struct sk_buff *new, struct sk_buff *old)
-+{
-+      struct skb_cb_table *next;
-+
-+      if (!old->cb_next) {
-+              new->cb_next = 0;
-+              return;
-+      }
-+
-+      spin_lock(&skb_cb_store_lock);
-+
-+      next = old->cb_next;
-+      atomic_inc(&next->refcnt);
-+      new->cb_next = next;
-+
-+      spin_unlock(&skb_cb_store_lock);
-+}
-+#endif
- /* Pipe buffer operations for a socket. */
- static struct pipe_buf_operations sock_pipe_buf_ops = {
-@@ -398,6 +475,15 @@ static void skb_release_head_state(struc
-               WARN_ON(in_irq());
-               skb->destructor(skb);
-       }
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      /* This should not happen. When it does, avoid memleak by restoring
-+      the chain of cb-backups. */
-+      while(skb->cb_next != NULL) {
-+              printk(KERN_WARNING "kfree_skb: skb->cb_next: %08x\n",
-+                      skb->cb_next);
-+              skb_restore_cb(skb);
-+      }
-+#endif
- #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
-       nf_conntrack_put(skb->nfct);
-       nf_conntrack_put_reasm(skb->nfct_reasm);
-@@ -535,6 +621,9 @@ static void __copy_skb_header(struct sk_
-       new->sp                 = secpath_get(old->sp);
- #endif
-       memcpy(new->cb, old->cb, sizeof(old->cb));
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+   skb_copy_stored_cb(new, old);
-+#endif
-       new->csum               = old->csum;
-       new->local_df           = old->local_df;
-       new->pkt_type           = old->pkt_type;
-@@ -2779,6 +2868,13 @@ void __init skb_init(void)
-                                               0,
-                                               SLAB_HWCACHE_ALIGN|SLAB_PANIC,
-                                               NULL);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      skbuff_cb_store_cache = kmem_cache_create("skbuff_cb_store_cache",
-+                                                sizeof(struct skb_cb_table),
-+                                                0,
-+                                                SLAB_HWCACHE_ALIGN|SLAB_PANIC,
-+                                                NULL);
-+#endif
- }
- /**
---- a/net/netfilter/Kconfig
-+++ b/net/netfilter/Kconfig
-@@ -396,6 +396,18 @@ config NETFILTER_XT_TARGET_LED
-         For more information on the LEDs available on your system, see
-         Documentation/leds-class.txt
-+config NETFILTER_XT_TARGET_IMQ
-+        tristate '"IMQ" target support'
-+      depends on NETFILTER_XTABLES
-+      depends on IP_NF_MANGLE || IP6_NF_MANGLE
-+      select IMQ
-+      default m if NETFILTER_ADVANCED=n
-+        help
-+          This option adds a `IMQ' target which is used to specify if and
-+          to which imq device packets should get enqueued/dequeued.
-+
-+          To compile it as a module, choose M here.  If unsure, say N.
-+
- config NETFILTER_XT_TARGET_MARK
-       tristate '"MARK" target support'
-       default m if NETFILTER_ADVANCED=n
---- a/net/netfilter/Makefile
-+++ b/net/netfilter/Makefile
-@@ -46,6 +46,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMAR
- obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o
-+obj-$(CONFIG_NETFILTER_XT_TARGET_IMQ) += xt_IMQ.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
---- a/net/netfilter/nf_queue.c
-+++ b/net/netfilter/nf_queue.c
-@@ -20,6 +20,26 @@ static const struct nf_queue_handler *qu
- static DEFINE_MUTEX(queue_handler_mutex);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+static const struct nf_queue_handler *queue_imq_handler;
-+
-+void nf_register_queue_imq_handler(const struct nf_queue_handler *qh)
-+{
-+      mutex_lock(&queue_handler_mutex);
-+      rcu_assign_pointer(queue_imq_handler, qh);
-+      mutex_unlock(&queue_handler_mutex);
-+}
-+EXPORT_SYMBOL(nf_register_queue_imq_handler);
-+
-+void nf_unregister_queue_imq_handler(void)
-+{
-+      mutex_lock(&queue_handler_mutex);
-+      rcu_assign_pointer(queue_imq_handler, NULL);
-+      mutex_unlock(&queue_handler_mutex);
-+}
-+EXPORT_SYMBOL(nf_unregister_queue_imq_handler);
-+#endif
-+
- /* return EBUSY when somebody else is registered, return EEXIST if the
-  * same handler is registered, return 0 in case of success. */
- int nf_register_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh)
-@@ -80,7 +100,7 @@ void nf_unregister_queue_handlers(const
- }
- EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers);
--static void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
-+void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
- {
-       /* Release those devices we held, or Alexey will kill me. */
-       if (entry->indev)
-@@ -100,6 +120,7 @@ static void nf_queue_entry_release_refs(
-       /* Drop reference to owner of hook which queued us. */
-       module_put(entry->elem->owner);
- }
-+EXPORT_SYMBOL_GPL(nf_queue_entry_release_refs);
- /*
-  * Any packet that leaves via this function must come back
-@@ -121,12 +142,26 @@ static int __nf_queue(struct sk_buff *sk
- #endif
-       const struct nf_afinfo *afinfo;
-       const struct nf_queue_handler *qh;
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      const struct nf_queue_handler *qih = NULL;
-+#endif
-       /* QUEUE == DROP if noone is waiting, to be safe. */
-       rcu_read_lock();
-       qh = rcu_dereference(queue_handler[pf]);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+      if (pf == PF_INET || pf == PF_INET6)
-+#else
-+      if (pf == PF_INET)
-+#endif
-+              qih = rcu_dereference(queue_imq_handler);
-+
-+      if (!qh && !qih)
-+#else /* !IMQ */
-       if (!qh)
-+#endif
-               goto err_unlock;
-       afinfo = nf_get_afinfo(pf);
-@@ -145,6 +180,10 @@ static int __nf_queue(struct sk_buff *sk
-               .indev  = indev,
-               .outdev = outdev,
-               .okfn   = okfn,
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+              .next_outfn = qh ? qh->outfn : NULL,
-+              .next_queuenum = queuenum,
-+#endif
-       };
-       /* If it's going away, ignore hook. */
-@@ -170,8 +209,19 @@ static int __nf_queue(struct sk_buff *sk
-       }
- #endif
-       afinfo->saveroute(skb, entry);
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      if (qih) {
-+              status = qih->outfn(entry, queuenum);
-+              goto imq_skip_queue;
-+      }
-+#endif
-+
-       status = qh->outfn(entry, queuenum);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+imq_skip_queue:
-+#endif
-       rcu_read_unlock();
-       if (status < 0) {
---- /dev/null
-+++ b/net/netfilter/xt_IMQ.c
-@@ -0,0 +1,73 @@
-+/*
-+ * This target marks packets to be enqueued to an imq device
-+ */
-+#include <linux/module.h>
-+#include <linux/skbuff.h>
-+#include <linux/netfilter/x_tables.h>
-+#include <linux/netfilter/xt_IMQ.h>
-+#include <linux/imq.h>
-+
-+static unsigned int imq_target(struct sk_buff *pskb,
-+                              const struct xt_target_param *par)
-+{
-+      const struct xt_imq_info *mr = par->targinfo;
-+
-+      pskb->imq_flags = (mr->todev & IMQ_F_IFMASK) | IMQ_F_ENQUEUE;
-+
-+      return XT_CONTINUE;
-+}
-+
-+static bool imq_checkentry(const struct xt_tgchk_param *par)
-+{
-+      struct xt_imq_info *mr = par->targinfo;
-+
-+      if (mr->todev > IMQ_MAX_DEVS - 1) {
-+              printk(KERN_WARNING
-+                     "IMQ: invalid device specified, highest is %u\n",
-+                     IMQ_MAX_DEVS - 1);
-+              return 0;
-+      }
-+
-+      return 1;
-+}
-+
-+static struct xt_target xt_imq_reg[] __read_mostly = {
-+      {
-+              .name           = "IMQ",
-+              .family         = AF_INET,
-+              .checkentry     = imq_checkentry,
-+              .target         = imq_target,
-+              .targetsize     = sizeof(struct xt_imq_info),
-+              .table          = "mangle",
-+              .me             = THIS_MODULE
-+      },
-+      {
-+              .name           = "IMQ",
-+              .family         = AF_INET6,
-+              .checkentry     = imq_checkentry,
-+              .target         = imq_target,
-+              .targetsize     = sizeof(struct xt_imq_info),
-+              .table          = "mangle",
-+              .me             = THIS_MODULE
-+      },
-+};
-+
-+static int __init imq_init(void)
-+{
-+      return xt_register_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg));
-+}
-+
-+static void __exit imq_fini(void)
-+{
-+      xt_unregister_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg));
-+}
-+
-+module_init(imq_init);
-+module_exit(imq_fini);
-+
-+MODULE_AUTHOR("http://www.linuximq.net");
-+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information.");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS("ipt_IMQ");
-+MODULE_ALIAS("ip6t_IMQ");
-+
index 2618fafeb99abea83e2c607d0ca12f6444670fcb..7010d367b8f25449a593d19fbbe4e69f543ecc2c 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/mtd/chips/cfi_cmdset_0002.c
 +++ b/drivers/mtd/chips/cfi_cmdset_0002.c
-@@ -325,6 +325,8 @@ static struct cfi_fixup fixup_table[] =
+@@ -325,6 +325,8 @@ static struct cfi_fixup fixup_table[] = 
  static void cfi_fixup_major_minor(struct cfi_private *cfi,
                                  struct cfi_pri_amdstd *extp)
  {
@@ -9,7 +9,7 @@
        if (cfi->mfr == CFI_MFR_SAMSUNG && cfi->id == 0x257e &&
            extp->MajorVersion == '0')
                extp->MajorVersion = '1';
-@@ -355,6 +357,9 @@ struct mtd_info *cfi_cmdset_0002(struct
+@@ -355,6 +357,9 @@ struct mtd_info *cfi_cmdset_0002(struct 
        mtd->name    = map->name;
        mtd->writesize = 1;
  
@@ -19,7 +19,7 @@
        if (cfi->cfi_mode==CFI_MODE_CFI){
                unsigned char bootloc;
                /*
-@@ -373,16 +378,24 @@ struct mtd_info *cfi_cmdset_0002(struct
+@@ -373,16 +378,24 @@ struct mtd_info *cfi_cmdset_0002(struct 
  
                cfi_fixup_major_minor(cfi, extp);
  
index d53c0c85fc826814fbc768180da787e767f2dc2c..d73b2d1523c4dc060f9bac44fbd644537ccf1b89 100644 (file)
  
  unsigned int vced_count, vcei_count;
  
-@@ -31,8 +32,12 @@ static int show_cpuinfo(struct seq_file
+@@ -31,8 +32,12 @@ static int show_cpuinfo(struct seq_file 
        /*
         * For the first processor also print the system type
         */
index 9880ff0141ae9e7146644751b5bfb6f2ebc6e7d6..dba3b32d807f04b0e184e5e0b9fd5e17261ad340 100644 (file)
@@ -55,7 +55,7 @@
  vesper                        MACH_VESPER             VESPER                  2256
  str9                  MACH_STR9               STR9                    2257
  omap3_wl_ff           MACH_OMAP3_WL_FF        OMAP3_WL_FF             2258
-@@ -2256,7 +2257,7 @@ oratisalog               MACH_ORATISALOG         ORATISALOG
+@@ -2256,7 +2257,7 @@ oratisalog               MACH_ORATISALOG         ORATISALOG      
  oratismadi            MACH_ORATISMADI         ORATISMADI              2269
  oratisot16            MACH_ORATISOT16         ORATISOT16              2270
  oratisdesk            MACH_ORATISDESK         ORATISDESK              2271
  htc_excalibur_s620    MACH_HTC_EXCALIBUR_S620 HTC_EXCALIBUR_S620      2391
  htc_opal              MACH_HTC_OPAL           HTC_OPAL                2392
  touchbook             MACH_TOUCHBOOK          TOUCHBOOK               2393
-@@ -2445,7 +2446,7 @@ siogentoo1               MACH_SIOGENTOO1         SIOGENTOO1
+@@ -2445,7 +2446,7 @@ siogentoo1               MACH_SIOGENTOO1         SIOGENTOO1      
  siogentoo2            MACH_SIOGENTOO2         SIOGENTOO2              2459
  sm3k                  MACH_SM3K               SM3K                    2460
  acer_tempo_f900               MACH_ACER_TEMPO_F900    ACER_TEMPO_F900         2461
index de9c63c357abafaea08a9faaf4e825c76314a722..be7d97fe1203646d5082b42bd10ec9394d19b6a0 100644 (file)
@@ -71,7 +71,7 @@
        depends on NETFILTER_ADVANCED
 --- a/net/netfilter/Makefile
 +++ b/net/netfilter/Makefile
-@@ -89,6 +89,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_RECENT)
+@@ -89,6 +89,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_RECENT) 
  obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o
  obj-$(CONFIG_NETFILTER_XT_MATCH_SOCKET) += xt_socket.o
  obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o
index 04ba7102740d210b3d01355792204da9e867f9e3..a9eb1089f5f206af1793b3897c123bf26bb1b00f 100644 (file)
  
                e = (struct ipt_entry *)(loc_cpu_entry + off);
                if (copy_to_user(userptr + off
-@@ -1001,6 +1041,14 @@ copy_entries_to_user(unsigned int total_
-                       ret = -EFAULT;
+@@ -1002,6 +1042,14 @@ copy_entries_to_user(unsigned int total_
                        goto free_counters;
                }
-+
 +              flags = e->ip.flags & ~IPT_F_NO_DEF_MATCH;
 +              if (copy_to_user(userptr + off
 +                               + offsetof(struct ipt_entry, ip.flags),
 +                      ret = -EFAULT;
 +                      goto free_counters;
 +              }
++
                for (i = sizeof(struct ipt_entry);
                     i < e->target_offset;
+                    i += m->u.match_size) {
diff --git a/target/linux/generic/patches-2.6.32/150-netfilter_imq.patch b/target/linux/generic/patches-2.6.32/150-netfilter_imq.patch
deleted file mode 100644 (file)
index 3b46e25..0000000
+++ /dev/null
@@ -1,1336 +0,0 @@
---- /dev/null
-+++ b/drivers/net/imq.c
-@@ -0,0 +1,632 @@
-+/*
-+ *             Pseudo-driver for the intermediate queue device.
-+ *
-+ *             This program is free software; you can redistribute it and/or
-+ *             modify it under the terms of the GNU General Public License
-+ *             as published by the Free Software Foundation; either version
-+ *             2 of the License, or (at your option) any later version.
-+ *
-+ * Authors:    Patrick McHardy, <kaber@trash.net>
-+ *
-+ *            The first version was written by Martin Devera, <devik@cdi.cz>
-+ *
-+ * Credits:    Jan Rafaj <imq2t@cedric.vabo.cz>
-+ *              - Update patch to 2.4.21
-+ *             Sebastian Strollo <sstrollo@nortelnetworks.com>
-+ *              - Fix "Dead-loop on netdevice imq"-issue
-+ *             Marcel Sebek <sebek64@post.cz>
-+ *              - Update to 2.6.2-rc1
-+ *
-+ *           After some time of inactivity there is a group taking care
-+ *           of IMQ again: http://www.linuximq.net
-+ *
-+ *
-+ *           2004/06/30 - New version of IMQ patch to kernels <=2.6.7
-+ *             including the following changes:
-+ *
-+ *           - Correction of ipv6 support "+"s issue (Hasso Tepper)
-+ *           - Correction of imq_init_devs() issue that resulted in
-+ *           kernel OOPS unloading IMQ as module (Norbert Buchmuller)
-+ *           - Addition of functionality to choose number of IMQ devices
-+ *           during kernel config (Andre Correa)
-+ *           - Addition of functionality to choose how IMQ hooks on
-+ *           PRE and POSTROUTING (after or before NAT) (Andre Correa)
-+ *           - Cosmetic corrections (Norbert Buchmuller) (Andre Correa)
-+ *
-+ *
-+ *             2005/12/16 - IMQ versions between 2.6.7 and 2.6.13 were
-+ *             released with almost no problems. 2.6.14-x was released
-+ *             with some important changes: nfcache was removed; After
-+ *             some weeks of trouble we figured out that some IMQ fields
-+ *             in skb were missing in skbuff.c - skb_clone and copy_skb_header.
-+ *             These functions are correctly patched by this new patch version.
-+ *
-+ *             Thanks for all who helped to figure out all the problems with
-+ *             2.6.14.x: Patrick McHardy, Rune Kock, VeNoMouS, Max CtRiX,
-+ *             Kevin Shanahan, Richard Lucassen, Valery Dachev (hopefully
-+ *             I didn't forget anybody). I apologize again for my lack of time.
-+ *
-+ *
-+ *             2008/06/17 - 2.6.25 - Changed imq.c to use qdisc_run() instead 
-+ *             of qdisc_restart() and moved qdisc_run() to tasklet to avoid
-+ *             recursive locking. New initialization routines to fix 'rmmod' not
-+ *             working anymore. Used code from ifb.c. (Jussi Kivilinna)
-+ *
-+ *             2008/08/06 - 2.6.26 - (JK)
-+ *              - Replaced tasklet with 'netif_schedule()'.
-+ *              - Cleaned up and added comments for imq_nf_queue().
-+ *
-+ *             2009/04/12
-+ *              - Add skb_save_cb/skb_restore_cb helper functions for backuping
-+ *                control buffer. This is needed because qdisc-layer on kernels
-+ *                2.6.27 and newer overwrite control buffer. (Jussi Kivilinna)
-+ *              - Add better locking for IMQ device. Hopefully this will solve
-+ *                SMP issues. (Jussi Kivilinna)
-+ *              - Port to 2.6.27
-+ *              - Port to 2.6.28
-+ *              - Port to 2.6.29 + fix rmmod not working
-+ *
-+ *             2009/04/20 - (Jussi Kivilinna)
-+ *              - Use netdevice feature flags to avoid extra packet handling
-+ *                by core networking layer and possibly increase performance.
-+ *
-+ *             2009/09/26 - (Jussi Kivilinna)
-+ *              - Add imq_nf_reinject_lockless to fix deadlock with
-+ *                imq_nf_queue/imq_nf_reinject.
-+ *
-+ *             2009/12/08 - (Jussi Kivilinna)
-+ *              - Port to 2.6.32
-+ *              - Add check for skb->nf_queue_entry==NULL in imq_dev_xmit()
-+ *              - Also add better error checking for skb->nf_queue_entry usage
-+ *
-+ *           Also, many thanks to pablo Sebastian Greco for making the initial
-+ *           patch and to those who helped the testing.
-+ *
-+ *             More info at: http://www.linuximq.net/ (Andre Correa)
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/moduleparam.h>
-+#include <linux/list.h>
-+#include <linux/skbuff.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/rtnetlink.h>
-+#include <linux/if_arp.h>
-+#include <linux/netfilter.h>
-+#include <linux/netfilter_ipv4.h>
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+      #include <linux/netfilter_ipv6.h>
-+#endif
-+#include <linux/imq.h>
-+#include <net/pkt_sched.h>
-+#include <net/netfilter/nf_queue.h>
-+
-+static nf_hookfn imq_nf_hook;
-+
-+static struct nf_hook_ops imq_ingress_ipv4 = {
-+      .hook           = imq_nf_hook,
-+      .owner          = THIS_MODULE,
-+      .pf             = PF_INET,
-+      .hooknum        = NF_INET_PRE_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+      .priority       = NF_IP_PRI_MANGLE + 1
-+#else
-+      .priority       = NF_IP_PRI_NAT_DST + 1
-+#endif
-+};
-+
-+static struct nf_hook_ops imq_egress_ipv4 = {
-+      .hook           = imq_nf_hook,
-+      .owner          = THIS_MODULE,
-+      .pf             = PF_INET,
-+      .hooknum        = NF_INET_POST_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
-+      .priority       = NF_IP_PRI_LAST
-+#else
-+      .priority       = NF_IP_PRI_NAT_SRC - 1
-+#endif
-+};
-+
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+static struct nf_hook_ops imq_ingress_ipv6 = {
-+      .hook           = imq_nf_hook,
-+      .owner          = THIS_MODULE,
-+      .pf             = PF_INET6,
-+      .hooknum        = NF_INET_PRE_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+      .priority       = NF_IP6_PRI_MANGLE + 1
-+#else
-+      .priority       = NF_IP6_PRI_NAT_DST + 1
-+#endif
-+};
-+
-+static struct nf_hook_ops imq_egress_ipv6 = {
-+      .hook           = imq_nf_hook,
-+      .owner          = THIS_MODULE,
-+      .pf             = PF_INET6,
-+      .hooknum        = NF_INET_POST_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
-+      .priority       = NF_IP6_PRI_LAST
-+#else
-+      .priority       = NF_IP6_PRI_NAT_SRC - 1
-+#endif
-+};
-+#endif
-+
-+#if defined(CONFIG_IMQ_NUM_DEVS)
-+static unsigned int numdevs = CONFIG_IMQ_NUM_DEVS;
-+#else
-+static unsigned int numdevs = IMQ_MAX_DEVS;
-+#endif
-+
-+static DEFINE_SPINLOCK(imq_nf_queue_lock);
-+
-+static struct net_device *imq_devs_cache[IMQ_MAX_DEVS];
-+
-+
-+static struct net_device_stats *imq_get_stats(struct net_device *dev)
-+{
-+      return &dev->stats;
-+}
-+
-+/* called for packets kfree'd in qdiscs at places other than enqueue */
-+static void imq_skb_destructor(struct sk_buff *skb)
-+{
-+      struct nf_queue_entry *entry = skb->nf_queue_entry;
-+
-+      skb->nf_queue_entry = NULL;
-+
-+      if (entry) {
-+              nf_queue_entry_release_refs(entry);
-+              kfree(entry);
-+      }
-+
-+      skb_restore_cb(skb); /* kfree backup */
-+}
-+
-+/* locking not needed when called from imq_nf_queue */
-+static void imq_nf_reinject_lockless(struct nf_queue_entry *entry,
-+                                              unsigned int verdict)
-+{
-+      int status;
-+
-+      if (!entry->next_outfn) {
-+              nf_reinject(entry, verdict);
-+              return;
-+      }
-+
-+      status = entry->next_outfn(entry, entry->next_queuenum);
-+      if (status < 0) {
-+              nf_queue_entry_release_refs(entry);
-+              kfree_skb(entry->skb);
-+              kfree(entry);
-+      }
-+}
-+
-+static void imq_nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
-+{
-+      int status;
-+
-+      if (!entry->next_outfn) {
-+              spin_lock_bh(&imq_nf_queue_lock);
-+              nf_reinject(entry, verdict);
-+              spin_unlock_bh(&imq_nf_queue_lock);
-+              return;
-+      }
-+
-+      rcu_read_lock();
-+      local_bh_disable();
-+      status = entry->next_outfn(entry, entry->next_queuenum);
-+      local_bh_enable();
-+      if (status < 0) {
-+              nf_queue_entry_release_refs(entry);
-+              kfree_skb(entry->skb);
-+              kfree(entry);
-+      }
-+
-+      rcu_read_unlock();
-+}
-+
-+static netdev_tx_t imq_dev_xmit(struct sk_buff *skb, struct net_device *dev)
-+{
-+      struct nf_queue_entry *entry = skb->nf_queue_entry;
-+
-+      skb->nf_queue_entry = NULL;
-+      dev->trans_start = jiffies;
-+
-+      dev->stats.tx_bytes += skb->len;
-+      dev->stats.tx_packets++;
-+
-+      if (entry == NULL) {
-+              /* We don't know what is going on here.. packet is queued for
-+               * imq device, but (probably) not by us.
-+               *
-+               * If this packet was not send here by imq_nf_queue(), then
-+               * skb_save_cb() was not used and skb_free() should not show:
-+               *   WARNING: IMQ: kfree_skb: skb->cb_next:..
-+               * and/or
-+               *   WARNING: IMQ: kfree_skb: skb->nf_queue_entry...
-+               *
-+               * However if this message is shown, then IMQ is somehow broken
-+               * and you should report this to linuximq.net.
-+               */
-+
-+              /* imq_dev_xmit is black hole that eats all packets, report that
-+               * we eat this packet happily and increase dropped counters.
-+               */
-+
-+              dev->stats.tx_dropped++;
-+              dev_kfree_skb(skb);
-+
-+              return NETDEV_TX_OK;
-+      }
-+
-+      skb_restore_cb(skb); /* restore skb->cb */
-+
-+      skb->imq_flags = 0;
-+      skb->destructor = NULL;
-+
-+      imq_nf_reinject(entry, NF_ACCEPT);
-+
-+      return NETDEV_TX_OK;
-+}
-+
-+static int imq_nf_queue(struct nf_queue_entry *entry, unsigned queue_num)
-+{
-+      struct net_device *dev;
-+      struct sk_buff *skb_orig, *skb, *skb_shared;
-+      struct Qdisc *q;
-+      struct netdev_queue *txq;
-+      int users, index;
-+      int retval = -EINVAL;
-+
-+      index = entry->skb->imq_flags & IMQ_F_IFMASK;
-+      if (unlikely(index > numdevs - 1)) {
-+              if (net_ratelimit())
-+                      printk(KERN_WARNING
-+                             "IMQ: invalid device specified, highest is %u\n",
-+                             numdevs - 1);
-+              retval = -EINVAL;
-+              goto out;
-+      }
-+
-+      /* check for imq device by index from cache */
-+      dev = imq_devs_cache[index];
-+      if (unlikely(!dev)) {
-+              char buf[8];
-+
-+              /* get device by name and cache result */
-+              snprintf(buf, sizeof(buf), "imq%d", index);
-+              dev = dev_get_by_name(&init_net, buf);
-+              if (!dev) {
-+                      /* not found ?!*/
-+                      BUG();
-+                      retval = -ENODEV;
-+                      goto out;
-+              }
-+
-+              imq_devs_cache[index] = dev;
-+              dev_put(dev);
-+      }
-+
-+      if (unlikely(!(dev->flags & IFF_UP))) {
-+              entry->skb->imq_flags = 0;
-+              imq_nf_reinject_lockless(entry, NF_ACCEPT);
-+              retval = 0;
-+              goto out;
-+      }
-+      dev->last_rx = jiffies;
-+
-+      skb = entry->skb;
-+      skb_orig = NULL;
-+
-+      /* skb has owner? => make clone */
-+      if (unlikely(skb->destructor)) {
-+              skb_orig = skb;
-+              skb = skb_clone(skb, GFP_ATOMIC);
-+              if (!skb) {
-+                      retval = -ENOMEM;
-+                      goto out;
-+              }
-+              entry->skb = skb;
-+      }
-+
-+      skb->nf_queue_entry = entry;
-+
-+      dev->stats.rx_bytes += skb->len;
-+      dev->stats.rx_packets++;
-+
-+      txq = dev_pick_tx(dev, skb);
-+
-+      q = rcu_dereference(txq->qdisc);
-+      if (unlikely(!q->enqueue))
-+              goto packet_not_eaten_by_imq_dev;
-+
-+      spin_lock_bh(qdisc_lock(q));
-+
-+      users = atomic_read(&skb->users);
-+
-+      skb_shared = skb_get(skb); /* increase reference count by one */
-+      skb_save_cb(skb_shared); /* backup skb->cb, as qdisc layer will
-+                                      overwrite it */
-+      qdisc_enqueue_root(skb_shared, q); /* might kfree_skb */
-+
-+      if (likely(atomic_read(&skb_shared->users) == users + 1)) {
-+              kfree_skb(skb_shared); /* decrease reference count by one */
-+
-+              skb->destructor = &imq_skb_destructor;
-+
-+              /* cloned? */
-+              if (skb_orig)
-+                      kfree_skb(skb_orig); /* free original */
-+
-+              spin_unlock_bh(qdisc_lock(q));
-+
-+              /* schedule qdisc dequeue */
-+              __netif_schedule(q);
-+
-+              retval = 0;
-+              goto out;
-+      } else {
-+              skb_restore_cb(skb_shared); /* restore skb->cb */
-+              skb->nf_queue_entry = NULL;
-+              /* qdisc dropped packet and decreased skb reference count of
-+               * skb, so we don't really want to and try refree as that would
-+               * actually destroy the skb. */
-+              spin_unlock_bh(qdisc_lock(q));
-+              goto packet_not_eaten_by_imq_dev;
-+      }
-+
-+packet_not_eaten_by_imq_dev:
-+      /* cloned? restore original */
-+      if (skb_orig) {
-+              kfree_skb(skb);
-+              entry->skb = skb_orig;
-+      }
-+      retval = -1;
-+out:
-+      return retval;
-+}
-+
-+static struct nf_queue_handler nfqh = {
-+      .name  = "imq",
-+      .outfn = imq_nf_queue,
-+};
-+
-+static unsigned int imq_nf_hook(unsigned int hook, struct sk_buff *pskb,
-+                              const struct net_device *indev,
-+                              const struct net_device *outdev,
-+                              int (*okfn)(struct sk_buff *))
-+{
-+      if (pskb->imq_flags & IMQ_F_ENQUEUE)
-+              return NF_QUEUE;
-+
-+      return NF_ACCEPT;
-+}
-+
-+static int imq_close(struct net_device *dev)
-+{
-+      netif_stop_queue(dev);
-+      return 0;
-+}
-+
-+static int imq_open(struct net_device *dev)
-+{
-+      netif_start_queue(dev);
-+      return 0;
-+}
-+
-+static const struct net_device_ops imq_netdev_ops = {
-+      .ndo_open               = imq_open,
-+      .ndo_stop               = imq_close,
-+      .ndo_start_xmit         = imq_dev_xmit,
-+      .ndo_get_stats          = imq_get_stats,
-+};
-+
-+static void imq_setup(struct net_device *dev)
-+{
-+      dev->netdev_ops         = &imq_netdev_ops;
-+      dev->type               = ARPHRD_VOID;
-+      dev->mtu                = 16000;
-+      dev->tx_queue_len       = 11000;
-+      dev->flags              = IFF_NOARP;
-+      dev->features           = NETIF_F_SG | NETIF_F_FRAGLIST |
-+                                NETIF_F_GSO | NETIF_F_HW_CSUM |
-+                                NETIF_F_HIGHDMA;
-+      dev->priv_flags         &= ~IFF_XMIT_DST_RELEASE;
-+}
-+
-+static int imq_validate(struct nlattr *tb[], struct nlattr *data[])
-+{
-+      int ret = 0;
-+
-+      if (tb[IFLA_ADDRESS]) {
-+              if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) {
-+                      ret = -EINVAL;
-+                      goto end;
-+              }
-+              if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) {
-+                      ret = -EADDRNOTAVAIL;
-+                      goto end;
-+              }
-+      }
-+      return 0;
-+end:
-+      printk(KERN_WARNING "IMQ: imq_validate failed (%d)\n", ret);
-+      return ret;
-+}
-+
-+static struct rtnl_link_ops imq_link_ops __read_mostly = {
-+      .kind           = "imq",
-+      .priv_size      = 0,
-+      .setup          = imq_setup,
-+      .validate       = imq_validate,
-+};
-+
-+static int __init imq_init_hooks(void)
-+{
-+      int err;
-+
-+      nf_register_queue_imq_handler(&nfqh);
-+
-+      err = nf_register_hook(&imq_ingress_ipv4);
-+      if (err)
-+              goto err1;
-+
-+      err = nf_register_hook(&imq_egress_ipv4);
-+      if (err)
-+              goto err2;
-+
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+      err = nf_register_hook(&imq_ingress_ipv6);
-+      if (err)
-+              goto err3;
-+
-+      err = nf_register_hook(&imq_egress_ipv6);
-+      if (err)
-+              goto err4;
-+#endif
-+
-+      return 0;
-+
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+err4:
-+      nf_unregister_hook(&imq_ingress_ipv6);
-+err3:
-+      nf_unregister_hook(&imq_egress_ipv4);
-+#endif
-+err2:
-+      nf_unregister_hook(&imq_ingress_ipv4);
-+err1:
-+      nf_unregister_queue_imq_handler();
-+      return err;
-+}
-+
-+static int __init imq_init_one(int index)
-+{
-+      struct net_device *dev;
-+      int ret;
-+
-+      dev = alloc_netdev(0, "imq%d", imq_setup);
-+      if (!dev)
-+              return -ENOMEM;
-+
-+      ret = dev_alloc_name(dev, dev->name);
-+      if (ret < 0)
-+              goto fail;
-+
-+      dev->rtnl_link_ops = &imq_link_ops;
-+      ret = register_netdevice(dev);
-+      if (ret < 0)
-+              goto fail;
-+
-+      return 0;
-+fail:
-+      free_netdev(dev);
-+      return ret;
-+}
-+
-+static int __init imq_init_devs(void)
-+{
-+      int err, i;
-+
-+      if (numdevs < 1 || numdevs > IMQ_MAX_DEVS) {
-+              printk(KERN_ERR "IMQ: numdevs has to be betweed 1 and %u\n",
-+                     IMQ_MAX_DEVS);
-+              return -EINVAL;
-+      }
-+
-+      rtnl_lock();
-+      err = __rtnl_link_register(&imq_link_ops);
-+
-+      for (i = 0; i < numdevs && !err; i++)
-+              err = imq_init_one(i);
-+
-+      if (err) {
-+              __rtnl_link_unregister(&imq_link_ops);
-+              memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
-+      }
-+      rtnl_unlock();
-+
-+      return err;
-+}
-+
-+static int __init imq_init_module(void)
-+{
-+      int err;
-+
-+#if defined(CONFIG_IMQ_NUM_DEVS)
-+      BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS > 16);
-+      BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS < 2);
-+      BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS - 1 > IMQ_F_IFMASK);
-+#endif
-+
-+      err = imq_init_devs();
-+      if (err) {
-+              printk(KERN_ERR "IMQ: Error trying imq_init_devs(net)\n");
-+              return err;
-+      }
-+
-+      err = imq_init_hooks();
-+      if (err) {
-+              printk(KERN_ERR "IMQ: Error trying imq_init_hooks()\n");
-+              rtnl_link_unregister(&imq_link_ops);
-+              memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
-+              return err;
-+      }
-+
-+      printk(KERN_INFO "IMQ driver loaded successfully.\n");
-+
-+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+      printk(KERN_INFO "\tHooking IMQ before NAT on PREROUTING.\n");
-+#else
-+      printk(KERN_INFO "\tHooking IMQ after NAT on PREROUTING.\n");
-+#endif
-+#if defined(CONFIG_IMQ_BEHAVIOR_AB) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+      printk(KERN_INFO "\tHooking IMQ before NAT on POSTROUTING.\n");
-+#else
-+      printk(KERN_INFO "\tHooking IMQ after NAT on POSTROUTING.\n");
-+#endif
-+
-+      return 0;
-+}
-+
-+static void __exit imq_unhook(void)
-+{
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+      nf_unregister_hook(&imq_ingress_ipv6);
-+      nf_unregister_hook(&imq_egress_ipv6);
-+#endif
-+      nf_unregister_hook(&imq_ingress_ipv4);
-+      nf_unregister_hook(&imq_egress_ipv4);
-+
-+      nf_unregister_queue_imq_handler();
-+}
-+
-+static void __exit imq_cleanup_devs(void)
-+{
-+      rtnl_link_unregister(&imq_link_ops);
-+      memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
-+}
-+
-+static void __exit imq_exit_module(void)
-+{
-+      imq_unhook();
-+      imq_cleanup_devs();
-+      printk(KERN_INFO "IMQ driver unloaded successfully.\n");
-+}
-+
-+module_init(imq_init_module);
-+module_exit(imq_exit_module);
-+
-+module_param(numdevs, int, 0);
-+MODULE_PARM_DESC(numdevs, "number of IMQ devices (how many imq* devices will "
-+                      "be created)");
-+MODULE_AUTHOR("http://www.linuximq.net");
-+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See "
-+                      "http://www.linuximq.net/ for more information.");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS_RTNL_LINK("imq");
-+
---- a/drivers/net/Kconfig
-+++ b/drivers/net/Kconfig
-@@ -109,6 +109,129 @@ config EQUALIZER
-         To compile this driver as a module, choose M here: the module
-         will be called eql.  If unsure, say N.
-+config IMQ
-+      tristate "IMQ (intermediate queueing device) support"
-+      depends on NETDEVICES && NETFILTER
-+      ---help---
-+        The IMQ device(s) is used as placeholder for QoS queueing
-+        disciplines. Every packet entering/leaving the IP stack can be
-+        directed through the IMQ device where it's enqueued/dequeued to the
-+        attached qdisc. This allows you to treat network devices as classes
-+        and distribute bandwidth among them. Iptables is used to specify
-+        through which IMQ device, if any, packets travel.
-+
-+        More information at: http://www.linuximq.net/
-+
-+        To compile this driver as a module, choose M here: the module
-+        will be called imq.  If unsure, say N.
-+
-+choice
-+      prompt "IMQ behavior (PRE/POSTROUTING)"
-+      depends on IMQ
-+      default IMQ_BEHAVIOR_AB
-+      help
-+
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              IMQ can work in any of the following ways:
-+
-+                  PREROUTING   |      POSTROUTING
-+              -----------------|-------------------
-+              #1  After NAT    |      After NAT
-+              #2  After NAT    |      Before NAT
-+              #3  Before NAT   |      After NAT
-+              #4  Before NAT   |      Before NAT
-+
-+              The default behavior is to hook before NAT on PREROUTING
-+              and after NAT on POSTROUTING (#3).
-+
-+              This settings are specially usefull when trying to use IMQ
-+              to shape NATed clients.
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_AA
-+      bool "IMQ AA"
-+      help
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              Choosing this option will make IMQ hook like this:
-+
-+              PREROUTING:   After NAT
-+              POSTROUTING:  After NAT
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_AB
-+      bool "IMQ AB"
-+      help
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              Choosing this option will make IMQ hook like this:
-+
-+              PREROUTING:   After NAT
-+              POSTROUTING:  Before NAT
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_BA
-+      bool "IMQ BA"
-+      help
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              Choosing this option will make IMQ hook like this:
-+
-+              PREROUTING:   Before NAT
-+              POSTROUTING:  After NAT
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_BB
-+      bool "IMQ BB"
-+      help
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              Choosing this option will make IMQ hook like this:
-+
-+              PREROUTING:   Before NAT
-+              POSTROUTING:  Before NAT
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+endchoice
-+
-+config IMQ_NUM_DEVS
-+
-+      int "Number of IMQ devices"
-+      range 2 16
-+      depends on IMQ
-+      default "16"
-+      help
-+
-+              This settings defines how many IMQ devices will be
-+              created.
-+
-+              The default value is 16.
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
- config TUN
-       tristate "Universal TUN/TAP device driver support"
-       select CRC32
---- a/drivers/net/Makefile
-+++ b/drivers/net/Makefile
-@@ -165,6 +165,7 @@ obj-$(CONFIG_SLHC) += slhc.o
- obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o
- obj-$(CONFIG_DUMMY) += dummy.o
-+obj-$(CONFIG_IMQ) += imq.o
- obj-$(CONFIG_IFB) += ifb.o
- obj-$(CONFIG_MACVLAN) += macvlan.o
- obj-$(CONFIG_DE600) += de600.o
---- /dev/null
-+++ b/include/linux/imq.h
-@@ -0,0 +1,13 @@
-+#ifndef _IMQ_H
-+#define _IMQ_H
-+
-+/* IFMASK (16 device indexes, 0 to 15) and flag(s) fit in 5 bits */
-+#define IMQ_F_BITS    5
-+
-+#define IMQ_F_IFMASK  0x0f
-+#define IMQ_F_ENQUEUE 0x10
-+
-+#define IMQ_MAX_DEVS  (IMQ_F_IFMASK + 1)
-+
-+#endif /* _IMQ_H */
-+
---- a/include/linux/netdevice.h
-+++ b/include/linux/netdevice.h
-@@ -1114,6 +1114,7 @@ extern int               dev_alloc_name(struct net_de
- extern int            dev_open(struct net_device *dev);
- extern int            dev_close(struct net_device *dev);
- extern void           dev_disable_lro(struct net_device *dev);
-+extern struct netdev_queue *dev_pick_tx(struct net_device *dev, struct sk_buff *skb);
- extern int            dev_queue_xmit(struct sk_buff *skb);
- extern int            register_netdevice(struct net_device *dev);
- extern void           unregister_netdevice(struct net_device *dev);
---- /dev/null
-+++ b/include/linux/netfilter/xt_IMQ.h
-@@ -0,0 +1,9 @@
-+#ifndef _XT_IMQ_H
-+#define _XT_IMQ_H
-+
-+struct xt_imq_info {
-+      unsigned int todev;     /* target imq device */
-+};
-+
-+#endif /* _XT_IMQ_H */
-+
---- /dev/null
-+++ b/include/linux/netfilter_ipv4/ipt_IMQ.h
-@@ -0,0 +1,10 @@
-+#ifndef _IPT_IMQ_H
-+#define _IPT_IMQ_H
-+
-+/* Backwards compatibility for old userspace */
-+#include <linux/netfilter/xt_IMQ.h>
-+
-+#define ipt_imq_info xt_imq_info
-+
-+#endif /* _IPT_IMQ_H */
-+
---- /dev/null
-+++ b/include/linux/netfilter_ipv6/ip6t_IMQ.h
-@@ -0,0 +1,10 @@
-+#ifndef _IP6T_IMQ_H
-+#define _IP6T_IMQ_H
-+
-+/* Backwards compatibility for old userspace */
-+#include <linux/netfilter/xt_IMQ.h>
-+
-+#define ip6t_imq_info xt_imq_info
-+
-+#endif /* _IP6T_IMQ_H */
-+
---- a/include/linux/skbuff.h
-+++ b/include/linux/skbuff.h
-@@ -29,6 +29,9 @@
- #include <linux/rcupdate.h>
- #include <linux/dmaengine.h>
- #include <linux/hrtimer.h>
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+#include <linux/imq.h>
-+#endif
- /* Don't change this without changing skb_csum_unnecessary! */
- #define CHECKSUM_NONE 0
-@@ -330,6 +333,9 @@ struct sk_buff {
-        * first. This is owned by whoever has the skb queued ATM.
-        */
-       char                    cb[48];
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      void                    *cb_next;
-+#endif
-       unsigned int            len,
-                               data_len;
-@@ -362,6 +368,9 @@ struct sk_buff {
-       struct nf_conntrack     *nfct;
-       struct sk_buff          *nfct_reasm;
- #endif
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      struct nf_queue_entry   *nf_queue_entry;
-+#endif
- #ifdef CONFIG_BRIDGE_NETFILTER
-       struct nf_bridge_info   *nf_bridge;
- #endif
-@@ -383,6 +392,10 @@ struct sk_buff {
-       /* 0/14 bit hole */
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      __u8                    imq_flags:IMQ_F_BITS;
-+#endif
-+
- #ifdef CONFIG_NET_DMA
-       dma_cookie_t            dma_cookie;
- #endif
-@@ -437,6 +450,12 @@ static inline struct rtable *skb_rtable(
-       return (struct rtable *)skb_dst(skb);
- }
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+extern int skb_save_cb(struct sk_buff *skb);
-+extern int skb_restore_cb(struct sk_buff *skb);
-+#endif
-+
- extern void kfree_skb(struct sk_buff *skb);
- extern void consume_skb(struct sk_buff *skb);
- extern void          __kfree_skb(struct sk_buff *skb);
-@@ -1972,6 +1991,10 @@ static inline void __nf_copy(struct sk_b
-       dst->nfct_reasm = src->nfct_reasm;
-       nf_conntrack_get_reasm(src->nfct_reasm);
- #endif
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      dst->imq_flags = src->imq_flags;
-+      dst->nf_queue_entry = src->nf_queue_entry;
-+#endif
- #ifdef CONFIG_BRIDGE_NETFILTER
-       dst->nf_bridge  = src->nf_bridge;
-       nf_bridge_get(src->nf_bridge);
---- a/include/net/netfilter/nf_queue.h
-+++ b/include/net/netfilter/nf_queue.h
-@@ -13,6 +13,12 @@ struct nf_queue_entry {
-       struct net_device       *indev;
-       struct net_device       *outdev;
-       int                     (*okfn)(struct sk_buff *);
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      int                     (*next_outfn)(struct nf_queue_entry *entry,
-+                                            unsigned int queuenum);
-+      unsigned int            next_queuenum;
-+#endif
- };
- #define nf_queue_entry_reroute(x) ((void *)x + sizeof(struct nf_queue_entry))
-@@ -30,5 +36,11 @@ extern int nf_unregister_queue_handler(u
-                                      const struct nf_queue_handler *qh);
- extern void nf_unregister_queue_handlers(const struct nf_queue_handler *qh);
- extern void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
-+extern void nf_queue_entry_release_refs(struct nf_queue_entry *entry);
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+extern void nf_register_queue_imq_handler(const struct nf_queue_handler *qh);
-+extern void nf_unregister_queue_imq_handler(void);
-+#endif
- #endif /* _NF_QUEUE_H */
---- a/net/core/dev.c
-+++ b/net/core/dev.c
-@@ -96,6 +96,9 @@
- #include <net/net_namespace.h>
- #include <net/sock.h>
- #include <linux/rtnetlink.h>
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+#include <linux/imq.h>
-+#endif
- #include <linux/proc_fs.h>
- #include <linux/seq_file.h>
- #include <linux/stat.h>
-@@ -1704,7 +1707,11 @@ int dev_hard_start_xmit(struct sk_buff *
-       int rc;
-       if (likely(!skb->next)) {
--              if (!list_empty(&ptype_all))
-+              if (!list_empty(&ptype_all)
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+                  && !(skb->imq_flags & IMQ_F_ENQUEUE)
-+#endif
-+                  )
-                       dev_queue_xmit_nit(skb, dev);
-               if (netif_needs_gso(dev, skb)) {
-@@ -1797,8 +1804,7 @@ u16 skb_tx_hash(const struct net_device
- }
- EXPORT_SYMBOL(skb_tx_hash);
--static struct netdev_queue *dev_pick_tx(struct net_device *dev,
--                                      struct sk_buff *skb)
-+struct netdev_queue *dev_pick_tx(struct net_device *dev, struct sk_buff *skb)
- {
-       const struct net_device_ops *ops = dev->netdev_ops;
-       u16 queue_index = 0;
-@@ -1811,6 +1817,7 @@ static struct netdev_queue *dev_pick_tx(
-       skb_set_queue_mapping(skb, queue_index);
-       return netdev_get_tx_queue(dev, queue_index);
- }
-+EXPORT_SYMBOL(dev_pick_tx);
- static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
-                                struct net_device *dev,
---- a/net/core/skbuff.c
-+++ b/net/core/skbuff.c
-@@ -72,6 +72,9 @@
- static struct kmem_cache *skbuff_head_cache __read_mostly;
- static struct kmem_cache *skbuff_fclone_cache __read_mostly;
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+static struct kmem_cache *skbuff_cb_store_cache __read_mostly;
-+#endif
- static void sock_pipe_buf_release(struct pipe_inode_info *pipe,
-                                 struct pipe_buffer *buf)
-@@ -91,6 +94,83 @@ static int sock_pipe_buf_steal(struct pi
-       return 1;
- }
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+/* Control buffer save/restore for IMQ devices */
-+struct skb_cb_table {
-+      void                    *cb_next;
-+      atomic_t                refcnt;
-+      char                    cb[48];
-+};
-+
-+static DEFINE_SPINLOCK(skb_cb_store_lock);
-+
-+int skb_save_cb(struct sk_buff *skb)
-+{
-+      struct skb_cb_table *next;
-+
-+      next = kmem_cache_alloc(skbuff_cb_store_cache, GFP_ATOMIC);
-+      if (!next)
-+              return -ENOMEM;
-+
-+      BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb));
-+
-+      memcpy(next->cb, skb->cb, sizeof(skb->cb));
-+      next->cb_next = skb->cb_next;
-+
-+      atomic_set(&next->refcnt, 1);
-+
-+      skb->cb_next = next;
-+      return 0;
-+}
-+EXPORT_SYMBOL(skb_save_cb);
-+
-+int skb_restore_cb(struct sk_buff *skb)
-+{
-+      struct skb_cb_table *next;
-+
-+      if (!skb->cb_next)
-+              return 0;
-+
-+      next = skb->cb_next;
-+
-+      BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb));
-+
-+      memcpy(skb->cb, next->cb, sizeof(skb->cb));
-+      skb->cb_next = next->cb_next;
-+
-+      spin_lock(&skb_cb_store_lock);
-+
-+      if (atomic_dec_and_test(&next->refcnt)) {
-+              kmem_cache_free(skbuff_cb_store_cache, next);
-+      }
-+
-+      spin_unlock(&skb_cb_store_lock);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL(skb_restore_cb);
-+
-+static void skb_copy_stored_cb(struct sk_buff *new, const struct sk_buff *__old)
-+{
-+      struct skb_cb_table *next;
-+      struct sk_buff *old;
-+
-+      if (!__old->cb_next) {
-+              new->cb_next = NULL;
-+              return;
-+      }
-+
-+      spin_lock(&skb_cb_store_lock);
-+
-+      old = (struct sk_buff *)__old;
-+
-+      next = old->cb_next;
-+      atomic_inc(&next->refcnt);
-+      new->cb_next = next;
-+
-+      spin_unlock(&skb_cb_store_lock);
-+}
-+#endif
- /* Pipe buffer operations for a socket. */
- static struct pipe_buf_operations sock_pipe_buf_ops = {
-@@ -398,6 +478,26 @@ static void skb_release_head_state(struc
-               WARN_ON(in_irq());
-               skb->destructor(skb);
-       }
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      /* This should not happen. When it does, avoid memleak by restoring
-+      the chain of cb-backups. */
-+      while(skb->cb_next != NULL) {
-+              if (net_ratelimit())
-+                      printk(KERN_WARNING "IMQ: kfree_skb: skb->cb_next: "
-+                              "%08x\n", (unsigned int)skb->cb_next);
-+
-+              skb_restore_cb(skb);
-+      }
-+      /* This should not happen either, nf_queue_entry is nullified in
-+       * imq_dev_xmit(). If we have non-NULL nf_queue_entry then we are
-+       * leaking entry pointers, maybe memory. We don't know if this is
-+       * pointer to already freed memory, or should this be freed.
-+       * If this happens we need to add refcounting, etc for nf_queue_entry.
-+       */
-+      if (skb->nf_queue_entry && net_ratelimit())
-+              printk(KERN_WARNING
-+                              "IMQ: kfree_skb: skb->nf_queue_entry != NULL");
-+#endif
- #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
-       nf_conntrack_put(skb->nfct);
-       nf_conntrack_put_reasm(skb->nfct_reasm);
-@@ -535,6 +635,9 @@ static void __copy_skb_header(struct sk_
-       new->sp                 = secpath_get(old->sp);
- #endif
-       memcpy(new->cb, old->cb, sizeof(old->cb));
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      skb_copy_stored_cb(new, old);
-+#endif
-       new->csum               = old->csum;
-       new->local_df           = old->local_df;
-       new->pkt_type           = old->pkt_type;
-@@ -2781,6 +2884,13 @@ void __init skb_init(void)
-                                               0,
-                                               SLAB_HWCACHE_ALIGN|SLAB_PANIC,
-                                               NULL);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      skbuff_cb_store_cache = kmem_cache_create("skbuff_cb_store_cache",
-+                                                sizeof(struct skb_cb_table),
-+                                                0,
-+                                                SLAB_HWCACHE_ALIGN|SLAB_PANIC,
-+                                                NULL);
-+#endif
- }
- /**
---- a/net/netfilter/Kconfig
-+++ b/net/netfilter/Kconfig
-@@ -396,6 +396,18 @@ config NETFILTER_XT_TARGET_LED
-         For more information on the LEDs available on your system, see
-         Documentation/leds-class.txt
-+config NETFILTER_XT_TARGET_IMQ
-+        tristate '"IMQ" target support'
-+      depends on NETFILTER_XTABLES
-+      depends on IP_NF_MANGLE || IP6_NF_MANGLE
-+      select IMQ
-+      default m if NETFILTER_ADVANCED=n
-+        help
-+          This option adds a `IMQ' target which is used to specify if and
-+          to which imq device packets should get enqueued/dequeued.
-+
-+          To compile it as a module, choose M here.  If unsure, say N.
-+
- config NETFILTER_XT_TARGET_MARK
-       tristate '"MARK" target support'
-       default m if NETFILTER_ADVANCED=n
---- a/net/netfilter/Makefile
-+++ b/net/netfilter/Makefile
-@@ -46,6 +46,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMAR
- obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o
-+obj-$(CONFIG_NETFILTER_XT_TARGET_IMQ) += xt_IMQ.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
---- a/net/netfilter/nf_queue.c
-+++ b/net/netfilter/nf_queue.c
-@@ -20,6 +20,26 @@ static const struct nf_queue_handler *qu
- static DEFINE_MUTEX(queue_handler_mutex);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+static const struct nf_queue_handler *queue_imq_handler;
-+
-+void nf_register_queue_imq_handler(const struct nf_queue_handler *qh)
-+{
-+      mutex_lock(&queue_handler_mutex);
-+      rcu_assign_pointer(queue_imq_handler, qh);
-+      mutex_unlock(&queue_handler_mutex);
-+}
-+EXPORT_SYMBOL(nf_register_queue_imq_handler);
-+
-+void nf_unregister_queue_imq_handler(void)
-+{
-+      mutex_lock(&queue_handler_mutex);
-+      rcu_assign_pointer(queue_imq_handler, NULL);
-+      mutex_unlock(&queue_handler_mutex);
-+}
-+EXPORT_SYMBOL(nf_unregister_queue_imq_handler);
-+#endif
-+
- /* return EBUSY when somebody else is registered, return EEXIST if the
-  * same handler is registered, return 0 in case of success. */
- int nf_register_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh)
-@@ -80,7 +100,7 @@ void nf_unregister_queue_handlers(const
- }
- EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers);
--static void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
-+void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
- {
-       /* Release those devices we held, or Alexey will kill me. */
-       if (entry->indev)
-@@ -100,6 +120,7 @@ static void nf_queue_entry_release_refs(
-       /* Drop reference to owner of hook which queued us. */
-       module_put(entry->elem->owner);
- }
-+EXPORT_SYMBOL_GPL(nf_queue_entry_release_refs);
- /*
-  * Any packet that leaves via this function must come back
-@@ -121,12 +142,26 @@ static int __nf_queue(struct sk_buff *sk
- #endif
-       const struct nf_afinfo *afinfo;
-       const struct nf_queue_handler *qh;
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      const struct nf_queue_handler *qih = NULL;
-+#endif
-       /* QUEUE == DROP if noone is waiting, to be safe. */
-       rcu_read_lock();
-       qh = rcu_dereference(queue_handler[pf]);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+      if (pf == PF_INET || pf == PF_INET6)
-+#else
-+      if (pf == PF_INET)
-+#endif
-+              qih = rcu_dereference(queue_imq_handler);
-+
-+      if (!qh && !qih)
-+#else /* !IMQ */
-       if (!qh)
-+#endif
-               goto err_unlock;
-       afinfo = nf_get_afinfo(pf);
-@@ -145,6 +180,10 @@ static int __nf_queue(struct sk_buff *sk
-               .indev  = indev,
-               .outdev = outdev,
-               .okfn   = okfn,
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+              .next_outfn = qh ? qh->outfn : NULL,
-+              .next_queuenum = queuenum,
-+#endif
-       };
-       /* If it's going away, ignore hook. */
-@@ -170,8 +209,19 @@ static int __nf_queue(struct sk_buff *sk
-       }
- #endif
-       afinfo->saveroute(skb, entry);
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      if (qih) {
-+              status = qih->outfn(entry, queuenum);
-+              goto imq_skip_queue;
-+      }
-+#endif
-+
-       status = qh->outfn(entry, queuenum);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+imq_skip_queue:
-+#endif
-       rcu_read_unlock();
-       if (status < 0) {
---- /dev/null
-+++ b/net/netfilter/xt_IMQ.c
-@@ -0,0 +1,73 @@
-+/*
-+ * This target marks packets to be enqueued to an imq device
-+ */
-+#include <linux/module.h>
-+#include <linux/skbuff.h>
-+#include <linux/netfilter/x_tables.h>
-+#include <linux/netfilter/xt_IMQ.h>
-+#include <linux/imq.h>
-+
-+static unsigned int imq_target(struct sk_buff *pskb,
-+                              const struct xt_target_param *par)
-+{
-+      const struct xt_imq_info *mr = par->targinfo;
-+
-+      pskb->imq_flags = (mr->todev & IMQ_F_IFMASK) | IMQ_F_ENQUEUE;
-+
-+      return XT_CONTINUE;
-+}
-+
-+static bool imq_checkentry(const struct xt_tgchk_param *par)
-+{
-+      struct xt_imq_info *mr = par->targinfo;
-+
-+      if (mr->todev > IMQ_MAX_DEVS - 1) {
-+              printk(KERN_WARNING
-+                     "IMQ: invalid device specified, highest is %u\n",
-+                     IMQ_MAX_DEVS - 1);
-+              return 0;
-+      }
-+
-+      return 1;
-+}
-+
-+static struct xt_target xt_imq_reg[] __read_mostly = {
-+      {
-+              .name           = "IMQ",
-+              .family         = AF_INET,
-+              .checkentry     = imq_checkentry,
-+              .target         = imq_target,
-+              .targetsize     = sizeof(struct xt_imq_info),
-+              .table          = "mangle",
-+              .me             = THIS_MODULE
-+      },
-+      {
-+              .name           = "IMQ",
-+              .family         = AF_INET6,
-+              .checkentry     = imq_checkentry,
-+              .target         = imq_target,
-+              .targetsize     = sizeof(struct xt_imq_info),
-+              .table          = "mangle",
-+              .me             = THIS_MODULE
-+      },
-+};
-+
-+static int __init imq_init(void)
-+{
-+      return xt_register_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg));
-+}
-+
-+static void __exit imq_fini(void)
-+{
-+      xt_unregister_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg));
-+}
-+
-+module_init(imq_init);
-+module_exit(imq_fini);
-+
-+MODULE_AUTHOR("http://www.linuximq.net");
-+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information.");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS("ipt_IMQ");
-+MODULE_ALIAS("ip6t_IMQ");
-+
index fc00d159c3dcef3b85fe260ade1de66023c14c9f..e05ec77514e1a2f8a97c545c96012855f3b01e89 100644 (file)
@@ -8,7 +8,7 @@
        depends on NETFILTER_ADVANCED
        help
          H.323 is a VoIP signalling protocol from ITU-T. As one of the most
-@@ -505,7 +504,6 @@ config NETFILTER_XT_TARGET_SECMARK
+@@ -493,7 +492,6 @@ config NETFILTER_XT_TARGET_SECMARK
  
  config NETFILTER_XT_TARGET_TCPMSS
        tristate '"TCPMSS" target support'
index e4324717b4459ce1f1009053e6317c930b01b6e4..6ea9ba51ee0d24cf3a3ac657278109d9b11de859 100644 (file)
@@ -1,6 +1,6 @@
 --- a/arch/mips/include/asm/string.h
 +++ b/arch/mips/include/asm/string.h
-@@ -133,11 +133,44 @@ strncmp(__const__ char *__cs, __const__
+@@ -133,11 +133,44 @@ strncmp(__const__ char *__cs, __const__ 
  
  #define __HAVE_ARCH_MEMSET
  extern void *memset(void *__s, int __c, size_t __count);
index 5bbf9f5f0ef1986190db569ca4bdb55d35ab55cd..0c1ae72a4ebe435e684bcd198039d89090e0cd13 100644 (file)
@@ -1,6 +1,6 @@
 --- a/include/linux/slab.h
 +++ b/include/linux/slab.h
-@@ -124,8 +124,8 @@ int kmem_ptr_validate(struct kmem_cache
+@@ -124,8 +124,8 @@ int kmem_ptr_validate(struct kmem_cache 
   * to do various tricks to work around compiler limitations in order to
   * ensure proper constant folding.
   */
index face44c0a3b41f5a399cd99781d5ec090bd6c149..2405f5936a1ba2adc221c8d365eb69b159fcebf8 100644 (file)
@@ -1,6 +1,6 @@
 --- a/include/linux/skbuff.h
 +++ b/include/linux/skbuff.h
-@@ -1384,11 +1384,18 @@ static inline int skb_network_offset(con
+@@ -1365,11 +1365,18 @@ static inline int skb_network_offset(con
   *
   * Various parts of the networking layer expect at least 32 bytes of
   * headroom, you should not reduce this.
@@ -19,7 +19,7 @@
  extern int ___pskb_trim(struct sk_buff *skb, unsigned int len);
  
  static inline void __skb_trim(struct sk_buff *skb, unsigned int len)
-@@ -1478,9 +1485,9 @@ static inline void __skb_queue_purge(str
+@@ -1459,9 +1466,9 @@ static inline void __skb_queue_purge(str
  static inline struct sk_buff *__dev_alloc_skb(unsigned int length,
                                              gfp_t gfp_mask)
  {
@@ -31,7 +31,7 @@
        return skb;
  }
  
-@@ -1553,7 +1560,7 @@ static inline int __skb_cow(struct sk_bu
+@@ -1534,7 +1541,7 @@ static inline int __skb_cow(struct sk_bu
                delta = headroom - skb_headroom(skb);
  
        if (delta || cloned)
@@ -42,7 +42,7 @@
  }
 --- a/net/core/skbuff.c
 +++ b/net/core/skbuff.c
-@@ -339,9 +339,9 @@ struct sk_buff *__netdev_alloc_skb(struc
+@@ -259,9 +259,9 @@ struct sk_buff *__netdev_alloc_skb(struc
        int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1;
        struct sk_buff *skb;
  
index b64630d50045480d022ba26c901cea68f6da66b3..d71e3b6faa6644c2337588f4b344cc5677419841 100644 (file)
@@ -61,7 +61,7 @@
  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
  extern int mini_fo_create(inode_t *dir, dentry_t *dentry, int mode, struct nameidata *nd);
  
-@@ -501,6 +505,29 @@ static inline void double_unlock(struct
+@@ -501,6 +505,29 @@ static inline void double_unlock(struct 
  #endif  /* if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) */
  #endif /* __KERNEL__ */
  
  #endif /* defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) */
 --- a/fs/mini_fo/aux.c
 +++ b/fs/mini_fo/aux.c
-@@ -164,11 +164,11 @@ dentry_t *bpath_walk(super_block_t *sb,
+@@ -164,11 +164,11 @@ dentry_t *bpath_walk(super_block_t *sb, 
        err = vfs_path_lookup(mnt->mnt_root, mnt, bpath+1, 0, &nd);
  
        /* validate */
index b5fa64e6a19e7fff343aed59f4ddccfc34578d91..8bd9ba32447e15df6ebc7153edfe89dfd38f43f6 100644 (file)
@@ -1,6 +1,6 @@
 --- a/fs/mini_fo/super.c
 +++ b/fs/mini_fo/super.c
-@@ -84,6 +84,7 @@ mini_fo_write_inode(inode_t *inode, int
+@@ -84,6 +84,7 @@ mini_fo_write_inode(inode_t *inode, int 
  #endif /* defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) */
  
  
index cc4ffb25533285eda399cfb2af96326668e1f7ed..393668b8af4869ca98614508ee1a240b06ef91ff 100644 (file)
@@ -20,7 +20,7 @@
  #else
  static inline int kobject_uevent(struct kobject *kobj,
                                 enum kobject_action action)
-@@ -224,6 +230,16 @@ static inline int add_uevent_var(struct
+@@ -224,6 +230,16 @@ static inline int add_uevent_var(struct 
  static inline int kobject_action_type(const char *buf, size_t count,
                                      enum kobject_action *type)
  { return -EINVAL; }
index 4edb071adea2d27bd51306575d92b2f6df090254..1892eb5bd9c8fad928a805757f5d364e8fe79ef9 100644 (file)
@@ -11,7 +11,7 @@
  endif # NEW_LEDS
 --- a/drivers/leds/Makefile
 +++ b/drivers/leds/Makefile
-@@ -40,3 +40,4 @@ obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) +=
+@@ -40,3 +40,4 @@ obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += 
  obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT)  += ledtrig-backlight.o
  obj-$(CONFIG_LEDS_TRIGGER_GPIO)               += ledtrig-gpio.o
  obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
index 11b87acac5326366b764293befebcadbc22da5e7..69e3f265cdc3e29f6cde1fb460ebaad6c9e5852d 100644 (file)
@@ -14,7 +14,7 @@
  endif # NEW_LEDS
 --- a/drivers/leds/Makefile
 +++ b/drivers/leds/Makefile
-@@ -41,3 +41,4 @@ obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) +=
+@@ -41,3 +41,4 @@ obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) += 
  obj-$(CONFIG_LEDS_TRIGGER_GPIO)               += ledtrig-gpio.o
  obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
  obj-$(CONFIG_LEDS_TRIGGER_MORSE)      += ledtrig-morse.o
index c334b17d0872a877f52cd9c0e4234ad118df7d09..5c70e79a058d050e90224ac0ef80dcb1180235ab 100644 (file)
                        dev->checkpointBlockList[i] = -1;
        }
  
-@@ -191,18 +185,17 @@ int yaffs_GetCheckpointSum(yaffs_Device
+@@ -191,18 +185,17 @@ int yaffs_GetCheckpointSum(yaffs_Device 
  
  static int yaffs_CheckpointFlushBuffer(yaffs_Device *dev)
  {
  {
        unsigned char cDelta;   /* column parity delta */
        unsigned lDelta;        /* line parity delta */
-@@ -294,8 +292,7 @@ int yaffs_ECCCorrectOther(unsigned char
+@@ -294,8 +292,7 @@ int yaffs_ECCCorrectOther(unsigned char 
                return 0; /* no error */
  
        if (lDelta == ~lDeltaPrime &&
                /* Single bit (recoverable) error in data */
  
                bit = 0;
-@@ -307,7 +304,7 @@ int yaffs_ECCCorrectOther(unsigned char
+@@ -307,7 +304,7 @@ int yaffs_ECCCorrectOther(unsigned char 
                if (cDelta & 0x02)
                        bit |= 0x01;
  
                        return -1;
  
                data[lDelta] ^= (1 << bit);
-@@ -316,7 +313,7 @@ int yaffs_ECCCorrectOther(unsigned char
+@@ -316,7 +313,7 @@ int yaffs_ECCCorrectOther(unsigned char 
        }
  
        if ((yaffs_CountBits32(lDelta) + yaffs_CountBits32(lDeltaPrime) +
                /* Reccoverable error in ecc */
  
                *read_ecc = *test_ecc;
-@@ -326,6 +323,4 @@ int yaffs_ECCCorrectOther(unsigned char
+@@ -326,6 +323,4 @@ int yaffs_ECCCorrectOther(unsigned char 
        /* Unrecoverable error */
  
        return -1;
  {
        unsigned char *alias;
        int ret;
-@@ -329,7 +395,7 @@ static int yaffs_readlink(struct dentry
+@@ -329,7 +395,7 @@ static int yaffs_readlink(struct dentry 
        return ret;
  }
  
  static int yaffs_file_flush(struct file *file, fl_owner_t id)
  #else
  static int yaffs_file_flush(struct file *file)
-@@ -513,8 +579,8 @@ static int yaffs_file_flush(struct file
+@@ -513,8 +579,8 @@ static int yaffs_file_flush(struct file 
        yaffs_Device *dev = obj->myDev;
  
        T(YAFFS_TRACE_OS,
  
        yaffs_GrossLock(dev);
  
-@@ -535,15 +601,15 @@ static int yaffs_readpage_nolock(struct
+@@ -535,15 +601,15 @@ static int yaffs_readpage_nolock(struct 
  
        yaffs_Device *dev;
  
        BUG_ON(!PageLocked(pg));
  #else
        if (!PageLocked(pg))
-@@ -555,9 +621,9 @@ static int yaffs_readpage_nolock(struct
+@@ -555,9 +621,9 @@ static int yaffs_readpage_nolock(struct 
  
        yaffs_GrossLock(dev);
  
  
        yaffs_GrossUnlock(dev);
  
-@@ -575,7 +641,7 @@ static int yaffs_readpage_nolock(struct
+@@ -575,7 +641,7 @@ static int yaffs_readpage_nolock(struct 
        flush_dcache_page(pg);
        kunmap(pg);
  
                if (n < step) {
                        n++;
                        continue;
-@@ -2119,7 +2356,7 @@ static int yaffs_proc_write(struct file
+@@ -2119,7 +2356,7 @@ static int yaffs_proc_write(struct file 
        char *end;
        char *mask_name;
        const char *x;
        int i;
        int done = 0;
        int add, len = 0;
-@@ -2129,9 +2366,8 @@ static int yaffs_proc_write(struct file
+@@ -2129,9 +2366,8 @@ static int yaffs_proc_write(struct file 
  
        while (!done && (pos < count)) {
                done = 1;
  
                switch (buf[pos]) {
                case '+':
-@@ -2148,20 +2384,21 @@ static int yaffs_proc_write(struct file
+@@ -2148,20 +2384,21 @@ static int yaffs_proc_write(struct file 
                mask_name = NULL;
  
                mask_bitfield = simple_strtoul(buf + pos, &end, 0);
                                        mask_name = mask_flags[i].mask_name;
                                        mask_bitfield = mask_flags[i].mask_bitfield;
                                        done = 0;
-@@ -2172,7 +2409,7 @@ static int yaffs_proc_write(struct file
+@@ -2172,7 +2409,7 @@ static int yaffs_proc_write(struct file 
  
                if (mask_name != NULL) {
                        done = 0;
                        case '-':
                                rg &= ~mask_bitfield;
                                break;
-@@ -2191,13 +2428,13 @@ static int yaffs_proc_write(struct file
+@@ -2191,13 +2428,13 @@ static int yaffs_proc_write(struct file 
  
        yaffs_traceMask = rg | YAFFS_TRACE_ALWAYS;
  
  {
        /* Get the real object in case we were fed a hard link as an equivalent object */
        equivalentObject = yaffs_GetEquivalentObject(equivalentObject);
-@@ -2363,33 +2396,31 @@ yaffs_Object *yaffs_Link(yaffs_Object *
+@@ -2363,33 +2396,31 @@ yaffs_Object *yaffs_Link(yaffs_Object * 
  
  }
  
        int nToCopy;
        int n = nBytes;
        int nDone = 0;
-@@ -4600,27 +4665,26 @@ int yaffs_ReadDataFromFile(yaffs_Object
+@@ -4600,27 +4665,26 @@ int yaffs_ReadDataFromFile(yaffs_Object 
        dev = in->myDev;
  
        while (n > 0) {
                        if (dev->nShortOpCaches > 0) {
  
                                /* If we can't find the data in the cache, then load it up. */
-@@ -4641,14 +4705,9 @@ int yaffs_ReadDataFromFile(yaffs_Object
+@@ -4641,14 +4705,9 @@ int yaffs_ReadDataFromFile(yaffs_Object 
  
                                cache->locked = 1;
  
                                cache->locked = 0;
                        } else {
                                /* Read into the local buffer then copy..*/
-@@ -4657,41 +4716,19 @@ int yaffs_ReadDataFromFile(yaffs_Object
+@@ -4657,41 +4716,19 @@ int yaffs_ReadDataFromFile(yaffs_Object 
                                    yaffs_GetTempBuffer(dev, __LINE__);
                                yaffs_ReadChunkDataFromObject(in, chunk,
                                                              localBuffer);
                }
  
                n -= nToCopy;
-@@ -4704,28 +4741,37 @@ int yaffs_ReadDataFromFile(yaffs_Object
+@@ -4704,28 +4741,37 @@ int yaffs_ReadDataFromFile(yaffs_Object 
        return nDone;
  }
  
        int newFullChunks;
  
        yaffs_Device *dev = in->myDev;
-@@ -4955,13 +4981,11 @@ int yaffs_ResizeFile(yaffs_Object * in,
+@@ -4955,13 +4981,11 @@ int yaffs_ResizeFile(yaffs_Object * in, 
  
        yaffs_CheckGarbageCollection(dev);
  
  
        if (newSize < oldFileSize) {
  
-@@ -4994,21 +5018,20 @@ int yaffs_ResizeFile(yaffs_Object * in,
+@@ -4994,21 +5018,20 @@ int yaffs_ResizeFile(yaffs_Object * in, 
        }
  
  
  {
        obj = yaffs_GetEquivalentObject(obj);
  
-@@ -5024,7 +5047,7 @@ loff_t yaffs_GetFileSize(yaffs_Object *
+@@ -5024,7 +5047,7 @@ loff_t yaffs_GetFileSize(yaffs_Object * 
  
  
  
  {
        int init_failed = 0;
        unsigned x;
-@@ -7040,6 +7126,8 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7040,6 +7126,8 @@ int yaffs_GutsInitialise(yaffs_Device * 
        dev->chunkOffset = 0;
        dev->nFreeChunks = 0;
  
        if (dev->startBlock == 0) {
                dev->internalStartBlock = dev->startBlock + 1;
                dev->internalEndBlock = dev->endBlock + 1;
-@@ -7049,18 +7137,18 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7049,18 +7137,18 @@ int yaffs_GutsInitialise(yaffs_Device * 
  
        /* Check geometry parameters. */
  
                return YAFFS_FAIL;
        }
  
-@@ -7070,6 +7158,12 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7070,6 +7158,12 @@ int yaffs_GutsInitialise(yaffs_Device * 
                return YAFFS_FAIL;
        }
  
        /* Got the right mix of functions? */
        if (!yaffs_CheckDevFunctions(dev)) {
                /* Function missing */
-@@ -7097,31 +7191,18 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7097,31 +7191,18 @@ int yaffs_GutsInitialise(yaffs_Device * 
  
        dev->isMounted = 1;
  
  
        /*
         * Calculate chunkGroupBits.
-@@ -7133,16 +7214,15 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7133,16 +7214,15 @@ int yaffs_GutsInitialise(yaffs_Device * 
        bits = ShiftsGE(x);
  
        /* Set up tnode width if wide tnodes are enabled. */
                dev->tnodeWidth = 16;
  
        dev->tnodeMask = (1<<dev->tnodeWidth)-1;
-@@ -7193,7 +7273,7 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7193,7 +7273,7 @@ int yaffs_GutsInitialise(yaffs_Device * 
        dev->hasPendingPrioritisedGCs = 1; /* Assume the worst for now, will get fixed on first GC */
  
        /* Initialise temporary buffers and caches. */
                init_failed = 1;
  
        dev->srCache = NULL;
-@@ -7203,25 +7283,26 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7203,25 +7283,26 @@ int yaffs_GutsInitialise(yaffs_Device * 
        if (!init_failed &&
            dev->nShortOpCaches > 0) {
                int i;
                        init_failed = 1;
  
                dev->srLastUse = 0;
-@@ -7229,29 +7310,30 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7229,29 +7310,30 @@ int yaffs_GutsInitialise(yaffs_Device * 
  
        dev->cacheHits = 0;
  
                                T(YAFFS_TRACE_ALWAYS,
                                  (TSTR("yaffs: restored from checkpoint" TENDSTR)));
                        } else {
-@@ -7273,24 +7355,25 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7273,24 +7355,25 @@ int yaffs_GutsInitialise(yaffs_Device * 
                                dev->nBackgroundDeletions = 0;
                                dev->oldestDirtySequence = 0;
  
                /* Clean up the mess */
                T(YAFFS_TRACE_TRACING,
                  (TSTR("yaffs: yaffs_GutsInitialise() aborted.\n" TENDSTR)));
-@@ -7318,7 +7401,7 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7318,7 +7401,7 @@ int yaffs_GutsInitialise(yaffs_Device * 
  
  }
  
  {
        if (etags) {
                memset(etags, 0, sizeof(*etags));
-@@ -169,9 +169,9 @@ static int rettags(yaffs_ExtendedTags *
+@@ -169,9 +169,9 @@ static int rettags(yaffs_ExtendedTags * 
   * Returns YAFFS_OK or YAFFS_FAIL.
   */
  int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device *dev,
 +                      yaffs_UnpackTags2(tags, &pt);
 +              }
 +      }
-+
+-      if(tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR)
+-              tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
 +      if (localData)
 +              yaffs_ReleaseTempBuffer(dev, data, __LINE__);
  
--      if(tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR)
 +      if (tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR)
-               tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
--
++              tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
        if (retval == 0)
                return YAFFS_OK;
        else
index 22a65924da155e63575004a51a036e81f6a23a60..7552ceb33dd00fc0be9381b325389e3a6b0a16bc 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/hostap/hostap_ap.c
 +++ b/drivers/net/wireless/hostap/hostap_ap.c
-@@ -2335,13 +2335,13 @@ int prism2_ap_get_sta_qual(local_info_t
+@@ -2335,13 +2335,13 @@ int prism2_ap_get_sta_qual(local_info_t 
                addr[count].sa_family = ARPHRD_ETHER;
                memcpy(addr[count].sa_data, sta->addr, ETH_ALEN);
                if (sta->last_rx_silence == 0)
index b9091c7b23fea0a8d08a6db7b312dff7100ac3d1..0ac0900842b7a25037b81517e76636c1df0e29c8 100644 (file)
@@ -55,7 +55,7 @@
  #include <linux/kallsyms.h>
  #include <linux/notifier.h>
  #include <linux/module.h>
-@@ -74,6 +75,7 @@ NORET_TYPE void panic(const char * fmt,
+@@ -74,6 +75,7 @@ NORET_TYPE void panic(const char * fmt, 
        dump_stack();
  #endif
  
index 8eff02fa6c951cd3f622110ec8fad5ec4ea13696..0b0c1e279c79dc86dbda83d48e7fcb2aabd503c9 100644 (file)
@@ -24,7 +24,7 @@
   * All of these routines try to estimate how many bits of randomness a
   * particular randomness source.  They do this by keeping track of the
   * first and second order deltas of the event timings.
-@@ -714,6 +724,61 @@ void add_disk_randomness(struct gendisk
+@@ -714,6 +724,61 @@ void add_disk_randomness(struct gendisk 
  }
  #endif
  
index 373df1a62de598e2db980037bfb7541b2b6b16ec..0cb84830212b8fc25a13b99ef2df9f9b3adeec93 100644 (file)
 +static int ssb_pcmcia_get_mac(struct pcmcia_device *p_dev,
 +                      tuple_t *tuple,
 +                      void *priv)
- {
--      tuple_t tuple;
--      int res;
--      unsigned char buf[32];
++{
 +      struct ssb_sprom *sprom = priv;
 +
 +      if (tuple->TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID)
 +static int ssb_pcmcia_do_get_invariants(struct pcmcia_device *p_dev,
 +                                      tuple_t *tuple,
 +                                      void *priv)
-+{
+ {
+-      tuple_t tuple;
+-      int res;
+-      unsigned char buf[32];
 +      struct ssb_init_invariants *iv = priv;
        struct ssb_sprom *sprom = &iv->sprom;
        struct ssb_boardinfo *bi = &iv->boardinfo;
index f81e22f116ddf86a0bce29587eb6ba454de397fc..face9154d8da77d1abdb032bf5acee19b4bf0961 100644 (file)
@@ -1,6 +1,6 @@
 --- a/scripts/Makefile.lib
 +++ b/scripts/Makefile.lib
-@@ -228,7 +228,7 @@ cmd_bzip2 = (cat $(filter-out FORCE,$^)
+@@ -228,7 +228,7 @@ cmd_bzip2 = (cat $(filter-out FORCE,$^) 
  
  quiet_cmd_lzma = LZMA    $@
  cmd_lzma = (cat $(filter-out FORCE,$^) | \
index 2618fafeb99abea83e2c607d0ca12f6444670fcb..7010d367b8f25449a593d19fbbe4e69f543ecc2c 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/mtd/chips/cfi_cmdset_0002.c
 +++ b/drivers/mtd/chips/cfi_cmdset_0002.c
-@@ -325,6 +325,8 @@ static struct cfi_fixup fixup_table[] =
+@@ -325,6 +325,8 @@ static struct cfi_fixup fixup_table[] = 
  static void cfi_fixup_major_minor(struct cfi_private *cfi,
                                  struct cfi_pri_amdstd *extp)
  {
@@ -9,7 +9,7 @@
        if (cfi->mfr == CFI_MFR_SAMSUNG && cfi->id == 0x257e &&
            extp->MajorVersion == '0')
                extp->MajorVersion = '1';
-@@ -355,6 +357,9 @@ struct mtd_info *cfi_cmdset_0002(struct
+@@ -355,6 +357,9 @@ struct mtd_info *cfi_cmdset_0002(struct 
        mtd->name    = map->name;
        mtd->writesize = 1;
  
@@ -19,7 +19,7 @@
        if (cfi->cfi_mode==CFI_MODE_CFI){
                unsigned char bootloc;
                /*
-@@ -373,16 +378,24 @@ struct mtd_info *cfi_cmdset_0002(struct
+@@ -373,16 +378,24 @@ struct mtd_info *cfi_cmdset_0002(struct 
  
                cfi_fixup_major_minor(cfi, extp);
  
index 83e24451c1c952088afd9c4e91b2c65f8707b27e..ca0c10b20dbbcf35f71f402f8b4b219f167a3ea7 100644 (file)
  
  unsigned int vced_count, vcei_count;
  
-@@ -31,8 +32,12 @@ static int show_cpuinfo(struct seq_file
+@@ -31,8 +32,12 @@ static int show_cpuinfo(struct seq_file 
        /*
         * For the first processor also print the system type
         */
index a19ff620cb7ad6b052294a443c5812d8ec96f41b..ce8853396af0c279574877bef8ee0f4aa08b51d6 100644 (file)
@@ -71,7 +71,7 @@
        depends on NETFILTER_ADVANCED
 --- a/net/netfilter/Makefile
 +++ b/net/netfilter/Makefile
-@@ -90,6 +90,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_RECENT)
+@@ -90,6 +90,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_RECENT) 
  obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o
  obj-$(CONFIG_NETFILTER_XT_MATCH_SOCKET) += xt_socket.o
  obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o
index 41c487b6899719c926cfad1b6e9b33405bbdcddb..8178a225ee07a0505b2af368291544215f6c01df 100644 (file)
  
                e = (struct ipt_entry *)(loc_cpu_entry + off);
                if (copy_to_user(userptr + off
-@@ -1000,6 +1040,14 @@ copy_entries_to_user(unsigned int total_
-                       ret = -EFAULT;
+@@ -1001,6 +1041,14 @@ copy_entries_to_user(unsigned int total_
                        goto free_counters;
                }
-+
 +              flags = e->ip.flags & ~IPT_F_NO_DEF_MATCH;
 +              if (copy_to_user(userptr + off
 +                               + offsetof(struct ipt_entry, ip.flags),
 +                      ret = -EFAULT;
 +                      goto free_counters;
 +              }
++
                for (i = sizeof(struct ipt_entry);
                     i < e->target_offset;
+                    i += m->u.match_size) {
diff --git a/target/linux/generic/patches-2.6.34/150-netfilter_imq.patch b/target/linux/generic/patches-2.6.34/150-netfilter_imq.patch
deleted file mode 100644 (file)
index 8441e41..0000000
+++ /dev/null
@@ -1,1336 +0,0 @@
---- /dev/null
-+++ b/drivers/net/imq.c
-@@ -0,0 +1,632 @@
-+/*
-+ *             Pseudo-driver for the intermediate queue device.
-+ *
-+ *             This program is free software; you can redistribute it and/or
-+ *             modify it under the terms of the GNU General Public License
-+ *             as published by the Free Software Foundation; either version
-+ *             2 of the License, or (at your option) any later version.
-+ *
-+ * Authors:    Patrick McHardy, <kaber@trash.net>
-+ *
-+ *            The first version was written by Martin Devera, <devik@cdi.cz>
-+ *
-+ * Credits:    Jan Rafaj <imq2t@cedric.vabo.cz>
-+ *              - Update patch to 2.4.21
-+ *             Sebastian Strollo <sstrollo@nortelnetworks.com>
-+ *              - Fix "Dead-loop on netdevice imq"-issue
-+ *             Marcel Sebek <sebek64@post.cz>
-+ *              - Update to 2.6.2-rc1
-+ *
-+ *           After some time of inactivity there is a group taking care
-+ *           of IMQ again: http://www.linuximq.net
-+ *
-+ *
-+ *           2004/06/30 - New version of IMQ patch to kernels <=2.6.7
-+ *             including the following changes:
-+ *
-+ *           - Correction of ipv6 support "+"s issue (Hasso Tepper)
-+ *           - Correction of imq_init_devs() issue that resulted in
-+ *           kernel OOPS unloading IMQ as module (Norbert Buchmuller)
-+ *           - Addition of functionality to choose number of IMQ devices
-+ *           during kernel config (Andre Correa)
-+ *           - Addition of functionality to choose how IMQ hooks on
-+ *           PRE and POSTROUTING (after or before NAT) (Andre Correa)
-+ *           - Cosmetic corrections (Norbert Buchmuller) (Andre Correa)
-+ *
-+ *
-+ *             2005/12/16 - IMQ versions between 2.6.7 and 2.6.13 were
-+ *             released with almost no problems. 2.6.14-x was released
-+ *             with some important changes: nfcache was removed; After
-+ *             some weeks of trouble we figured out that some IMQ fields
-+ *             in skb were missing in skbuff.c - skb_clone and copy_skb_header.
-+ *             These functions are correctly patched by this new patch version.
-+ *
-+ *             Thanks for all who helped to figure out all the problems with
-+ *             2.6.14.x: Patrick McHardy, Rune Kock, VeNoMouS, Max CtRiX,
-+ *             Kevin Shanahan, Richard Lucassen, Valery Dachev (hopefully
-+ *             I didn't forget anybody). I apologize again for my lack of time.
-+ *
-+ *
-+ *             2008/06/17 - 2.6.25 - Changed imq.c to use qdisc_run() instead 
-+ *             of qdisc_restart() and moved qdisc_run() to tasklet to avoid
-+ *             recursive locking. New initialization routines to fix 'rmmod' not
-+ *             working anymore. Used code from ifb.c. (Jussi Kivilinna)
-+ *
-+ *             2008/08/06 - 2.6.26 - (JK)
-+ *              - Replaced tasklet with 'netif_schedule()'.
-+ *              - Cleaned up and added comments for imq_nf_queue().
-+ *
-+ *             2009/04/12
-+ *              - Add skb_save_cb/skb_restore_cb helper functions for backuping
-+ *                control buffer. This is needed because qdisc-layer on kernels
-+ *                2.6.27 and newer overwrite control buffer. (Jussi Kivilinna)
-+ *              - Add better locking for IMQ device. Hopefully this will solve
-+ *                SMP issues. (Jussi Kivilinna)
-+ *              - Port to 2.6.27
-+ *              - Port to 2.6.28
-+ *              - Port to 2.6.29 + fix rmmod not working
-+ *
-+ *             2009/04/20 - (Jussi Kivilinna)
-+ *              - Use netdevice feature flags to avoid extra packet handling
-+ *                by core networking layer and possibly increase performance.
-+ *
-+ *             2009/09/26 - (Jussi Kivilinna)
-+ *              - Add imq_nf_reinject_lockless to fix deadlock with
-+ *                imq_nf_queue/imq_nf_reinject.
-+ *
-+ *             2009/12/08 - (Jussi Kivilinna)
-+ *              - Port to 2.6.32
-+ *              - Add check for skb->nf_queue_entry==NULL in imq_dev_xmit()
-+ *              - Also add better error checking for skb->nf_queue_entry usage
-+ *
-+ *           Also, many thanks to pablo Sebastian Greco for making the initial
-+ *           patch and to those who helped the testing.
-+ *
-+ *             More info at: http://www.linuximq.net/ (Andre Correa)
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/moduleparam.h>
-+#include <linux/list.h>
-+#include <linux/skbuff.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/rtnetlink.h>
-+#include <linux/if_arp.h>
-+#include <linux/netfilter.h>
-+#include <linux/netfilter_ipv4.h>
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+      #include <linux/netfilter_ipv6.h>
-+#endif
-+#include <linux/imq.h>
-+#include <net/pkt_sched.h>
-+#include <net/netfilter/nf_queue.h>
-+
-+static nf_hookfn imq_nf_hook;
-+
-+static struct nf_hook_ops imq_ingress_ipv4 = {
-+      .hook           = imq_nf_hook,
-+      .owner          = THIS_MODULE,
-+      .pf             = PF_INET,
-+      .hooknum        = NF_INET_PRE_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+      .priority       = NF_IP_PRI_MANGLE + 1
-+#else
-+      .priority       = NF_IP_PRI_NAT_DST + 1
-+#endif
-+};
-+
-+static struct nf_hook_ops imq_egress_ipv4 = {
-+      .hook           = imq_nf_hook,
-+      .owner          = THIS_MODULE,
-+      .pf             = PF_INET,
-+      .hooknum        = NF_INET_POST_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
-+      .priority       = NF_IP_PRI_LAST
-+#else
-+      .priority       = NF_IP_PRI_NAT_SRC - 1
-+#endif
-+};
-+
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+static struct nf_hook_ops imq_ingress_ipv6 = {
-+      .hook           = imq_nf_hook,
-+      .owner          = THIS_MODULE,
-+      .pf             = PF_INET6,
-+      .hooknum        = NF_INET_PRE_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+      .priority       = NF_IP6_PRI_MANGLE + 1
-+#else
-+      .priority       = NF_IP6_PRI_NAT_DST + 1
-+#endif
-+};
-+
-+static struct nf_hook_ops imq_egress_ipv6 = {
-+      .hook           = imq_nf_hook,
-+      .owner          = THIS_MODULE,
-+      .pf             = PF_INET6,
-+      .hooknum        = NF_INET_POST_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
-+      .priority       = NF_IP6_PRI_LAST
-+#else
-+      .priority       = NF_IP6_PRI_NAT_SRC - 1
-+#endif
-+};
-+#endif
-+
-+#if defined(CONFIG_IMQ_NUM_DEVS)
-+static unsigned int numdevs = CONFIG_IMQ_NUM_DEVS;
-+#else
-+static unsigned int numdevs = IMQ_MAX_DEVS;
-+#endif
-+
-+static DEFINE_SPINLOCK(imq_nf_queue_lock);
-+
-+static struct net_device *imq_devs_cache[IMQ_MAX_DEVS];
-+
-+
-+static struct net_device_stats *imq_get_stats(struct net_device *dev)
-+{
-+      return &dev->stats;
-+}
-+
-+/* called for packets kfree'd in qdiscs at places other than enqueue */
-+static void imq_skb_destructor(struct sk_buff *skb)
-+{
-+      struct nf_queue_entry *entry = skb->nf_queue_entry;
-+
-+      skb->nf_queue_entry = NULL;
-+
-+      if (entry) {
-+              nf_queue_entry_release_refs(entry);
-+              kfree(entry);
-+      }
-+
-+      skb_restore_cb(skb); /* kfree backup */
-+}
-+
-+/* locking not needed when called from imq_nf_queue */
-+static void imq_nf_reinject_lockless(struct nf_queue_entry *entry,
-+                                              unsigned int verdict)
-+{
-+      int status;
-+
-+      if (!entry->next_outfn) {
-+              nf_reinject(entry, verdict);
-+              return;
-+      }
-+
-+      status = entry->next_outfn(entry, entry->next_queuenum);
-+      if (status < 0) {
-+              nf_queue_entry_release_refs(entry);
-+              kfree_skb(entry->skb);
-+              kfree(entry);
-+      }
-+}
-+
-+static void imq_nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
-+{
-+      int status;
-+
-+      if (!entry->next_outfn) {
-+              spin_lock_bh(&imq_nf_queue_lock);
-+              nf_reinject(entry, verdict);
-+              spin_unlock_bh(&imq_nf_queue_lock);
-+              return;
-+      }
-+
-+      rcu_read_lock();
-+      local_bh_disable();
-+      status = entry->next_outfn(entry, entry->next_queuenum);
-+      local_bh_enable();
-+      if (status < 0) {
-+              nf_queue_entry_release_refs(entry);
-+              kfree_skb(entry->skb);
-+              kfree(entry);
-+      }
-+
-+      rcu_read_unlock();
-+}
-+
-+static netdev_tx_t imq_dev_xmit(struct sk_buff *skb, struct net_device *dev)
-+{
-+      struct nf_queue_entry *entry = skb->nf_queue_entry;
-+
-+      skb->nf_queue_entry = NULL;
-+      dev->trans_start = jiffies;
-+
-+      dev->stats.tx_bytes += skb->len;
-+      dev->stats.tx_packets++;
-+
-+      if (entry == NULL) {
-+              /* We don't know what is going on here.. packet is queued for
-+               * imq device, but (probably) not by us.
-+               *
-+               * If this packet was not send here by imq_nf_queue(), then
-+               * skb_save_cb() was not used and skb_free() should not show:
-+               *   WARNING: IMQ: kfree_skb: skb->cb_next:..
-+               * and/or
-+               *   WARNING: IMQ: kfree_skb: skb->nf_queue_entry...
-+               *
-+               * However if this message is shown, then IMQ is somehow broken
-+               * and you should report this to linuximq.net.
-+               */
-+
-+              /* imq_dev_xmit is black hole that eats all packets, report that
-+               * we eat this packet happily and increase dropped counters.
-+               */
-+
-+              dev->stats.tx_dropped++;
-+              dev_kfree_skb(skb);
-+
-+              return NETDEV_TX_OK;
-+      }
-+
-+      skb_restore_cb(skb); /* restore skb->cb */
-+
-+      skb->imq_flags = 0;
-+      skb->destructor = NULL;
-+
-+      imq_nf_reinject(entry, NF_ACCEPT);
-+
-+      return NETDEV_TX_OK;
-+}
-+
-+static int imq_nf_queue(struct nf_queue_entry *entry, unsigned queue_num)
-+{
-+      struct net_device *dev;
-+      struct sk_buff *skb_orig, *skb, *skb_shared;
-+      struct Qdisc *q;
-+      struct netdev_queue *txq;
-+      int users, index;
-+      int retval = -EINVAL;
-+
-+      index = entry->skb->imq_flags & IMQ_F_IFMASK;
-+      if (unlikely(index > numdevs - 1)) {
-+              if (net_ratelimit())
-+                      printk(KERN_WARNING
-+                             "IMQ: invalid device specified, highest is %u\n",
-+                             numdevs - 1);
-+              retval = -EINVAL;
-+              goto out;
-+      }
-+
-+      /* check for imq device by index from cache */
-+      dev = imq_devs_cache[index];
-+      if (unlikely(!dev)) {
-+              char buf[8];
-+
-+              /* get device by name and cache result */
-+              snprintf(buf, sizeof(buf), "imq%d", index);
-+              dev = dev_get_by_name(&init_net, buf);
-+              if (!dev) {
-+                      /* not found ?!*/
-+                      BUG();
-+                      retval = -ENODEV;
-+                      goto out;
-+              }
-+
-+              imq_devs_cache[index] = dev;
-+              dev_put(dev);
-+      }
-+
-+      if (unlikely(!(dev->flags & IFF_UP))) {
-+              entry->skb->imq_flags = 0;
-+              imq_nf_reinject_lockless(entry, NF_ACCEPT);
-+              retval = 0;
-+              goto out;
-+      }
-+      dev->last_rx = jiffies;
-+
-+      skb = entry->skb;
-+      skb_orig = NULL;
-+
-+      /* skb has owner? => make clone */
-+      if (unlikely(skb->destructor)) {
-+              skb_orig = skb;
-+              skb = skb_clone(skb, GFP_ATOMIC);
-+              if (!skb) {
-+                      retval = -ENOMEM;
-+                      goto out;
-+              }
-+              entry->skb = skb;
-+      }
-+
-+      skb->nf_queue_entry = entry;
-+
-+      dev->stats.rx_bytes += skb->len;
-+      dev->stats.rx_packets++;
-+
-+      txq = dev_pick_tx(dev, skb);
-+
-+      q = rcu_dereference(txq->qdisc);
-+      if (unlikely(!q->enqueue))
-+              goto packet_not_eaten_by_imq_dev;
-+
-+      spin_lock_bh(qdisc_lock(q));
-+
-+      users = atomic_read(&skb->users);
-+
-+      skb_shared = skb_get(skb); /* increase reference count by one */
-+      skb_save_cb(skb_shared); /* backup skb->cb, as qdisc layer will
-+                                      overwrite it */
-+      qdisc_enqueue_root(skb_shared, q); /* might kfree_skb */
-+
-+      if (likely(atomic_read(&skb_shared->users) == users + 1)) {
-+              kfree_skb(skb_shared); /* decrease reference count by one */
-+
-+              skb->destructor = &imq_skb_destructor;
-+
-+              /* cloned? */
-+              if (skb_orig)
-+                      kfree_skb(skb_orig); /* free original */
-+
-+              spin_unlock_bh(qdisc_lock(q));
-+
-+              /* schedule qdisc dequeue */
-+              __netif_schedule(q);
-+
-+              retval = 0;
-+              goto out;
-+      } else {
-+              skb_restore_cb(skb_shared); /* restore skb->cb */
-+              skb->nf_queue_entry = NULL;
-+              /* qdisc dropped packet and decreased skb reference count of
-+               * skb, so we don't really want to and try refree as that would
-+               * actually destroy the skb. */
-+              spin_unlock_bh(qdisc_lock(q));
-+              goto packet_not_eaten_by_imq_dev;
-+      }
-+
-+packet_not_eaten_by_imq_dev:
-+      /* cloned? restore original */
-+      if (skb_orig) {
-+              kfree_skb(skb);
-+              entry->skb = skb_orig;
-+      }
-+      retval = -1;
-+out:
-+      return retval;
-+}
-+
-+static struct nf_queue_handler nfqh = {
-+      .name  = "imq",
-+      .outfn = imq_nf_queue,
-+};
-+
-+static unsigned int imq_nf_hook(unsigned int hook, struct sk_buff *pskb,
-+                              const struct net_device *indev,
-+                              const struct net_device *outdev,
-+                              int (*okfn)(struct sk_buff *))
-+{
-+      if (pskb->imq_flags & IMQ_F_ENQUEUE)
-+              return NF_QUEUE;
-+
-+      return NF_ACCEPT;
-+}
-+
-+static int imq_close(struct net_device *dev)
-+{
-+      netif_stop_queue(dev);
-+      return 0;
-+}
-+
-+static int imq_open(struct net_device *dev)
-+{
-+      netif_start_queue(dev);
-+      return 0;
-+}
-+
-+static const struct net_device_ops imq_netdev_ops = {
-+      .ndo_open               = imq_open,
-+      .ndo_stop               = imq_close,
-+      .ndo_start_xmit         = imq_dev_xmit,
-+      .ndo_get_stats          = imq_get_stats,
-+};
-+
-+static void imq_setup(struct net_device *dev)
-+{
-+      dev->netdev_ops         = &imq_netdev_ops;
-+      dev->type               = ARPHRD_VOID;
-+      dev->mtu                = 16000;
-+      dev->tx_queue_len       = 11000;
-+      dev->flags              = IFF_NOARP;
-+      dev->features           = NETIF_F_SG | NETIF_F_FRAGLIST |
-+                                NETIF_F_GSO | NETIF_F_HW_CSUM |
-+                                NETIF_F_HIGHDMA;
-+      dev->priv_flags         &= ~IFF_XMIT_DST_RELEASE;
-+}
-+
-+static int imq_validate(struct nlattr *tb[], struct nlattr *data[])
-+{
-+      int ret = 0;
-+
-+      if (tb[IFLA_ADDRESS]) {
-+              if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) {
-+                      ret = -EINVAL;
-+                      goto end;
-+              }
-+              if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) {
-+                      ret = -EADDRNOTAVAIL;
-+                      goto end;
-+              }
-+      }
-+      return 0;
-+end:
-+      printk(KERN_WARNING "IMQ: imq_validate failed (%d)\n", ret);
-+      return ret;
-+}
-+
-+static struct rtnl_link_ops imq_link_ops __read_mostly = {
-+      .kind           = "imq",
-+      .priv_size      = 0,
-+      .setup          = imq_setup,
-+      .validate       = imq_validate,
-+};
-+
-+static int __init imq_init_hooks(void)
-+{
-+      int err;
-+
-+      nf_register_queue_imq_handler(&nfqh);
-+
-+      err = nf_register_hook(&imq_ingress_ipv4);
-+      if (err)
-+              goto err1;
-+
-+      err = nf_register_hook(&imq_egress_ipv4);
-+      if (err)
-+              goto err2;
-+
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+      err = nf_register_hook(&imq_ingress_ipv6);
-+      if (err)
-+              goto err3;
-+
-+      err = nf_register_hook(&imq_egress_ipv6);
-+      if (err)
-+              goto err4;
-+#endif
-+
-+      return 0;
-+
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+err4:
-+      nf_unregister_hook(&imq_ingress_ipv6);
-+err3:
-+      nf_unregister_hook(&imq_egress_ipv4);
-+#endif
-+err2:
-+      nf_unregister_hook(&imq_ingress_ipv4);
-+err1:
-+      nf_unregister_queue_imq_handler();
-+      return err;
-+}
-+
-+static int __init imq_init_one(int index)
-+{
-+      struct net_device *dev;
-+      int ret;
-+
-+      dev = alloc_netdev(0, "imq%d", imq_setup);
-+      if (!dev)
-+              return -ENOMEM;
-+
-+      ret = dev_alloc_name(dev, dev->name);
-+      if (ret < 0)
-+              goto fail;
-+
-+      dev->rtnl_link_ops = &imq_link_ops;
-+      ret = register_netdevice(dev);
-+      if (ret < 0)
-+              goto fail;
-+
-+      return 0;
-+fail:
-+      free_netdev(dev);
-+      return ret;
-+}
-+
-+static int __init imq_init_devs(void)
-+{
-+      int err, i;
-+
-+      if (numdevs < 1 || numdevs > IMQ_MAX_DEVS) {
-+              printk(KERN_ERR "IMQ: numdevs has to be betweed 1 and %u\n",
-+                     IMQ_MAX_DEVS);
-+              return -EINVAL;
-+      }
-+
-+      rtnl_lock();
-+      err = __rtnl_link_register(&imq_link_ops);
-+
-+      for (i = 0; i < numdevs && !err; i++)
-+              err = imq_init_one(i);
-+
-+      if (err) {
-+              __rtnl_link_unregister(&imq_link_ops);
-+              memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
-+      }
-+      rtnl_unlock();
-+
-+      return err;
-+}
-+
-+static int __init imq_init_module(void)
-+{
-+      int err;
-+
-+#if defined(CONFIG_IMQ_NUM_DEVS)
-+      BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS > 16);
-+      BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS < 2);
-+      BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS - 1 > IMQ_F_IFMASK);
-+#endif
-+
-+      err = imq_init_devs();
-+      if (err) {
-+              printk(KERN_ERR "IMQ: Error trying imq_init_devs(net)\n");
-+              return err;
-+      }
-+
-+      err = imq_init_hooks();
-+      if (err) {
-+              printk(KERN_ERR "IMQ: Error trying imq_init_hooks()\n");
-+              rtnl_link_unregister(&imq_link_ops);
-+              memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
-+              return err;
-+      }
-+
-+      printk(KERN_INFO "IMQ driver loaded successfully.\n");
-+
-+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+      printk(KERN_INFO "\tHooking IMQ before NAT on PREROUTING.\n");
-+#else
-+      printk(KERN_INFO "\tHooking IMQ after NAT on PREROUTING.\n");
-+#endif
-+#if defined(CONFIG_IMQ_BEHAVIOR_AB) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+      printk(KERN_INFO "\tHooking IMQ before NAT on POSTROUTING.\n");
-+#else
-+      printk(KERN_INFO "\tHooking IMQ after NAT on POSTROUTING.\n");
-+#endif
-+
-+      return 0;
-+}
-+
-+static void __exit imq_unhook(void)
-+{
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+      nf_unregister_hook(&imq_ingress_ipv6);
-+      nf_unregister_hook(&imq_egress_ipv6);
-+#endif
-+      nf_unregister_hook(&imq_ingress_ipv4);
-+      nf_unregister_hook(&imq_egress_ipv4);
-+
-+      nf_unregister_queue_imq_handler();
-+}
-+
-+static void __exit imq_cleanup_devs(void)
-+{
-+      rtnl_link_unregister(&imq_link_ops);
-+      memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
-+}
-+
-+static void __exit imq_exit_module(void)
-+{
-+      imq_unhook();
-+      imq_cleanup_devs();
-+      printk(KERN_INFO "IMQ driver unloaded successfully.\n");
-+}
-+
-+module_init(imq_init_module);
-+module_exit(imq_exit_module);
-+
-+module_param(numdevs, int, 0);
-+MODULE_PARM_DESC(numdevs, "number of IMQ devices (how many imq* devices will "
-+                      "be created)");
-+MODULE_AUTHOR("http://www.linuximq.net");
-+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See "
-+                      "http://www.linuximq.net/ for more information.");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS_RTNL_LINK("imq");
-+
---- a/drivers/net/Kconfig
-+++ b/drivers/net/Kconfig
-@@ -121,6 +121,129 @@ config EQUALIZER
-         To compile this driver as a module, choose M here: the module
-         will be called eql.  If unsure, say N.
-+config IMQ
-+      tristate "IMQ (intermediate queueing device) support"
-+      depends on NETDEVICES && NETFILTER
-+      ---help---
-+        The IMQ device(s) is used as placeholder for QoS queueing
-+        disciplines. Every packet entering/leaving the IP stack can be
-+        directed through the IMQ device where it's enqueued/dequeued to the
-+        attached qdisc. This allows you to treat network devices as classes
-+        and distribute bandwidth among them. Iptables is used to specify
-+        through which IMQ device, if any, packets travel.
-+
-+        More information at: http://www.linuximq.net/
-+
-+        To compile this driver as a module, choose M here: the module
-+        will be called imq.  If unsure, say N.
-+
-+choice
-+      prompt "IMQ behavior (PRE/POSTROUTING)"
-+      depends on IMQ
-+      default IMQ_BEHAVIOR_AB
-+      help
-+
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              IMQ can work in any of the following ways:
-+
-+                  PREROUTING   |      POSTROUTING
-+              -----------------|-------------------
-+              #1  After NAT    |      After NAT
-+              #2  After NAT    |      Before NAT
-+              #3  Before NAT   |      After NAT
-+              #4  Before NAT   |      Before NAT
-+
-+              The default behavior is to hook before NAT on PREROUTING
-+              and after NAT on POSTROUTING (#3).
-+
-+              This settings are specially usefull when trying to use IMQ
-+              to shape NATed clients.
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_AA
-+      bool "IMQ AA"
-+      help
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              Choosing this option will make IMQ hook like this:
-+
-+              PREROUTING:   After NAT
-+              POSTROUTING:  After NAT
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_AB
-+      bool "IMQ AB"
-+      help
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              Choosing this option will make IMQ hook like this:
-+
-+              PREROUTING:   After NAT
-+              POSTROUTING:  Before NAT
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_BA
-+      bool "IMQ BA"
-+      help
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              Choosing this option will make IMQ hook like this:
-+
-+              PREROUTING:   Before NAT
-+              POSTROUTING:  After NAT
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_BB
-+      bool "IMQ BB"
-+      help
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              Choosing this option will make IMQ hook like this:
-+
-+              PREROUTING:   Before NAT
-+              POSTROUTING:  Before NAT
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+endchoice
-+
-+config IMQ_NUM_DEVS
-+
-+      int "Number of IMQ devices"
-+      range 2 16
-+      depends on IMQ
-+      default "16"
-+      help
-+
-+              This settings defines how many IMQ devices will be
-+              created.
-+
-+              The default value is 16.
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
- config TUN
-       tristate "Universal TUN/TAP device driver support"
-       select CRC32
---- a/drivers/net/Makefile
-+++ b/drivers/net/Makefile
-@@ -169,6 +169,7 @@ obj-$(CONFIG_SLHC) += slhc.o
- obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o
- obj-$(CONFIG_DUMMY) += dummy.o
-+obj-$(CONFIG_IMQ) += imq.o
- obj-$(CONFIG_IFB) += ifb.o
- obj-$(CONFIG_MACVLAN) += macvlan.o
- obj-$(CONFIG_MACVTAP) += macvtap.o
---- /dev/null
-+++ b/include/linux/imq.h
-@@ -0,0 +1,13 @@
-+#ifndef _IMQ_H
-+#define _IMQ_H
-+
-+/* IFMASK (16 device indexes, 0 to 15) and flag(s) fit in 5 bits */
-+#define IMQ_F_BITS    5
-+
-+#define IMQ_F_IFMASK  0x0f
-+#define IMQ_F_ENQUEUE 0x10
-+
-+#define IMQ_MAX_DEVS  (IMQ_F_IFMASK + 1)
-+
-+#endif /* _IMQ_H */
-+
---- a/include/linux/netdevice.h
-+++ b/include/linux/netdevice.h
-@@ -1203,6 +1203,7 @@ extern int               dev_alloc_name(struct net_de
- extern int            dev_open(struct net_device *dev);
- extern int            dev_close(struct net_device *dev);
- extern void           dev_disable_lro(struct net_device *dev);
-+extern struct netdev_queue *dev_pick_tx(struct net_device *dev, struct sk_buff *skb);
- extern int            dev_queue_xmit(struct sk_buff *skb);
- extern int            register_netdevice(struct net_device *dev);
- extern void           unregister_netdevice_queue(struct net_device *dev,
---- /dev/null
-+++ b/include/linux/netfilter/xt_IMQ.h
-@@ -0,0 +1,9 @@
-+#ifndef _XT_IMQ_H
-+#define _XT_IMQ_H
-+
-+struct xt_imq_info {
-+      unsigned int todev;     /* target imq device */
-+};
-+
-+#endif /* _XT_IMQ_H */
-+
---- /dev/null
-+++ b/include/linux/netfilter_ipv4/ipt_IMQ.h
-@@ -0,0 +1,10 @@
-+#ifndef _IPT_IMQ_H
-+#define _IPT_IMQ_H
-+
-+/* Backwards compatibility for old userspace */
-+#include <linux/netfilter/xt_IMQ.h>
-+
-+#define ipt_imq_info xt_imq_info
-+
-+#endif /* _IPT_IMQ_H */
-+
---- /dev/null
-+++ b/include/linux/netfilter_ipv6/ip6t_IMQ.h
-@@ -0,0 +1,10 @@
-+#ifndef _IP6T_IMQ_H
-+#define _IP6T_IMQ_H
-+
-+/* Backwards compatibility for old userspace */
-+#include <linux/netfilter/xt_IMQ.h>
-+
-+#define ip6t_imq_info xt_imq_info
-+
-+#endif /* _IP6T_IMQ_H */
-+
---- a/include/linux/skbuff.h
-+++ b/include/linux/skbuff.h
-@@ -29,6 +29,9 @@
- #include <linux/rcupdate.h>
- #include <linux/dmaengine.h>
- #include <linux/hrtimer.h>
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+#include <linux/imq.h>
-+#endif
- /* Don't change this without changing skb_csum_unnecessary! */
- #define CHECKSUM_NONE 0
-@@ -321,6 +324,9 @@ struct sk_buff {
-        * first. This is owned by whoever has the skb queued ATM.
-        */
-       char                    cb[48] __aligned(8);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      void                    *cb_next;
-+#endif
-       unsigned long           _skb_dst;
- #ifdef CONFIG_XFRM
-@@ -357,6 +363,9 @@ struct sk_buff {
-       struct nf_conntrack     *nfct;
-       struct sk_buff          *nfct_reasm;
- #endif
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      struct nf_queue_entry   *nf_queue_entry;
-+#endif
- #ifdef CONFIG_BRIDGE_NETFILTER
-       struct nf_bridge_info   *nf_bridge;
- #endif
-@@ -378,6 +387,10 @@ struct sk_buff {
-       /* 0/14 bit hole */
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      __u8                    imq_flags:IMQ_F_BITS;
-+#endif
-+
- #ifdef CONFIG_NET_DMA
-       dma_cookie_t            dma_cookie;
- #endif
-@@ -426,6 +439,12 @@ static inline struct rtable *skb_rtable(
-       return (struct rtable *)skb_dst(skb);
- }
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+extern int skb_save_cb(struct sk_buff *skb);
-+extern int skb_restore_cb(struct sk_buff *skb);
-+#endif
-+
- extern void kfree_skb(struct sk_buff *skb);
- extern void consume_skb(struct sk_buff *skb);
- extern void          __kfree_skb(struct sk_buff *skb);
-@@ -1970,6 +1989,10 @@ static inline void __nf_copy(struct sk_b
-       dst->nfct_reasm = src->nfct_reasm;
-       nf_conntrack_get_reasm(src->nfct_reasm);
- #endif
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      dst->imq_flags = src->imq_flags;
-+      dst->nf_queue_entry = src->nf_queue_entry;
-+#endif
- #ifdef CONFIG_BRIDGE_NETFILTER
-       dst->nf_bridge  = src->nf_bridge;
-       nf_bridge_get(src->nf_bridge);
---- a/include/net/netfilter/nf_queue.h
-+++ b/include/net/netfilter/nf_queue.h
-@@ -13,6 +13,12 @@ struct nf_queue_entry {
-       struct net_device       *indev;
-       struct net_device       *outdev;
-       int                     (*okfn)(struct sk_buff *);
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      int                     (*next_outfn)(struct nf_queue_entry *entry,
-+                                            unsigned int queuenum);
-+      unsigned int            next_queuenum;
-+#endif
- };
- #define nf_queue_entry_reroute(x) ((void *)x + sizeof(struct nf_queue_entry))
-@@ -30,5 +36,11 @@ extern int nf_unregister_queue_handler(u
-                                      const struct nf_queue_handler *qh);
- extern void nf_unregister_queue_handlers(const struct nf_queue_handler *qh);
- extern void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
-+extern void nf_queue_entry_release_refs(struct nf_queue_entry *entry);
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+extern void nf_register_queue_imq_handler(const struct nf_queue_handler *qh);
-+extern void nf_unregister_queue_imq_handler(void);
-+#endif
- #endif /* _NF_QUEUE_H */
---- a/net/core/dev.c
-+++ b/net/core/dev.c
-@@ -98,6 +98,9 @@
- #include <net/net_namespace.h>
- #include <net/sock.h>
- #include <linux/rtnetlink.h>
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+#include <linux/imq.h>
-+#endif
- #include <linux/proc_fs.h>
- #include <linux/seq_file.h>
- #include <linux/stat.h>
-@@ -1860,7 +1863,11 @@ int dev_hard_start_xmit(struct sk_buff *
-       int rc = NETDEV_TX_OK;
-       if (likely(!skb->next)) {
--              if (!list_empty(&ptype_all))
-+              if (!list_empty(&ptype_all)
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+                  && !(skb->imq_flags & IMQ_F_ENQUEUE)
-+#endif
-+                  )
-                       dev_queue_xmit_nit(skb, dev);
-               if (netif_needs_gso(dev, skb)) {
-@@ -1970,8 +1977,7 @@ static inline u16 dev_cap_txqueue(struct
-       return queue_index;
- }
--static struct netdev_queue *dev_pick_tx(struct net_device *dev,
--                                      struct sk_buff *skb)
-+struct netdev_queue *dev_pick_tx(struct net_device *dev, struct sk_buff *skb)
- {
-       int queue_index;
-       struct sock *sk = skb->sk;
-@@ -2000,6 +2006,7 @@ static struct netdev_queue *dev_pick_tx(
-       skb_set_queue_mapping(skb, queue_index);
-       return netdev_get_tx_queue(dev, queue_index);
- }
-+EXPORT_SYMBOL(dev_pick_tx);
- static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
-                                struct net_device *dev,
---- a/net/core/skbuff.c
-+++ b/net/core/skbuff.c
-@@ -72,6 +72,9 @@
- static struct kmem_cache *skbuff_head_cache __read_mostly;
- static struct kmem_cache *skbuff_fclone_cache __read_mostly;
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+static struct kmem_cache *skbuff_cb_store_cache __read_mostly;
-+#endif
- static void sock_pipe_buf_release(struct pipe_inode_info *pipe,
-                                 struct pipe_buffer *buf)
-@@ -91,6 +94,83 @@ static int sock_pipe_buf_steal(struct pi
-       return 1;
- }
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+/* Control buffer save/restore for IMQ devices */
-+struct skb_cb_table {
-+      void                    *cb_next;
-+      atomic_t                refcnt;
-+      char                    cb[48];
-+};
-+
-+static DEFINE_SPINLOCK(skb_cb_store_lock);
-+
-+int skb_save_cb(struct sk_buff *skb)
-+{
-+      struct skb_cb_table *next;
-+
-+      next = kmem_cache_alloc(skbuff_cb_store_cache, GFP_ATOMIC);
-+      if (!next)
-+              return -ENOMEM;
-+
-+      BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb));
-+
-+      memcpy(next->cb, skb->cb, sizeof(skb->cb));
-+      next->cb_next = skb->cb_next;
-+
-+      atomic_set(&next->refcnt, 1);
-+
-+      skb->cb_next = next;
-+      return 0;
-+}
-+EXPORT_SYMBOL(skb_save_cb);
-+
-+int skb_restore_cb(struct sk_buff *skb)
-+{
-+      struct skb_cb_table *next;
-+
-+      if (!skb->cb_next)
-+              return 0;
-+
-+      next = skb->cb_next;
-+
-+      BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb));
-+
-+      memcpy(skb->cb, next->cb, sizeof(skb->cb));
-+      skb->cb_next = next->cb_next;
-+
-+      spin_lock(&skb_cb_store_lock);
-+
-+      if (atomic_dec_and_test(&next->refcnt)) {
-+              kmem_cache_free(skbuff_cb_store_cache, next);
-+      }
-+
-+      spin_unlock(&skb_cb_store_lock);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL(skb_restore_cb);
-+
-+static void skb_copy_stored_cb(struct sk_buff *new, const struct sk_buff *__old)
-+{
-+      struct skb_cb_table *next;
-+      struct sk_buff *old;
-+
-+      if (!__old->cb_next) {
-+              new->cb_next = NULL;
-+              return;
-+      }
-+
-+      spin_lock(&skb_cb_store_lock);
-+
-+      old = (struct sk_buff *)__old;
-+
-+      next = old->cb_next;
-+      atomic_inc(&next->refcnt);
-+      new->cb_next = next;
-+
-+      spin_unlock(&skb_cb_store_lock);
-+}
-+#endif
- /* Pipe buffer operations for a socket. */
- static const struct pipe_buf_operations sock_pipe_buf_ops = {
-@@ -398,6 +478,26 @@ static void skb_release_head_state(struc
-               WARN_ON(in_irq());
-               skb->destructor(skb);
-       }
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      /* This should not happen. When it does, avoid memleak by restoring
-+      the chain of cb-backups. */
-+      while(skb->cb_next != NULL) {
-+              if (net_ratelimit())
-+                      printk(KERN_WARNING "IMQ: kfree_skb: skb->cb_next: "
-+                              "%08x\n", (unsigned int)skb->cb_next);
-+
-+              skb_restore_cb(skb);
-+      }
-+      /* This should not happen either, nf_queue_entry is nullified in
-+       * imq_dev_xmit(). If we have non-NULL nf_queue_entry then we are
-+       * leaking entry pointers, maybe memory. We don't know if this is
-+       * pointer to already freed memory, or should this be freed.
-+       * If this happens we need to add refcounting, etc for nf_queue_entry.
-+       */
-+      if (skb->nf_queue_entry && net_ratelimit())
-+              printk(KERN_WARNING
-+                              "IMQ: kfree_skb: skb->nf_queue_entry != NULL");
-+#endif
- #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
-       nf_conntrack_put(skb->nfct);
-       nf_conntrack_put_reasm(skb->nfct_reasm);
-@@ -538,6 +638,9 @@ static void __copy_skb_header(struct sk_
-       new->sp                 = secpath_get(old->sp);
- #endif
-       memcpy(new->cb, old->cb, sizeof(old->cb));
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      skb_copy_stored_cb(new, old);
-+#endif
-       new->csum               = old->csum;
-       new->local_df           = old->local_df;
-       new->pkt_type           = old->pkt_type;
-@@ -2780,6 +2883,13 @@ void __init skb_init(void)
-                                               0,
-                                               SLAB_HWCACHE_ALIGN|SLAB_PANIC,
-                                               NULL);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      skbuff_cb_store_cache = kmem_cache_create("skbuff_cb_store_cache",
-+                                                sizeof(struct skb_cb_table),
-+                                                0,
-+                                                SLAB_HWCACHE_ALIGN|SLAB_PANIC,
-+                                                NULL);
-+#endif
- }
- /**
---- a/net/netfilter/Kconfig
-+++ b/net/netfilter/Kconfig
-@@ -421,6 +421,18 @@ config NETFILTER_XT_TARGET_LED
-         For more information on the LEDs available on your system, see
-         Documentation/leds-class.txt
-+config NETFILTER_XT_TARGET_IMQ
-+        tristate '"IMQ" target support'
-+      depends on NETFILTER_XTABLES
-+      depends on IP_NF_MANGLE || IP6_NF_MANGLE
-+      select IMQ
-+      default m if NETFILTER_ADVANCED=n
-+        help
-+          This option adds a `IMQ' target which is used to specify if and
-+          to which imq device packets should get enqueued/dequeued.
-+
-+          To compile it as a module, choose M here.  If unsure, say N.
-+
- config NETFILTER_XT_TARGET_MARK
-       tristate '"MARK" target support'
-       default m if NETFILTER_ADVANCED=n
---- a/net/netfilter/Makefile
-+++ b/net/netfilter/Makefile
-@@ -47,6 +47,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSEC
- obj-$(CONFIG_NETFILTER_XT_TARGET_CT) += xt_CT.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o
-+obj-$(CONFIG_NETFILTER_XT_TARGET_IMQ) += xt_IMQ.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
---- a/net/netfilter/nf_queue.c
-+++ b/net/netfilter/nf_queue.c
-@@ -21,6 +21,26 @@ static const struct nf_queue_handler *qu
- static DEFINE_MUTEX(queue_handler_mutex);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+static const struct nf_queue_handler *queue_imq_handler;
-+
-+void nf_register_queue_imq_handler(const struct nf_queue_handler *qh)
-+{
-+      mutex_lock(&queue_handler_mutex);
-+      rcu_assign_pointer(queue_imq_handler, qh);
-+      mutex_unlock(&queue_handler_mutex);
-+}
-+EXPORT_SYMBOL(nf_register_queue_imq_handler);
-+
-+void nf_unregister_queue_imq_handler(void)
-+{
-+      mutex_lock(&queue_handler_mutex);
-+      rcu_assign_pointer(queue_imq_handler, NULL);
-+      mutex_unlock(&queue_handler_mutex);
-+}
-+EXPORT_SYMBOL(nf_unregister_queue_imq_handler);
-+#endif
-+
- /* return EBUSY when somebody else is registered, return EEXIST if the
-  * same handler is registered, return 0 in case of success. */
- int nf_register_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh)
-@@ -81,7 +101,7 @@ void nf_unregister_queue_handlers(const
- }
- EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers);
--static void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
-+void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
- {
-       /* Release those devices we held, or Alexey will kill me. */
-       if (entry->indev)
-@@ -101,6 +121,7 @@ static void nf_queue_entry_release_refs(
-       /* Drop reference to owner of hook which queued us. */
-       module_put(entry->elem->owner);
- }
-+EXPORT_SYMBOL_GPL(nf_queue_entry_release_refs);
- /*
-  * Any packet that leaves via this function must come back
-@@ -122,12 +143,26 @@ static int __nf_queue(struct sk_buff *sk
- #endif
-       const struct nf_afinfo *afinfo;
-       const struct nf_queue_handler *qh;
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      const struct nf_queue_handler *qih = NULL;
-+#endif
-       /* QUEUE == DROP if noone is waiting, to be safe. */
-       rcu_read_lock();
-       qh = rcu_dereference(queue_handler[pf]);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+      if (pf == PF_INET || pf == PF_INET6)
-+#else
-+      if (pf == PF_INET)
-+#endif
-+              qih = rcu_dereference(queue_imq_handler);
-+
-+      if (!qh && !qih)
-+#else /* !IMQ */
-       if (!qh)
-+#endif
-               goto err_unlock;
-       afinfo = nf_get_afinfo(pf);
-@@ -146,6 +181,10 @@ static int __nf_queue(struct sk_buff *sk
-               .indev  = indev,
-               .outdev = outdev,
-               .okfn   = okfn,
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+              .next_outfn = qh ? qh->outfn : NULL,
-+              .next_queuenum = queuenum,
-+#endif
-       };
-       /* If it's going away, ignore hook. */
-@@ -171,8 +210,19 @@ static int __nf_queue(struct sk_buff *sk
-       }
- #endif
-       afinfo->saveroute(skb, entry);
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      if (qih) {
-+              status = qih->outfn(entry, queuenum);
-+              goto imq_skip_queue;
-+      }
-+#endif
-+
-       status = qh->outfn(entry, queuenum);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+imq_skip_queue:
-+#endif
-       rcu_read_unlock();
-       if (status < 0) {
---- /dev/null
-+++ b/net/netfilter/xt_IMQ.c
-@@ -0,0 +1,73 @@
-+/*
-+ * This target marks packets to be enqueued to an imq device
-+ */
-+#include <linux/module.h>
-+#include <linux/skbuff.h>
-+#include <linux/netfilter/x_tables.h>
-+#include <linux/netfilter/xt_IMQ.h>
-+#include <linux/imq.h>
-+
-+static unsigned int imq_target(struct sk_buff *pskb,
-+                              const struct xt_target_param *par)
-+{
-+      const struct xt_imq_info *mr = par->targinfo;
-+
-+      pskb->imq_flags = (mr->todev & IMQ_F_IFMASK) | IMQ_F_ENQUEUE;
-+
-+      return XT_CONTINUE;
-+}
-+
-+static bool imq_checkentry(const struct xt_tgchk_param *par)
-+{
-+      struct xt_imq_info *mr = par->targinfo;
-+
-+      if (mr->todev > IMQ_MAX_DEVS - 1) {
-+              printk(KERN_WARNING
-+                     "IMQ: invalid device specified, highest is %u\n",
-+                     IMQ_MAX_DEVS - 1);
-+              return 0;
-+      }
-+
-+      return 1;
-+}
-+
-+static struct xt_target xt_imq_reg[] __read_mostly = {
-+      {
-+              .name           = "IMQ",
-+              .family         = AF_INET,
-+              .checkentry     = imq_checkentry,
-+              .target         = imq_target,
-+              .targetsize     = sizeof(struct xt_imq_info),
-+              .table          = "mangle",
-+              .me             = THIS_MODULE
-+      },
-+      {
-+              .name           = "IMQ",
-+              .family         = AF_INET6,
-+              .checkentry     = imq_checkentry,
-+              .target         = imq_target,
-+              .targetsize     = sizeof(struct xt_imq_info),
-+              .table          = "mangle",
-+              .me             = THIS_MODULE
-+      },
-+};
-+
-+static int __init imq_init(void)
-+{
-+      return xt_register_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg));
-+}
-+
-+static void __exit imq_fini(void)
-+{
-+      xt_unregister_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg));
-+}
-+
-+module_init(imq_init);
-+module_exit(imq_fini);
-+
-+MODULE_AUTHOR("http://www.linuximq.net");
-+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information.");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS("ipt_IMQ");
-+MODULE_ALIAS("ip6t_IMQ");
-+
index 1bda13d19177ac2eed3fd65304fd9cb6f03c1028..4654ea0ad75175421af6e06678d58be2cfda7cd5 100644 (file)
@@ -8,7 +8,7 @@
        depends on NETFILTER_ADVANCED
        help
          H.323 is a VoIP signalling protocol from ITU-T. As one of the most
-@@ -530,7 +529,6 @@ config NETFILTER_XT_TARGET_SECMARK
+@@ -518,7 +517,6 @@ config NETFILTER_XT_TARGET_SECMARK
  
  config NETFILTER_XT_TARGET_TCPMSS
        tristate '"TCPMSS" target support'
index e4324717b4459ce1f1009053e6317c930b01b6e4..6ea9ba51ee0d24cf3a3ac657278109d9b11de859 100644 (file)
@@ -1,6 +1,6 @@
 --- a/arch/mips/include/asm/string.h
 +++ b/arch/mips/include/asm/string.h
-@@ -133,11 +133,44 @@ strncmp(__const__ char *__cs, __const__
+@@ -133,11 +133,44 @@ strncmp(__const__ char *__cs, __const__ 
  
  #define __HAVE_ARCH_MEMSET
  extern void *memset(void *__s, int __c, size_t __count);
index fe8cecfc771ed7a1cd16d22361475b2151e8bb98..83fd6c309928d78bdbdc7db87abdd7b06383d9cd 100644 (file)
@@ -1,6 +1,6 @@
 --- a/include/linux/slab.h
 +++ b/include/linux/slab.h
-@@ -130,8 +130,8 @@ int kmem_ptr_validate(struct kmem_cache
+@@ -130,8 +130,8 @@ int kmem_ptr_validate(struct kmem_cache 
   * to do various tricks to work around compiler limitations in order to
   * ensure proper constant folding.
   */
index adbe7021dff21973b310c361429dc8b263de338c..02604632b2d9f2267dcd2af05f854cd951b802d9 100644 (file)
@@ -1,6 +1,6 @@
 --- a/include/linux/skbuff.h
 +++ b/include/linux/skbuff.h
-@@ -1372,11 +1372,18 @@ static inline int skb_network_offset(con
+@@ -1353,11 +1353,18 @@ static inline int skb_network_offset(con
   *
   * Various parts of the networking layer expect at least 32 bytes of
   * headroom, you should not reduce this.
@@ -19,7 +19,7 @@
  extern int ___pskb_trim(struct sk_buff *skb, unsigned int len);
  
  static inline void __skb_trim(struct sk_buff *skb, unsigned int len)
-@@ -1466,9 +1473,9 @@ static inline void __skb_queue_purge(str
+@@ -1447,9 +1454,9 @@ static inline void __skb_queue_purge(str
  static inline struct sk_buff *__dev_alloc_skb(unsigned int length,
                                              gfp_t gfp_mask)
  {
@@ -31,7 +31,7 @@
        return skb;
  }
  
-@@ -1551,7 +1558,7 @@ static inline int __skb_cow(struct sk_bu
+@@ -1532,7 +1539,7 @@ static inline int __skb_cow(struct sk_bu
                delta = headroom - skb_headroom(skb);
  
        if (delta || cloned)
@@ -42,7 +42,7 @@
  }
 --- a/net/core/skbuff.c
 +++ b/net/core/skbuff.c
-@@ -339,9 +339,9 @@ struct sk_buff *__netdev_alloc_skb(struc
+@@ -259,9 +259,9 @@ struct sk_buff *__netdev_alloc_skb(struc
        int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1;
        struct sk_buff *skb;
  
index b64630d50045480d022ba26c901cea68f6da66b3..d71e3b6faa6644c2337588f4b344cc5677419841 100644 (file)
@@ -61,7 +61,7 @@
  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
  extern int mini_fo_create(inode_t *dir, dentry_t *dentry, int mode, struct nameidata *nd);
  
-@@ -501,6 +505,29 @@ static inline void double_unlock(struct
+@@ -501,6 +505,29 @@ static inline void double_unlock(struct 
  #endif  /* if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) */
  #endif /* __KERNEL__ */
  
  #endif /* defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) */
 --- a/fs/mini_fo/aux.c
 +++ b/fs/mini_fo/aux.c
-@@ -164,11 +164,11 @@ dentry_t *bpath_walk(super_block_t *sb,
+@@ -164,11 +164,11 @@ dentry_t *bpath_walk(super_block_t *sb, 
        err = vfs_path_lookup(mnt->mnt_root, mnt, bpath+1, 0, &nd);
  
        /* validate */
index b5fa64e6a19e7fff343aed59f4ddccfc34578d91..8bd9ba32447e15df6ebc7153edfe89dfd38f43f6 100644 (file)
@@ -1,6 +1,6 @@
 --- a/fs/mini_fo/super.c
 +++ b/fs/mini_fo/super.c
-@@ -84,6 +84,7 @@ mini_fo_write_inode(inode_t *inode, int
+@@ -84,6 +84,7 @@ mini_fo_write_inode(inode_t *inode, int 
  #endif /* defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) */
  
  
index 1dc655007e5bfb1be257a0d3bcf56b4cce8bbd08..d851d313ee8dd84f8232e3c7bb272fc420ad02a1 100644 (file)
@@ -20,7 +20,7 @@
  #else
  static inline int kobject_uevent(struct kobject *kobj,
                                 enum kobject_action action)
-@@ -224,6 +230,16 @@ static inline int add_uevent_var(struct
+@@ -224,6 +230,16 @@ static inline int add_uevent_var(struct 
  static inline int kobject_action_type(const char *buf, size_t count,
                                      enum kobject_action *type)
  { return -EINVAL; }
index e02d1bc317605baa14ba2173cc9687c8956cc506..286bdaec98b64a9d1e19d19e3a1ec375ff61b39a 100644 (file)
 +module_exit(connmark_cleanup_module);
 --- a/net/sched/Kconfig
 +++ b/net/sched/Kconfig
-@@ -549,6 +549,18 @@
+@@ -549,6 +549,18 @@ config NET_ACT_SKBEDIT
          To compile this code as a module, choose M here: the
          module will be called act_skbedit.
  
        depends on NET_CLS_U32 || NET_CLS_FW
 --- a/net/sched/Makefile
 +++ b/net/sched/Makefile
-@@ -15,6 +15,7 @@
+@@ -15,6 +15,7 @@ obj-$(CONFIG_NET_ACT_NAT)    += act_nat.o
  obj-$(CONFIG_NET_ACT_PEDIT)   += act_pedit.o
  obj-$(CONFIG_NET_ACT_SIMP)    += act_simple.o
  obj-$(CONFIG_NET_ACT_SKBEDIT) += act_skbedit.o
index 3f43c90acad3a2ca7e882a88595c72228cf4aed8..4060e65d8cf285dd770532150378b48241852bfd 100644 (file)
@@ -11,7 +11,7 @@
  endif # NEW_LEDS
 --- a/drivers/leds/Makefile
 +++ b/drivers/leds/Makefile
-@@ -46,3 +46,4 @@ obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) +=
+@@ -46,3 +46,4 @@ obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += 
  obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT)  += ledtrig-backlight.o
  obj-$(CONFIG_LEDS_TRIGGER_GPIO)               += ledtrig-gpio.o
  obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
index 001524681e85e13de2804d4b02c5e977ed94d37d..d2ceb087d7bd9e5b96ef069000f57929cd806b6c 100644 (file)
@@ -14,7 +14,7 @@
  endif # NEW_LEDS
 --- a/drivers/leds/Makefile
 +++ b/drivers/leds/Makefile
-@@ -47,3 +47,4 @@ obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) +=
+@@ -47,3 +47,4 @@ obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) += 
  obj-$(CONFIG_LEDS_TRIGGER_GPIO)               += ledtrig-gpio.o
  obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
  obj-$(CONFIG_LEDS_TRIGGER_MORSE)      += ledtrig-morse.o
index c334b17d0872a877f52cd9c0e4234ad118df7d09..5c70e79a058d050e90224ac0ef80dcb1180235ab 100644 (file)
                        dev->checkpointBlockList[i] = -1;
        }
  
-@@ -191,18 +185,17 @@ int yaffs_GetCheckpointSum(yaffs_Device
+@@ -191,18 +185,17 @@ int yaffs_GetCheckpointSum(yaffs_Device 
  
  static int yaffs_CheckpointFlushBuffer(yaffs_Device *dev)
  {
  {
        unsigned char cDelta;   /* column parity delta */
        unsigned lDelta;        /* line parity delta */
-@@ -294,8 +292,7 @@ int yaffs_ECCCorrectOther(unsigned char
+@@ -294,8 +292,7 @@ int yaffs_ECCCorrectOther(unsigned char 
                return 0; /* no error */
  
        if (lDelta == ~lDeltaPrime &&
                /* Single bit (recoverable) error in data */
  
                bit = 0;
-@@ -307,7 +304,7 @@ int yaffs_ECCCorrectOther(unsigned char
+@@ -307,7 +304,7 @@ int yaffs_ECCCorrectOther(unsigned char 
                if (cDelta & 0x02)
                        bit |= 0x01;
  
                        return -1;
  
                data[lDelta] ^= (1 << bit);
-@@ -316,7 +313,7 @@ int yaffs_ECCCorrectOther(unsigned char
+@@ -316,7 +313,7 @@ int yaffs_ECCCorrectOther(unsigned char 
        }
  
        if ((yaffs_CountBits32(lDelta) + yaffs_CountBits32(lDeltaPrime) +
                /* Reccoverable error in ecc */
  
                *read_ecc = *test_ecc;
-@@ -326,6 +323,4 @@ int yaffs_ECCCorrectOther(unsigned char
+@@ -326,6 +323,4 @@ int yaffs_ECCCorrectOther(unsigned char 
        /* Unrecoverable error */
  
        return -1;
  {
        unsigned char *alias;
        int ret;
-@@ -329,7 +395,7 @@ static int yaffs_readlink(struct dentry
+@@ -329,7 +395,7 @@ static int yaffs_readlink(struct dentry 
        return ret;
  }
  
  static int yaffs_file_flush(struct file *file, fl_owner_t id)
  #else
  static int yaffs_file_flush(struct file *file)
-@@ -513,8 +579,8 @@ static int yaffs_file_flush(struct file
+@@ -513,8 +579,8 @@ static int yaffs_file_flush(struct file 
        yaffs_Device *dev = obj->myDev;
  
        T(YAFFS_TRACE_OS,
  
        yaffs_GrossLock(dev);
  
-@@ -535,15 +601,15 @@ static int yaffs_readpage_nolock(struct
+@@ -535,15 +601,15 @@ static int yaffs_readpage_nolock(struct 
  
        yaffs_Device *dev;
  
        BUG_ON(!PageLocked(pg));
  #else
        if (!PageLocked(pg))
-@@ -555,9 +621,9 @@ static int yaffs_readpage_nolock(struct
+@@ -555,9 +621,9 @@ static int yaffs_readpage_nolock(struct 
  
        yaffs_GrossLock(dev);
  
  
        yaffs_GrossUnlock(dev);
  
-@@ -575,7 +641,7 @@ static int yaffs_readpage_nolock(struct
+@@ -575,7 +641,7 @@ static int yaffs_readpage_nolock(struct 
        flush_dcache_page(pg);
        kunmap(pg);
  
                if (n < step) {
                        n++;
                        continue;
-@@ -2119,7 +2356,7 @@ static int yaffs_proc_write(struct file
+@@ -2119,7 +2356,7 @@ static int yaffs_proc_write(struct file 
        char *end;
        char *mask_name;
        const char *x;
        int i;
        int done = 0;
        int add, len = 0;
-@@ -2129,9 +2366,8 @@ static int yaffs_proc_write(struct file
+@@ -2129,9 +2366,8 @@ static int yaffs_proc_write(struct file 
  
        while (!done && (pos < count)) {
                done = 1;
  
                switch (buf[pos]) {
                case '+':
-@@ -2148,20 +2384,21 @@ static int yaffs_proc_write(struct file
+@@ -2148,20 +2384,21 @@ static int yaffs_proc_write(struct file 
                mask_name = NULL;
  
                mask_bitfield = simple_strtoul(buf + pos, &end, 0);
                                        mask_name = mask_flags[i].mask_name;
                                        mask_bitfield = mask_flags[i].mask_bitfield;
                                        done = 0;
-@@ -2172,7 +2409,7 @@ static int yaffs_proc_write(struct file
+@@ -2172,7 +2409,7 @@ static int yaffs_proc_write(struct file 
  
                if (mask_name != NULL) {
                        done = 0;
                        case '-':
                                rg &= ~mask_bitfield;
                                break;
-@@ -2191,13 +2428,13 @@ static int yaffs_proc_write(struct file
+@@ -2191,13 +2428,13 @@ static int yaffs_proc_write(struct file 
  
        yaffs_traceMask = rg | YAFFS_TRACE_ALWAYS;
  
  {
        /* Get the real object in case we were fed a hard link as an equivalent object */
        equivalentObject = yaffs_GetEquivalentObject(equivalentObject);
-@@ -2363,33 +2396,31 @@ yaffs_Object *yaffs_Link(yaffs_Object *
+@@ -2363,33 +2396,31 @@ yaffs_Object *yaffs_Link(yaffs_Object * 
  
  }
  
        int nToCopy;
        int n = nBytes;
        int nDone = 0;
-@@ -4600,27 +4665,26 @@ int yaffs_ReadDataFromFile(yaffs_Object
+@@ -4600,27 +4665,26 @@ int yaffs_ReadDataFromFile(yaffs_Object 
        dev = in->myDev;
  
        while (n > 0) {
                        if (dev->nShortOpCaches > 0) {
  
                                /* If we can't find the data in the cache, then load it up. */
-@@ -4641,14 +4705,9 @@ int yaffs_ReadDataFromFile(yaffs_Object
+@@ -4641,14 +4705,9 @@ int yaffs_ReadDataFromFile(yaffs_Object 
  
                                cache->locked = 1;
  
                                cache->locked = 0;
                        } else {
                                /* Read into the local buffer then copy..*/
-@@ -4657,41 +4716,19 @@ int yaffs_ReadDataFromFile(yaffs_Object
+@@ -4657,41 +4716,19 @@ int yaffs_ReadDataFromFile(yaffs_Object 
                                    yaffs_GetTempBuffer(dev, __LINE__);
                                yaffs_ReadChunkDataFromObject(in, chunk,
                                                              localBuffer);
                }
  
                n -= nToCopy;
-@@ -4704,28 +4741,37 @@ int yaffs_ReadDataFromFile(yaffs_Object
+@@ -4704,28 +4741,37 @@ int yaffs_ReadDataFromFile(yaffs_Object 
        return nDone;
  }
  
        int newFullChunks;
  
        yaffs_Device *dev = in->myDev;
-@@ -4955,13 +4981,11 @@ int yaffs_ResizeFile(yaffs_Object * in,
+@@ -4955,13 +4981,11 @@ int yaffs_ResizeFile(yaffs_Object * in, 
  
        yaffs_CheckGarbageCollection(dev);
  
  
        if (newSize < oldFileSize) {
  
-@@ -4994,21 +5018,20 @@ int yaffs_ResizeFile(yaffs_Object * in,
+@@ -4994,21 +5018,20 @@ int yaffs_ResizeFile(yaffs_Object * in, 
        }
  
  
  {
        obj = yaffs_GetEquivalentObject(obj);
  
-@@ -5024,7 +5047,7 @@ loff_t yaffs_GetFileSize(yaffs_Object *
+@@ -5024,7 +5047,7 @@ loff_t yaffs_GetFileSize(yaffs_Object * 
  
  
  
  {
        int init_failed = 0;
        unsigned x;
-@@ -7040,6 +7126,8 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7040,6 +7126,8 @@ int yaffs_GutsInitialise(yaffs_Device * 
        dev->chunkOffset = 0;
        dev->nFreeChunks = 0;
  
        if (dev->startBlock == 0) {
                dev->internalStartBlock = dev->startBlock + 1;
                dev->internalEndBlock = dev->endBlock + 1;
-@@ -7049,18 +7137,18 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7049,18 +7137,18 @@ int yaffs_GutsInitialise(yaffs_Device * 
  
        /* Check geometry parameters. */
  
                return YAFFS_FAIL;
        }
  
-@@ -7070,6 +7158,12 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7070,6 +7158,12 @@ int yaffs_GutsInitialise(yaffs_Device * 
                return YAFFS_FAIL;
        }
  
        /* Got the right mix of functions? */
        if (!yaffs_CheckDevFunctions(dev)) {
                /* Function missing */
-@@ -7097,31 +7191,18 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7097,31 +7191,18 @@ int yaffs_GutsInitialise(yaffs_Device * 
  
        dev->isMounted = 1;
  
  
        /*
         * Calculate chunkGroupBits.
-@@ -7133,16 +7214,15 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7133,16 +7214,15 @@ int yaffs_GutsInitialise(yaffs_Device * 
        bits = ShiftsGE(x);
  
        /* Set up tnode width if wide tnodes are enabled. */
                dev->tnodeWidth = 16;
  
        dev->tnodeMask = (1<<dev->tnodeWidth)-1;
-@@ -7193,7 +7273,7 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7193,7 +7273,7 @@ int yaffs_GutsInitialise(yaffs_Device * 
        dev->hasPendingPrioritisedGCs = 1; /* Assume the worst for now, will get fixed on first GC */
  
        /* Initialise temporary buffers and caches. */
                init_failed = 1;
  
        dev->srCache = NULL;
-@@ -7203,25 +7283,26 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7203,25 +7283,26 @@ int yaffs_GutsInitialise(yaffs_Device * 
        if (!init_failed &&
            dev->nShortOpCaches > 0) {
                int i;
                        init_failed = 1;
  
                dev->srLastUse = 0;
-@@ -7229,29 +7310,30 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7229,29 +7310,30 @@ int yaffs_GutsInitialise(yaffs_Device * 
  
        dev->cacheHits = 0;
  
                                T(YAFFS_TRACE_ALWAYS,
                                  (TSTR("yaffs: restored from checkpoint" TENDSTR)));
                        } else {
-@@ -7273,24 +7355,25 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7273,24 +7355,25 @@ int yaffs_GutsInitialise(yaffs_Device * 
                                dev->nBackgroundDeletions = 0;
                                dev->oldestDirtySequence = 0;
  
                /* Clean up the mess */
                T(YAFFS_TRACE_TRACING,
                  (TSTR("yaffs: yaffs_GutsInitialise() aborted.\n" TENDSTR)));
-@@ -7318,7 +7401,7 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7318,7 +7401,7 @@ int yaffs_GutsInitialise(yaffs_Device * 
  
  }
  
  {
        if (etags) {
                memset(etags, 0, sizeof(*etags));
-@@ -169,9 +169,9 @@ static int rettags(yaffs_ExtendedTags *
+@@ -169,9 +169,9 @@ static int rettags(yaffs_ExtendedTags * 
   * Returns YAFFS_OK or YAFFS_FAIL.
   */
  int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device *dev,
 +                      yaffs_UnpackTags2(tags, &pt);
 +              }
 +      }
-+
+-      if(tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR)
+-              tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
 +      if (localData)
 +              yaffs_ReleaseTempBuffer(dev, data, __LINE__);
  
--      if(tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR)
 +      if (tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR)
-               tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
--
++              tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
        if (retval == 0)
                return YAFFS_OK;
        else
index 8aa43c52421f967dba199fd0de13f85cb816e42d..b7e28d2cdbacda6fb9864a1ad3f0767510017688 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/hostap/hostap_ap.c
 +++ b/drivers/net/wireless/hostap/hostap_ap.c
-@@ -2336,13 +2336,13 @@ int prism2_ap_get_sta_qual(local_info_t
+@@ -2336,13 +2336,13 @@ int prism2_ap_get_sta_qual(local_info_t 
                addr[count].sa_family = ARPHRD_ETHER;
                memcpy(addr[count].sa_data, sta->addr, ETH_ALEN);
                if (sta->last_rx_silence == 0)
index bda63729c7f32c3d54b7734c621ee44bdcd60cc6..ccf01bd42a2a3b7ef0e99ec6f7413e20e75d1f5e 100644 (file)
@@ -24,7 +24,7 @@
   * All of these routines try to estimate how many bits of randomness a
   * particular randomness source.  They do this by keeping track of the
   * first and second order deltas of the event timings.
-@@ -714,6 +724,61 @@ void add_disk_randomness(struct gendisk
+@@ -714,6 +724,61 @@ void add_disk_randomness(struct gendisk 
  }
  #endif
  
index 2a5b0cd954c6a6c9bdfeb87e4e4dc83f37a270ba..e9b06d06bf00d1cdb1a262e37d09cf4000ab6657 100644 (file)
        u32 pmucap;
  
        if (!(cc->capabilities & SSB_CHIPCO_CAP_PMU))
-@@ -516,15 +516,12 @@ void ssb_pmu_init(struct ssb_chipcommon
+@@ -516,15 +516,12 @@ void ssb_pmu_init(struct ssb_chipcommon 
        ssb_dprintk(KERN_DEBUG PFX "Found rev %u PMU (capabilities 0x%08X)\n",
                    cc->pmu.rev, pmucap);
  
index 63834d65ea1cc2f470ff363942502a8035f57988..0ac880caeab34f3fc2cbe84c298b9fc548daf71d 100644 (file)
@@ -1,6 +1,6 @@
 --- a/scripts/Makefile.lib
 +++ b/scripts/Makefile.lib
-@@ -238,7 +238,7 @@ cmd_bzip2 = (cat $(filter-out FORCE,$^)
+@@ -238,7 +238,7 @@ cmd_bzip2 = (cat $(filter-out FORCE,$^) 
  
  quiet_cmd_lzma = LZMA    $@
  cmd_lzma = (cat $(filter-out FORCE,$^) | \
index cd4da2c2ad7acf37ac269ead841d2ff65ea97bb4..1b028edd982c75a709e8273d4f5646f52b0943d3 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/mtd/chips/cfi_cmdset_0002.c
 +++ b/drivers/mtd/chips/cfi_cmdset_0002.c
-@@ -372,6 +372,8 @@ static struct cfi_fixup fixup_table[] =
+@@ -372,6 +372,8 @@ static struct cfi_fixup fixup_table[] = 
  static void cfi_fixup_major_minor(struct cfi_private *cfi,
                                  struct cfi_pri_amdstd *extp)
  {
@@ -9,7 +9,7 @@
        if (cfi->mfr == CFI_MFR_SAMSUNG && cfi->id == 0x257e &&
            extp->MajorVersion == '0')
                extp->MajorVersion = '1';
-@@ -404,6 +406,9 @@ struct mtd_info *cfi_cmdset_0002(struct
+@@ -404,6 +406,9 @@ struct mtd_info *cfi_cmdset_0002(struct 
  
        mtd->reboot_notifier.notifier_call = cfi_amdstd_reboot;
  
@@ -19,7 +19,7 @@
        if (cfi->cfi_mode==CFI_MODE_CFI){
                unsigned char bootloc;
                __u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR;
-@@ -417,16 +422,24 @@ struct mtd_info *cfi_cmdset_0002(struct
+@@ -417,16 +422,24 @@ struct mtd_info *cfi_cmdset_0002(struct 
                         */
                        cfi_fixup_major_minor(cfi, extp);
  
index 83e24451c1c952088afd9c4e91b2c65f8707b27e..ca0c10b20dbbcf35f71f402f8b4b219f167a3ea7 100644 (file)
  
  unsigned int vced_count, vcei_count;
  
-@@ -31,8 +32,12 @@ static int show_cpuinfo(struct seq_file
+@@ -31,8 +32,12 @@ static int show_cpuinfo(struct seq_file 
        /*
         * For the first processor also print the system type
         */
index 014bb256a40392253596db3ef22061f56811d852..c00886e5936d89925497ef1c6c39e5118dfd8ab7 100644 (file)
@@ -81,7 +81,7 @@
  htc_excalibur_s620    MACH_HTC_EXCALIBUR_S620 HTC_EXCALIBUR_S620      2391
  htc_opal              MACH_HTC_OPAL           HTC_OPAL                2392
  touchbook             MACH_TOUCHBOOK          TOUCHBOOK               2393
-@@ -2446,7 +2446,7 @@ siogentoo1               MACH_SIOGENTOO1         SIOGENTOO1
+@@ -2446,7 +2446,7 @@ siogentoo1               MACH_SIOGENTOO1         SIOGENTOO1      
  siogentoo2            MACH_SIOGENTOO2         SIOGENTOO2              2459
  sm3k                  MACH_SM3K               SM3K                    2460
  acer_tempo_f900               MACH_ACER_TEMPO_F900    ACER_TEMPO_F900         2461
index ed23fbbc1f3c4c81fec93c4ff7c71535798b2fc1..a6766de466dbcb55015139922d78b33ed2b9acc3 100644 (file)
  
  #include <asm/uaccess.h>
  
-@@ -826,6 +827,13 @@ static int mtd_ioctl(struct file *file,
+@@ -826,6 +827,13 @@ static int mtd_ioctl(struct file *file, 
                file->f_pos = 0;
                break;
        }
index 39ff04ad958d7446777b41c0adaa807c8b785422..fa1274c3b9de5d2936a83f35baf6b28130d9d4fa 100644 (file)
@@ -71,7 +71,7 @@
        depends on NETFILTER_ADVANCED
 --- a/net/netfilter/Makefile
 +++ b/net/netfilter/Makefile
-@@ -91,6 +91,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_RECENT)
+@@ -91,6 +91,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_RECENT) 
  obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o
  obj-$(CONFIG_NETFILTER_XT_MATCH_SOCKET) += xt_socket.o
  obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o
index cd840cdc21f0baddc6064a3319e8093eaa49e73e..7affbb1221bac8177e0e3c11ba098097688191a2 100644 (file)
  
                e = (struct ipt_entry *)(loc_cpu_entry + off);
                if (copy_to_user(userptr + off
-@@ -979,6 +1020,14 @@ copy_entries_to_user(unsigned int total_
-                       ret = -EFAULT;
+@@ -980,6 +1021,14 @@ copy_entries_to_user(unsigned int total_
                        goto free_counters;
                }
-+
 +              flags = e->ip.flags & ~IPT_F_NO_DEF_MATCH;
 +              if (copy_to_user(userptr + off
 +                               + offsetof(struct ipt_entry, ip.flags),
 +                      ret = -EFAULT;
 +                      goto free_counters;
 +              }
++
                for (i = sizeof(struct ipt_entry);
                     i < e->target_offset;
+                    i += m->u.match_size) {
diff --git a/target/linux/generic/patches-2.6.35/150-netfilter_imq.patch b/target/linux/generic/patches-2.6.35/150-netfilter_imq.patch
deleted file mode 100644 (file)
index 0195470..0000000
+++ /dev/null
@@ -1,1342 +0,0 @@
---- /dev/null
-+++ b/drivers/net/imq.c
-@@ -0,0 +1,638 @@
-+/*
-+ *             Pseudo-driver for the intermediate queue device.
-+ *
-+ *             This program is free software; you can redistribute it and/or
-+ *             modify it under the terms of the GNU General Public License
-+ *             as published by the Free Software Foundation; either version
-+ *             2 of the License, or (at your option) any later version.
-+ *
-+ * Authors:    Patrick McHardy, <kaber@trash.net>
-+ *
-+ *            The first version was written by Martin Devera, <devik@cdi.cz>
-+ *
-+ * Credits:    Jan Rafaj <imq2t@cedric.vabo.cz>
-+ *              - Update patch to 2.4.21
-+ *             Sebastian Strollo <sstrollo@nortelnetworks.com>
-+ *              - Fix "Dead-loop on netdevice imq"-issue
-+ *             Marcel Sebek <sebek64@post.cz>
-+ *              - Update to 2.6.2-rc1
-+ *
-+ *           After some time of inactivity there is a group taking care
-+ *           of IMQ again: http://www.linuximq.net
-+ *
-+ *
-+ *           2004/06/30 - New version of IMQ patch to kernels <=2.6.7
-+ *             including the following changes:
-+ *
-+ *           - Correction of ipv6 support "+"s issue (Hasso Tepper)
-+ *           - Correction of imq_init_devs() issue that resulted in
-+ *           kernel OOPS unloading IMQ as module (Norbert Buchmuller)
-+ *           - Addition of functionality to choose number of IMQ devices
-+ *           during kernel config (Andre Correa)
-+ *           - Addition of functionality to choose how IMQ hooks on
-+ *           PRE and POSTROUTING (after or before NAT) (Andre Correa)
-+ *           - Cosmetic corrections (Norbert Buchmuller) (Andre Correa)
-+ *
-+ *
-+ *             2005/12/16 - IMQ versions between 2.6.7 and 2.6.13 were
-+ *             released with almost no problems. 2.6.14-x was released
-+ *             with some important changes: nfcache was removed; After
-+ *             some weeks of trouble we figured out that some IMQ fields
-+ *             in skb were missing in skbuff.c - skb_clone and copy_skb_header.
-+ *             These functions are correctly patched by this new patch version.
-+ *
-+ *             Thanks for all who helped to figure out all the problems with
-+ *             2.6.14.x: Patrick McHardy, Rune Kock, VeNoMouS, Max CtRiX,
-+ *             Kevin Shanahan, Richard Lucassen, Valery Dachev (hopefully
-+ *             I didn't forget anybody). I apologize again for my lack of time.
-+ *
-+ *
-+ *             2008/06/17 - 2.6.25 - Changed imq.c to use qdisc_run() instead 
-+ *             of qdisc_restart() and moved qdisc_run() to tasklet to avoid
-+ *             recursive locking. New initialization routines to fix 'rmmod' not
-+ *             working anymore. Used code from ifb.c. (Jussi Kivilinna)
-+ *
-+ *             2008/08/06 - 2.6.26 - (JK)
-+ *              - Replaced tasklet with 'netif_schedule()'.
-+ *              - Cleaned up and added comments for imq_nf_queue().
-+ *
-+ *             2009/04/12
-+ *              - Add skb_save_cb/skb_restore_cb helper functions for backuping
-+ *                control buffer. This is needed because qdisc-layer on kernels
-+ *                2.6.27 and newer overwrite control buffer. (Jussi Kivilinna)
-+ *              - Add better locking for IMQ device. Hopefully this will solve
-+ *                SMP issues. (Jussi Kivilinna)
-+ *              - Port to 2.6.27
-+ *              - Port to 2.6.28
-+ *              - Port to 2.6.29 + fix rmmod not working
-+ *
-+ *             2009/04/20 - (Jussi Kivilinna)
-+ *              - Use netdevice feature flags to avoid extra packet handling
-+ *                by core networking layer and possibly increase performance.
-+ *
-+ *             2009/09/26 - (Jussi Kivilinna)
-+ *              - Add imq_nf_reinject_lockless to fix deadlock with
-+ *                imq_nf_queue/imq_nf_reinject.
-+ *
-+ *             2009/12/08 - (Jussi Kivilinna)
-+ *              - Port to 2.6.32
-+ *              - Add check for skb->nf_queue_entry==NULL in imq_dev_xmit()
-+ *              - Also add better error checking for skb->nf_queue_entry usage
-+ *
-+ *             2010/02/25 - (Jussi Kivilinna)
-+ *              - Port to 2.6.33
-+ *
-+ *             2010/08/12 - (Jussi Kivilinna)
-+ *              - Port to 2.6.35
-+ *
-+ *           Also, many thanks to pablo Sebastian Greco for making the initial
-+ *           patch and to those who helped the testing.
-+ *
-+ *             More info at: http://www.linuximq.net/ (Andre Correa)
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/moduleparam.h>
-+#include <linux/list.h>
-+#include <linux/skbuff.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/rtnetlink.h>
-+#include <linux/if_arp.h>
-+#include <linux/netfilter.h>
-+#include <linux/netfilter_ipv4.h>
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+      #include <linux/netfilter_ipv6.h>
-+#endif
-+#include <linux/imq.h>
-+#include <net/pkt_sched.h>
-+#include <net/netfilter/nf_queue.h>
-+
-+static nf_hookfn imq_nf_hook;
-+
-+static struct nf_hook_ops imq_ingress_ipv4 = {
-+      .hook           = imq_nf_hook,
-+      .owner          = THIS_MODULE,
-+      .pf             = PF_INET,
-+      .hooknum        = NF_INET_PRE_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+      .priority       = NF_IP_PRI_MANGLE + 1
-+#else
-+      .priority       = NF_IP_PRI_NAT_DST + 1
-+#endif
-+};
-+
-+static struct nf_hook_ops imq_egress_ipv4 = {
-+      .hook           = imq_nf_hook,
-+      .owner          = THIS_MODULE,
-+      .pf             = PF_INET,
-+      .hooknum        = NF_INET_POST_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
-+      .priority       = NF_IP_PRI_LAST
-+#else
-+      .priority       = NF_IP_PRI_NAT_SRC - 1
-+#endif
-+};
-+
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+static struct nf_hook_ops imq_ingress_ipv6 = {
-+      .hook           = imq_nf_hook,
-+      .owner          = THIS_MODULE,
-+      .pf             = PF_INET6,
-+      .hooknum        = NF_INET_PRE_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+      .priority       = NF_IP6_PRI_MANGLE + 1
-+#else
-+      .priority       = NF_IP6_PRI_NAT_DST + 1
-+#endif
-+};
-+
-+static struct nf_hook_ops imq_egress_ipv6 = {
-+      .hook           = imq_nf_hook,
-+      .owner          = THIS_MODULE,
-+      .pf             = PF_INET6,
-+      .hooknum        = NF_INET_POST_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
-+      .priority       = NF_IP6_PRI_LAST
-+#else
-+      .priority       = NF_IP6_PRI_NAT_SRC - 1
-+#endif
-+};
-+#endif
-+
-+#if defined(CONFIG_IMQ_NUM_DEVS)
-+static unsigned int numdevs = CONFIG_IMQ_NUM_DEVS;
-+#else
-+static unsigned int numdevs = IMQ_MAX_DEVS;
-+#endif
-+
-+static DEFINE_SPINLOCK(imq_nf_queue_lock);
-+
-+static struct net_device *imq_devs_cache[IMQ_MAX_DEVS];
-+
-+
-+static struct net_device_stats *imq_get_stats(struct net_device *dev)
-+{
-+      return &dev->stats;
-+}
-+
-+/* called for packets kfree'd in qdiscs at places other than enqueue */
-+static void imq_skb_destructor(struct sk_buff *skb)
-+{
-+      struct nf_queue_entry *entry = skb->nf_queue_entry;
-+
-+      skb->nf_queue_entry = NULL;
-+
-+      if (entry) {
-+              nf_queue_entry_release_refs(entry);
-+              kfree(entry);
-+      }
-+
-+      skb_restore_cb(skb); /* kfree backup */
-+}
-+
-+/* locking not needed when called from imq_nf_queue */
-+static void imq_nf_reinject_lockless(struct nf_queue_entry *entry,
-+                                              unsigned int verdict)
-+{
-+      int status;
-+
-+      if (!entry->next_outfn) {
-+              nf_reinject(entry, verdict);
-+              return;
-+      }
-+
-+      status = entry->next_outfn(entry, entry->next_queuenum);
-+      if (status < 0) {
-+              nf_queue_entry_release_refs(entry);
-+              kfree_skb(entry->skb);
-+              kfree(entry);
-+      }
-+}
-+
-+static void imq_nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
-+{
-+      int status;
-+
-+      if (!entry->next_outfn) {
-+              spin_lock_bh(&imq_nf_queue_lock);
-+              nf_reinject(entry, verdict);
-+              spin_unlock_bh(&imq_nf_queue_lock);
-+              return;
-+      }
-+
-+      rcu_read_lock();
-+      local_bh_disable();
-+      status = entry->next_outfn(entry, entry->next_queuenum);
-+      local_bh_enable();
-+      if (status < 0) {
-+              nf_queue_entry_release_refs(entry);
-+              kfree_skb(entry->skb);
-+              kfree(entry);
-+      }
-+
-+      rcu_read_unlock();
-+}
-+
-+static netdev_tx_t imq_dev_xmit(struct sk_buff *skb, struct net_device *dev)
-+{
-+      struct nf_queue_entry *entry = skb->nf_queue_entry;
-+
-+      skb->nf_queue_entry = NULL;
-+      dev->trans_start = jiffies;
-+
-+      dev->stats.tx_bytes += skb->len;
-+      dev->stats.tx_packets++;
-+
-+      if (entry == NULL) {
-+              /* We don't know what is going on here.. packet is queued for
-+               * imq device, but (probably) not by us.
-+               *
-+               * If this packet was not send here by imq_nf_queue(), then
-+               * skb_save_cb() was not used and skb_free() should not show:
-+               *   WARNING: IMQ: kfree_skb: skb->cb_next:..
-+               * and/or
-+               *   WARNING: IMQ: kfree_skb: skb->nf_queue_entry...
-+               *
-+               * However if this message is shown, then IMQ is somehow broken
-+               * and you should report this to linuximq.net.
-+               */
-+
-+              /* imq_dev_xmit is black hole that eats all packets, report that
-+               * we eat this packet happily and increase dropped counters.
-+               */
-+
-+              dev->stats.tx_dropped++;
-+              dev_kfree_skb(skb);
-+
-+              return NETDEV_TX_OK;
-+      }
-+
-+      skb_restore_cb(skb); /* restore skb->cb */
-+
-+      skb->imq_flags = 0;
-+      skb->destructor = NULL;
-+
-+      imq_nf_reinject(entry, NF_ACCEPT);
-+
-+      return NETDEV_TX_OK;
-+}
-+
-+static int imq_nf_queue(struct nf_queue_entry *entry, unsigned queue_num)
-+{
-+      struct net_device *dev;
-+      struct sk_buff *skb_orig, *skb, *skb_shared;
-+      struct Qdisc *q;
-+      struct netdev_queue *txq;
-+      int users, index;
-+      int retval = -EINVAL;
-+
-+      index = entry->skb->imq_flags & IMQ_F_IFMASK;
-+      if (unlikely(index > numdevs - 1)) {
-+              if (net_ratelimit())
-+                      printk(KERN_WARNING
-+                             "IMQ: invalid device specified, highest is %u\n",
-+                             numdevs - 1);
-+              retval = -EINVAL;
-+              goto out;
-+      }
-+
-+      /* check for imq device by index from cache */
-+      dev = imq_devs_cache[index];
-+      if (unlikely(!dev)) {
-+              char buf[8];
-+
-+              /* get device by name and cache result */
-+              snprintf(buf, sizeof(buf), "imq%d", index);
-+              dev = dev_get_by_name(&init_net, buf);
-+              if (!dev) {
-+                      /* not found ?!*/
-+                      BUG();
-+                      retval = -ENODEV;
-+                      goto out;
-+              }
-+
-+              imq_devs_cache[index] = dev;
-+              dev_put(dev);
-+      }
-+
-+      if (unlikely(!(dev->flags & IFF_UP))) {
-+              entry->skb->imq_flags = 0;
-+              imq_nf_reinject_lockless(entry, NF_ACCEPT);
-+              retval = 0;
-+              goto out;
-+      }
-+      dev->last_rx = jiffies;
-+
-+      skb = entry->skb;
-+      skb_orig = NULL;
-+
-+      /* skb has owner? => make clone */
-+      if (unlikely(skb->destructor)) {
-+              skb_orig = skb;
-+              skb = skb_clone(skb, GFP_ATOMIC);
-+              if (!skb) {
-+                      retval = -ENOMEM;
-+                      goto out;
-+              }
-+              entry->skb = skb;
-+      }
-+
-+      skb->nf_queue_entry = entry;
-+
-+      dev->stats.rx_bytes += skb->len;
-+      dev->stats.rx_packets++;
-+
-+      txq = dev_pick_tx(dev, skb);
-+
-+      q = rcu_dereference(txq->qdisc);
-+      if (unlikely(!q->enqueue))
-+              goto packet_not_eaten_by_imq_dev;
-+
-+      spin_lock_bh(qdisc_lock(q));
-+
-+      users = atomic_read(&skb->users);
-+
-+      skb_shared = skb_get(skb); /* increase reference count by one */
-+      skb_save_cb(skb_shared); /* backup skb->cb, as qdisc layer will
-+                                      overwrite it */
-+      qdisc_enqueue_root(skb_shared, q); /* might kfree_skb */
-+
-+      if (likely(atomic_read(&skb_shared->users) == users + 1)) {
-+              kfree_skb(skb_shared); /* decrease reference count by one */
-+
-+              skb->destructor = &imq_skb_destructor;
-+
-+              /* cloned? */
-+              if (skb_orig)
-+                      kfree_skb(skb_orig); /* free original */
-+
-+              spin_unlock_bh(qdisc_lock(q));
-+
-+              /* schedule qdisc dequeue */
-+              __netif_schedule(q);
-+
-+              retval = 0;
-+              goto out;
-+      } else {
-+              skb_restore_cb(skb_shared); /* restore skb->cb */
-+              skb->nf_queue_entry = NULL;
-+              /* qdisc dropped packet and decreased skb reference count of
-+               * skb, so we don't really want to and try refree as that would
-+               * actually destroy the skb. */
-+              spin_unlock_bh(qdisc_lock(q));
-+              goto packet_not_eaten_by_imq_dev;
-+      }
-+
-+packet_not_eaten_by_imq_dev:
-+      /* cloned? restore original */
-+      if (skb_orig) {
-+              kfree_skb(skb);
-+              entry->skb = skb_orig;
-+      }
-+      retval = -1;
-+out:
-+      return retval;
-+}
-+
-+static struct nf_queue_handler nfqh = {
-+      .name  = "imq",
-+      .outfn = imq_nf_queue,
-+};
-+
-+static unsigned int imq_nf_hook(unsigned int hook, struct sk_buff *pskb,
-+                              const struct net_device *indev,
-+                              const struct net_device *outdev,
-+                              int (*okfn)(struct sk_buff *))
-+{
-+      if (pskb->imq_flags & IMQ_F_ENQUEUE)
-+              return NF_QUEUE;
-+
-+      return NF_ACCEPT;
-+}
-+
-+static int imq_close(struct net_device *dev)
-+{
-+      netif_stop_queue(dev);
-+      return 0;
-+}
-+
-+static int imq_open(struct net_device *dev)
-+{
-+      netif_start_queue(dev);
-+      return 0;
-+}
-+
-+static const struct net_device_ops imq_netdev_ops = {
-+      .ndo_open               = imq_open,
-+      .ndo_stop               = imq_close,
-+      .ndo_start_xmit         = imq_dev_xmit,
-+      .ndo_get_stats          = imq_get_stats,
-+};
-+
-+static void imq_setup(struct net_device *dev)
-+{
-+      dev->netdev_ops         = &imq_netdev_ops;
-+      dev->type               = ARPHRD_VOID;
-+      dev->mtu                = 16000;
-+      dev->tx_queue_len       = 11000;
-+      dev->flags              = IFF_NOARP;
-+      dev->features           = NETIF_F_SG | NETIF_F_FRAGLIST |
-+                                NETIF_F_GSO | NETIF_F_HW_CSUM |
-+                                NETIF_F_HIGHDMA;
-+      dev->priv_flags         &= ~IFF_XMIT_DST_RELEASE;
-+}
-+
-+static int imq_validate(struct nlattr *tb[], struct nlattr *data[])
-+{
-+      int ret = 0;
-+
-+      if (tb[IFLA_ADDRESS]) {
-+              if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) {
-+                      ret = -EINVAL;
-+                      goto end;
-+              }
-+              if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) {
-+                      ret = -EADDRNOTAVAIL;
-+                      goto end;
-+              }
-+      }
-+      return 0;
-+end:
-+      printk(KERN_WARNING "IMQ: imq_validate failed (%d)\n", ret);
-+      return ret;
-+}
-+
-+static struct rtnl_link_ops imq_link_ops __read_mostly = {
-+      .kind           = "imq",
-+      .priv_size      = 0,
-+      .setup          = imq_setup,
-+      .validate       = imq_validate,
-+};
-+
-+static int __init imq_init_hooks(void)
-+{
-+      int err;
-+
-+      nf_register_queue_imq_handler(&nfqh);
-+
-+      err = nf_register_hook(&imq_ingress_ipv4);
-+      if (err)
-+              goto err1;
-+
-+      err = nf_register_hook(&imq_egress_ipv4);
-+      if (err)
-+              goto err2;
-+
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+      err = nf_register_hook(&imq_ingress_ipv6);
-+      if (err)
-+              goto err3;
-+
-+      err = nf_register_hook(&imq_egress_ipv6);
-+      if (err)
-+              goto err4;
-+#endif
-+
-+      return 0;
-+
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+err4:
-+      nf_unregister_hook(&imq_ingress_ipv6);
-+err3:
-+      nf_unregister_hook(&imq_egress_ipv4);
-+#endif
-+err2:
-+      nf_unregister_hook(&imq_ingress_ipv4);
-+err1:
-+      nf_unregister_queue_imq_handler();
-+      return err;
-+}
-+
-+static int __init imq_init_one(int index)
-+{
-+      struct net_device *dev;
-+      int ret;
-+
-+      dev = alloc_netdev(0, "imq%d", imq_setup);
-+      if (!dev)
-+              return -ENOMEM;
-+
-+      ret = dev_alloc_name(dev, dev->name);
-+      if (ret < 0)
-+              goto fail;
-+
-+      dev->rtnl_link_ops = &imq_link_ops;
-+      ret = register_netdevice(dev);
-+      if (ret < 0)
-+              goto fail;
-+
-+      return 0;
-+fail:
-+      free_netdev(dev);
-+      return ret;
-+}
-+
-+static int __init imq_init_devs(void)
-+{
-+      int err, i;
-+
-+      if (numdevs < 1 || numdevs > IMQ_MAX_DEVS) {
-+              printk(KERN_ERR "IMQ: numdevs has to be betweed 1 and %u\n",
-+                     IMQ_MAX_DEVS);
-+              return -EINVAL;
-+      }
-+
-+      rtnl_lock();
-+      err = __rtnl_link_register(&imq_link_ops);
-+
-+      for (i = 0; i < numdevs && !err; i++)
-+              err = imq_init_one(i);
-+
-+      if (err) {
-+              __rtnl_link_unregister(&imq_link_ops);
-+              memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
-+      }
-+      rtnl_unlock();
-+
-+      return err;
-+}
-+
-+static int __init imq_init_module(void)
-+{
-+      int err;
-+
-+#if defined(CONFIG_IMQ_NUM_DEVS)
-+      BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS > 16);
-+      BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS < 2);
-+      BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS - 1 > IMQ_F_IFMASK);
-+#endif
-+
-+      err = imq_init_devs();
-+      if (err) {
-+              printk(KERN_ERR "IMQ: Error trying imq_init_devs(net)\n");
-+              return err;
-+      }
-+
-+      err = imq_init_hooks();
-+      if (err) {
-+              printk(KERN_ERR "IMQ: Error trying imq_init_hooks()\n");
-+              rtnl_link_unregister(&imq_link_ops);
-+              memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
-+              return err;
-+      }
-+
-+      printk(KERN_INFO "IMQ driver loaded successfully.\n");
-+
-+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+      printk(KERN_INFO "\tHooking IMQ before NAT on PREROUTING.\n");
-+#else
-+      printk(KERN_INFO "\tHooking IMQ after NAT on PREROUTING.\n");
-+#endif
-+#if defined(CONFIG_IMQ_BEHAVIOR_AB) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+      printk(KERN_INFO "\tHooking IMQ before NAT on POSTROUTING.\n");
-+#else
-+      printk(KERN_INFO "\tHooking IMQ after NAT on POSTROUTING.\n");
-+#endif
-+
-+      return 0;
-+}
-+
-+static void __exit imq_unhook(void)
-+{
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+      nf_unregister_hook(&imq_ingress_ipv6);
-+      nf_unregister_hook(&imq_egress_ipv6);
-+#endif
-+      nf_unregister_hook(&imq_ingress_ipv4);
-+      nf_unregister_hook(&imq_egress_ipv4);
-+
-+      nf_unregister_queue_imq_handler();
-+}
-+
-+static void __exit imq_cleanup_devs(void)
-+{
-+      rtnl_link_unregister(&imq_link_ops);
-+      memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
-+}
-+
-+static void __exit imq_exit_module(void)
-+{
-+      imq_unhook();
-+      imq_cleanup_devs();
-+      printk(KERN_INFO "IMQ driver unloaded successfully.\n");
-+}
-+
-+module_init(imq_init_module);
-+module_exit(imq_exit_module);
-+
-+module_param(numdevs, int, 0);
-+MODULE_PARM_DESC(numdevs, "number of IMQ devices (how many imq* devices will "
-+                      "be created)");
-+MODULE_AUTHOR("http://www.linuximq.net");
-+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See "
-+                      "http://www.linuximq.net/ for more information.");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS_RTNL_LINK("imq");
-+
---- a/drivers/net/Kconfig
-+++ b/drivers/net/Kconfig
-@@ -121,6 +121,129 @@ config EQUALIZER
-         To compile this driver as a module, choose M here: the module
-         will be called eql.  If unsure, say N.
-+config IMQ
-+      tristate "IMQ (intermediate queueing device) support"
-+      depends on NETDEVICES && NETFILTER
-+      ---help---
-+        The IMQ device(s) is used as placeholder for QoS queueing
-+        disciplines. Every packet entering/leaving the IP stack can be
-+        directed through the IMQ device where it's enqueued/dequeued to the
-+        attached qdisc. This allows you to treat network devices as classes
-+        and distribute bandwidth among them. Iptables is used to specify
-+        through which IMQ device, if any, packets travel.
-+
-+        More information at: http://www.linuximq.net/
-+
-+        To compile this driver as a module, choose M here: the module
-+        will be called imq.  If unsure, say N.
-+
-+choice
-+      prompt "IMQ behavior (PRE/POSTROUTING)"
-+      depends on IMQ
-+      default IMQ_BEHAVIOR_AB
-+      help
-+
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              IMQ can work in any of the following ways:
-+
-+                  PREROUTING   |      POSTROUTING
-+              -----------------|-------------------
-+              #1  After NAT    |      After NAT
-+              #2  After NAT    |      Before NAT
-+              #3  Before NAT   |      After NAT
-+              #4  Before NAT   |      Before NAT
-+
-+              The default behavior is to hook before NAT on PREROUTING
-+              and after NAT on POSTROUTING (#3).
-+
-+              This settings are specially usefull when trying to use IMQ
-+              to shape NATed clients.
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_AA
-+      bool "IMQ AA"
-+      help
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              Choosing this option will make IMQ hook like this:
-+
-+              PREROUTING:   After NAT
-+              POSTROUTING:  After NAT
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_AB
-+      bool "IMQ AB"
-+      help
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              Choosing this option will make IMQ hook like this:
-+
-+              PREROUTING:   After NAT
-+              POSTROUTING:  Before NAT
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_BA
-+      bool "IMQ BA"
-+      help
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              Choosing this option will make IMQ hook like this:
-+
-+              PREROUTING:   Before NAT
-+              POSTROUTING:  After NAT
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_BB
-+      bool "IMQ BB"
-+      help
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              Choosing this option will make IMQ hook like this:
-+
-+              PREROUTING:   Before NAT
-+              POSTROUTING:  Before NAT
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+endchoice
-+
-+config IMQ_NUM_DEVS
-+
-+      int "Number of IMQ devices"
-+      range 2 16
-+      depends on IMQ
-+      default "16"
-+      help
-+
-+              This settings defines how many IMQ devices will be
-+              created.
-+
-+              The default value is 16.
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
- config TUN
-       tristate "Universal TUN/TAP device driver support"
-       select CRC32
---- a/drivers/net/Makefile
-+++ b/drivers/net/Makefile
-@@ -169,6 +169,7 @@ obj-$(CONFIG_SLHC) += slhc.o
- obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o
- obj-$(CONFIG_DUMMY) += dummy.o
-+obj-$(CONFIG_IMQ) += imq.o
- obj-$(CONFIG_IFB) += ifb.o
- obj-$(CONFIG_MACVLAN) += macvlan.o
- obj-$(CONFIG_MACVTAP) += macvtap.o
---- /dev/null
-+++ b/include/linux/imq.h
-@@ -0,0 +1,13 @@
-+#ifndef _IMQ_H
-+#define _IMQ_H
-+
-+/* IFMASK (16 device indexes, 0 to 15) and flag(s) fit in 5 bits */
-+#define IMQ_F_BITS    5
-+
-+#define IMQ_F_IFMASK  0x0f
-+#define IMQ_F_ENQUEUE 0x10
-+
-+#define IMQ_MAX_DEVS  (IMQ_F_IFMASK + 1)
-+
-+#endif /* _IMQ_H */
-+
---- a/include/linux/netdevice.h
-+++ b/include/linux/netdevice.h
-@@ -1281,6 +1281,7 @@ extern int               dev_alloc_name(struct net_de
- extern int            dev_open(struct net_device *dev);
- extern int            dev_close(struct net_device *dev);
- extern void           dev_disable_lro(struct net_device *dev);
-+extern struct netdev_queue *dev_pick_tx(struct net_device *dev, struct sk_buff *skb);
- extern int            dev_queue_xmit(struct sk_buff *skb);
- extern int            register_netdevice(struct net_device *dev);
- extern void           unregister_netdevice_queue(struct net_device *dev,
---- /dev/null
-+++ b/include/linux/netfilter/xt_IMQ.h
-@@ -0,0 +1,9 @@
-+#ifndef _XT_IMQ_H
-+#define _XT_IMQ_H
-+
-+struct xt_imq_info {
-+      unsigned int todev;     /* target imq device */
-+};
-+
-+#endif /* _XT_IMQ_H */
-+
---- /dev/null
-+++ b/include/linux/netfilter_ipv4/ipt_IMQ.h
-@@ -0,0 +1,10 @@
-+#ifndef _IPT_IMQ_H
-+#define _IPT_IMQ_H
-+
-+/* Backwards compatibility for old userspace */
-+#include <linux/netfilter/xt_IMQ.h>
-+
-+#define ipt_imq_info xt_imq_info
-+
-+#endif /* _IPT_IMQ_H */
-+
---- /dev/null
-+++ b/include/linux/netfilter_ipv6/ip6t_IMQ.h
-@@ -0,0 +1,10 @@
-+#ifndef _IP6T_IMQ_H
-+#define _IP6T_IMQ_H
-+
-+/* Backwards compatibility for old userspace */
-+#include <linux/netfilter/xt_IMQ.h>
-+
-+#define ip6t_imq_info xt_imq_info
-+
-+#endif /* _IP6T_IMQ_H */
-+
---- a/include/linux/skbuff.h
-+++ b/include/linux/skbuff.h
-@@ -29,6 +29,9 @@
- #include <linux/rcupdate.h>
- #include <linux/dmaengine.h>
- #include <linux/hrtimer.h>
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+#include <linux/imq.h>
-+#endif
- /* Don't change this without changing skb_csum_unnecessary! */
- #define CHECKSUM_NONE 0
-@@ -329,6 +332,9 @@ struct sk_buff {
-        * first. This is owned by whoever has the skb queued ATM.
-        */
-       char                    cb[48] __aligned(8);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      void                    *cb_next;
-+#endif
-       unsigned long           _skb_refdst;
- #ifdef CONFIG_XFRM
-@@ -365,6 +371,9 @@ struct sk_buff {
-       struct nf_conntrack     *nfct;
-       struct sk_buff          *nfct_reasm;
- #endif
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      struct nf_queue_entry   *nf_queue_entry;
-+#endif
- #ifdef CONFIG_BRIDGE_NETFILTER
-       struct nf_bridge_info   *nf_bridge;
- #endif
-@@ -391,6 +400,10 @@ struct sk_buff {
-       /* 0/14 bit hole */
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      __u8                    imq_flags:IMQ_F_BITS;
-+#endif
-+
- #ifdef CONFIG_NET_DMA
-       dma_cookie_t            dma_cookie;
- #endif
-@@ -489,6 +502,12 @@ static inline struct rtable *skb_rtable(
-       return (struct rtable *)skb_dst(skb);
- }
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+extern int skb_save_cb(struct sk_buff *skb);
-+extern int skb_restore_cb(struct sk_buff *skb);
-+#endif
-+
- extern void kfree_skb(struct sk_buff *skb);
- extern void consume_skb(struct sk_buff *skb);
- extern void          __kfree_skb(struct sk_buff *skb);
-@@ -2036,6 +2055,10 @@ static inline void __nf_copy(struct sk_b
-       dst->nfct_reasm = src->nfct_reasm;
-       nf_conntrack_get_reasm(src->nfct_reasm);
- #endif
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      dst->imq_flags = src->imq_flags;
-+      dst->nf_queue_entry = src->nf_queue_entry;
-+#endif
- #ifdef CONFIG_BRIDGE_NETFILTER
-       dst->nf_bridge  = src->nf_bridge;
-       nf_bridge_get(src->nf_bridge);
---- a/include/net/netfilter/nf_queue.h
-+++ b/include/net/netfilter/nf_queue.h
-@@ -13,6 +13,12 @@ struct nf_queue_entry {
-       struct net_device       *indev;
-       struct net_device       *outdev;
-       int                     (*okfn)(struct sk_buff *);
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      int                     (*next_outfn)(struct nf_queue_entry *entry,
-+                                            unsigned int queuenum);
-+      unsigned int            next_queuenum;
-+#endif
- };
- #define nf_queue_entry_reroute(x) ((void *)x + sizeof(struct nf_queue_entry))
-@@ -30,5 +36,11 @@ extern int nf_unregister_queue_handler(u
-                                      const struct nf_queue_handler *qh);
- extern void nf_unregister_queue_handlers(const struct nf_queue_handler *qh);
- extern void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
-+extern void nf_queue_entry_release_refs(struct nf_queue_entry *entry);
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+extern void nf_register_queue_imq_handler(const struct nf_queue_handler *qh);
-+extern void nf_unregister_queue_imq_handler(void);
-+#endif
- #endif /* _NF_QUEUE_H */
---- a/net/core/dev.c
-+++ b/net/core/dev.c
-@@ -98,6 +98,9 @@
- #include <net/net_namespace.h>
- #include <net/sock.h>
- #include <linux/rtnetlink.h>
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+#include <linux/imq.h>
-+#endif
- #include <linux/proc_fs.h>
- #include <linux/seq_file.h>
- #include <linux/stat.h>
-@@ -1931,7 +1934,11 @@ int dev_hard_start_xmit(struct sk_buff *
-       int rc = NETDEV_TX_OK;
-       if (likely(!skb->next)) {
--              if (!list_empty(&ptype_all))
-+              if (!list_empty(&ptype_all)
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+                      && !(skb->imq_flags & IMQ_F_ENQUEUE)
-+#endif
-+                 )
-                       dev_queue_xmit_nit(skb, dev);
-               /*
-@@ -2027,8 +2034,7 @@ static inline u16 dev_cap_txqueue(struct
-       return queue_index;
- }
--static struct netdev_queue *dev_pick_tx(struct net_device *dev,
--                                      struct sk_buff *skb)
-+struct netdev_queue *dev_pick_tx(struct net_device *dev, struct sk_buff *skb)
- {
-       int queue_index;
-       struct sock *sk = skb->sk;
-@@ -2057,6 +2063,7 @@ static struct netdev_queue *dev_pick_tx(
-       skb_set_queue_mapping(skb, queue_index);
-       return netdev_get_tx_queue(dev, queue_index);
- }
-+EXPORT_SYMBOL(dev_pick_tx);
- static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
-                                struct net_device *dev,
---- a/net/core/skbuff.c
-+++ b/net/core/skbuff.c
-@@ -72,6 +72,9 @@
- static struct kmem_cache *skbuff_head_cache __read_mostly;
- static struct kmem_cache *skbuff_fclone_cache __read_mostly;
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+static struct kmem_cache *skbuff_cb_store_cache __read_mostly;
-+#endif
- static void sock_pipe_buf_release(struct pipe_inode_info *pipe,
-                                 struct pipe_buffer *buf)
-@@ -91,6 +94,83 @@ static int sock_pipe_buf_steal(struct pi
-       return 1;
- }
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+/* Control buffer save/restore for IMQ devices */
-+struct skb_cb_table {
-+      void                    *cb_next;
-+      atomic_t                refcnt;
-+      char                    cb[48];
-+};
-+
-+static DEFINE_SPINLOCK(skb_cb_store_lock);
-+
-+int skb_save_cb(struct sk_buff *skb)
-+{
-+      struct skb_cb_table *next;
-+
-+      next = kmem_cache_alloc(skbuff_cb_store_cache, GFP_ATOMIC);
-+      if (!next)
-+              return -ENOMEM;
-+
-+      BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb));
-+
-+      memcpy(next->cb, skb->cb, sizeof(skb->cb));
-+      next->cb_next = skb->cb_next;
-+
-+      atomic_set(&next->refcnt, 1);
-+
-+      skb->cb_next = next;
-+      return 0;
-+}
-+EXPORT_SYMBOL(skb_save_cb);
-+
-+int skb_restore_cb(struct sk_buff *skb)
-+{
-+      struct skb_cb_table *next;
-+
-+      if (!skb->cb_next)
-+              return 0;
-+
-+      next = skb->cb_next;
-+
-+      BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb));
-+
-+      memcpy(skb->cb, next->cb, sizeof(skb->cb));
-+      skb->cb_next = next->cb_next;
-+
-+      spin_lock(&skb_cb_store_lock);
-+
-+      if (atomic_dec_and_test(&next->refcnt)) {
-+              kmem_cache_free(skbuff_cb_store_cache, next);
-+      }
-+
-+      spin_unlock(&skb_cb_store_lock);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL(skb_restore_cb);
-+
-+static void skb_copy_stored_cb(struct sk_buff *new, const struct sk_buff *__old)
-+{
-+      struct skb_cb_table *next;
-+      struct sk_buff *old;
-+
-+      if (!__old->cb_next) {
-+              new->cb_next = NULL;
-+              return;
-+      }
-+
-+      spin_lock(&skb_cb_store_lock);
-+
-+      old = (struct sk_buff *)__old;
-+
-+      next = old->cb_next;
-+      atomic_inc(&next->refcnt);
-+      new->cb_next = next;
-+
-+      spin_unlock(&skb_cb_store_lock);
-+}
-+#endif
- /* Pipe buffer operations for a socket. */
- static const struct pipe_buf_operations sock_pipe_buf_ops = {
-@@ -391,6 +471,26 @@ static void skb_release_head_state(struc
-               WARN_ON(in_irq());
-               skb->destructor(skb);
-       }
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      /* This should not happen. When it does, avoid memleak by restoring
-+      the chain of cb-backups. */
-+      while(skb->cb_next != NULL) {
-+              if (net_ratelimit())
-+                      printk(KERN_WARNING "IMQ: kfree_skb: skb->cb_next: "
-+                              "%08x\n", (unsigned int)skb->cb_next);
-+
-+              skb_restore_cb(skb);
-+      }
-+      /* This should not happen either, nf_queue_entry is nullified in
-+       * imq_dev_xmit(). If we have non-NULL nf_queue_entry then we are
-+       * leaking entry pointers, maybe memory. We don't know if this is
-+       * pointer to already freed memory, or should this be freed.
-+       * If this happens we need to add refcounting, etc for nf_queue_entry.
-+       */
-+      if (skb->nf_queue_entry && net_ratelimit())
-+              printk(KERN_WARNING
-+                              "IMQ: kfree_skb: skb->nf_queue_entry != NULL");
-+#endif
- #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
-       nf_conntrack_put(skb->nfct);
-       nf_conntrack_put_reasm(skb->nfct_reasm);
-@@ -526,6 +626,9 @@ static void __copy_skb_header(struct sk_
-       new->sp                 = secpath_get(old->sp);
- #endif
-       memcpy(new->cb, old->cb, sizeof(old->cb));
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      skb_copy_stored_cb(new, old);
-+#endif
-       new->csum               = old->csum;
-       new->local_df           = old->local_df;
-       new->pkt_type           = old->pkt_type;
-@@ -2780,6 +2883,13 @@ void __init skb_init(void)
-                                               0,
-                                               SLAB_HWCACHE_ALIGN|SLAB_PANIC,
-                                               NULL);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      skbuff_cb_store_cache = kmem_cache_create("skbuff_cb_store_cache",
-+                                                sizeof(struct skb_cb_table),
-+                                                0,
-+                                                SLAB_HWCACHE_ALIGN|SLAB_PANIC,
-+                                                NULL);
-+#endif
- }
- /**
---- a/net/netfilter/Kconfig
-+++ b/net/netfilter/Kconfig
-@@ -448,6 +448,18 @@ config NETFILTER_XT_TARGET_LED
-         For more information on the LEDs available on your system, see
-         Documentation/leds-class.txt
-+config NETFILTER_XT_TARGET_IMQ
-+        tristate '"IMQ" target support'
-+      depends on NETFILTER_XTABLES
-+      depends on IP_NF_MANGLE || IP6_NF_MANGLE
-+      select IMQ
-+      default m if NETFILTER_ADVANCED=n
-+        help
-+          This option adds a `IMQ' target which is used to specify if and
-+          to which imq device packets should get enqueued/dequeued.
-+
-+          To compile it as a module, choose M here.  If unsure, say N.
-+
- config NETFILTER_XT_TARGET_MARK
-       tristate '"MARK" target support'
-       depends on NETFILTER_ADVANCED
---- a/net/netfilter/Makefile
-+++ b/net/netfilter/Makefile
-@@ -50,6 +50,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSEC
- obj-$(CONFIG_NETFILTER_XT_TARGET_CT) += xt_CT.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o
-+obj-$(CONFIG_NETFILTER_XT_TARGET_IMQ) += xt_IMQ.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
---- a/net/netfilter/nf_queue.c
-+++ b/net/netfilter/nf_queue.c
-@@ -22,6 +22,26 @@ static const struct nf_queue_handler *qu
- static DEFINE_MUTEX(queue_handler_mutex);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+static const struct nf_queue_handler *queue_imq_handler;
-+
-+void nf_register_queue_imq_handler(const struct nf_queue_handler *qh)
-+{
-+      mutex_lock(&queue_handler_mutex);
-+      rcu_assign_pointer(queue_imq_handler, qh);
-+      mutex_unlock(&queue_handler_mutex);
-+}
-+EXPORT_SYMBOL(nf_register_queue_imq_handler);
-+
-+void nf_unregister_queue_imq_handler(void)
-+{
-+      mutex_lock(&queue_handler_mutex);
-+      rcu_assign_pointer(queue_imq_handler, NULL);
-+      mutex_unlock(&queue_handler_mutex);
-+}
-+EXPORT_SYMBOL(nf_unregister_queue_imq_handler);
-+#endif
-+
- /* return EBUSY when somebody else is registered, return EEXIST if the
-  * same handler is registered, return 0 in case of success. */
- int nf_register_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh)
-@@ -82,7 +102,7 @@ void nf_unregister_queue_handlers(const
- }
- EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers);
--static void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
-+void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
- {
-       /* Release those devices we held, or Alexey will kill me. */
-       if (entry->indev)
-@@ -102,6 +122,7 @@ static void nf_queue_entry_release_refs(
-       /* Drop reference to owner of hook which queued us. */
-       module_put(entry->elem->owner);
- }
-+EXPORT_SYMBOL_GPL(nf_queue_entry_release_refs);
- /*
-  * Any packet that leaves via this function must come back
-@@ -123,12 +144,26 @@ static int __nf_queue(struct sk_buff *sk
- #endif
-       const struct nf_afinfo *afinfo;
-       const struct nf_queue_handler *qh;
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      const struct nf_queue_handler *qih = NULL;
-+#endif
-       /* QUEUE == DROP if noone is waiting, to be safe. */
-       rcu_read_lock();
-       qh = rcu_dereference(queue_handler[pf]);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+      if (pf == PF_INET || pf == PF_INET6)
-+#else
-+      if (pf == PF_INET)
-+#endif
-+              qih = rcu_dereference(queue_imq_handler);
-+
-+      if (!qh && !qih)
-+#else /* !IMQ */
-       if (!qh)
-+#endif
-               goto err_unlock;
-       afinfo = nf_get_afinfo(pf);
-@@ -147,6 +182,10 @@ static int __nf_queue(struct sk_buff *sk
-               .indev  = indev,
-               .outdev = outdev,
-               .okfn   = okfn,
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+              .next_outfn = qh ? qh->outfn : NULL,
-+              .next_queuenum = queuenum,
-+#endif
-       };
-       /* If it's going away, ignore hook. */
-@@ -173,8 +212,19 @@ static int __nf_queue(struct sk_buff *sk
- #endif
-       skb_dst_force(skb);
-       afinfo->saveroute(skb, entry);
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      if (qih) {
-+              status = qih->outfn(entry, queuenum);
-+              goto imq_skip_queue;
-+      }
-+#endif
-+
-       status = qh->outfn(entry, queuenum);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+imq_skip_queue:
-+#endif
-       rcu_read_unlock();
-       if (status < 0) {
---- /dev/null
-+++ b/net/netfilter/xt_IMQ.c
-@@ -0,0 +1,73 @@
-+/*
-+ * This target marks packets to be enqueued to an imq device
-+ */
-+#include <linux/module.h>
-+#include <linux/skbuff.h>
-+#include <linux/netfilter/x_tables.h>
-+#include <linux/netfilter/xt_IMQ.h>
-+#include <linux/imq.h>
-+
-+static unsigned int imq_target(struct sk_buff *pskb,
-+                              const struct xt_action_param *par)
-+{
-+      const struct xt_imq_info *mr = par->targinfo;
-+
-+      pskb->imq_flags = (mr->todev & IMQ_F_IFMASK) | IMQ_F_ENQUEUE;
-+
-+      return XT_CONTINUE;
-+}
-+
-+static int imq_checkentry(const struct xt_tgchk_param *par)
-+{
-+      struct xt_imq_info *mr = par->targinfo;
-+
-+      if (mr->todev > IMQ_MAX_DEVS - 1) {
-+              printk(KERN_WARNING
-+                     "IMQ: invalid device specified, highest is %u\n",
-+                     IMQ_MAX_DEVS - 1);
-+              return -EINVAL;
-+      }
-+
-+      return 0;
-+}
-+
-+static struct xt_target xt_imq_reg[] __read_mostly = {
-+      {
-+              .name           = "IMQ",
-+              .family         = AF_INET,
-+              .checkentry     = imq_checkentry,
-+              .target         = imq_target,
-+              .targetsize     = sizeof(struct xt_imq_info),
-+              .table          = "mangle",
-+              .me             = THIS_MODULE
-+      },
-+      {
-+              .name           = "IMQ",
-+              .family         = AF_INET6,
-+              .checkentry     = imq_checkentry,
-+              .target         = imq_target,
-+              .targetsize     = sizeof(struct xt_imq_info),
-+              .table          = "mangle",
-+              .me             = THIS_MODULE
-+      },
-+};
-+
-+static int __init imq_init(void)
-+{
-+      return xt_register_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg));
-+}
-+
-+static void __exit imq_fini(void)
-+{
-+      xt_unregister_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg));
-+}
-+
-+module_init(imq_init);
-+module_exit(imq_fini);
-+
-+MODULE_AUTHOR("http://www.linuximq.net");
-+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information.");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS("ipt_IMQ");
-+MODULE_ALIAS("ip6t_IMQ");
-+
index 977f892d467d3280131935f229c980124aa52a5c..5532e2b35035be0785ceb3545de219b9ebef984c 100644 (file)
@@ -8,7 +8,7 @@
        depends on NETFILTER_ADVANCED
        help
          H.323 is a VoIP signalling protocol from ITU-T. As one of the most
-@@ -562,7 +561,6 @@ config NETFILTER_XT_TARGET_SECMARK
+@@ -550,7 +549,6 @@ config NETFILTER_XT_TARGET_SECMARK
  
  config NETFILTER_XT_TARGET_TCPMSS
        tristate '"TCPMSS" target support'
index e4324717b4459ce1f1009053e6317c930b01b6e4..6ea9ba51ee0d24cf3a3ac657278109d9b11de859 100644 (file)
@@ -1,6 +1,6 @@
 --- a/arch/mips/include/asm/string.h
 +++ b/arch/mips/include/asm/string.h
-@@ -133,11 +133,44 @@ strncmp(__const__ char *__cs, __const__
+@@ -133,11 +133,44 @@ strncmp(__const__ char *__cs, __const__ 
  
  #define __HAVE_ARCH_MEMSET
  extern void *memset(void *__s, int __c, size_t __count);
index fe8cecfc771ed7a1cd16d22361475b2151e8bb98..83fd6c309928d78bdbdc7db87abdd7b06383d9cd 100644 (file)
@@ -1,6 +1,6 @@
 --- a/include/linux/slab.h
 +++ b/include/linux/slab.h
-@@ -130,8 +130,8 @@ int kmem_ptr_validate(struct kmem_cache
+@@ -130,8 +130,8 @@ int kmem_ptr_validate(struct kmem_cache 
   * to do various tricks to work around compiler limitations in order to
   * ensure proper constant folding.
   */
index b64630d50045480d022ba26c901cea68f6da66b3..d71e3b6faa6644c2337588f4b344cc5677419841 100644 (file)
@@ -61,7 +61,7 @@
  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
  extern int mini_fo_create(inode_t *dir, dentry_t *dentry, int mode, struct nameidata *nd);
  
-@@ -501,6 +505,29 @@ static inline void double_unlock(struct
+@@ -501,6 +505,29 @@ static inline void double_unlock(struct 
  #endif  /* if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) */
  #endif /* __KERNEL__ */
  
  #endif /* defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) */
 --- a/fs/mini_fo/aux.c
 +++ b/fs/mini_fo/aux.c
-@@ -164,11 +164,11 @@ dentry_t *bpath_walk(super_block_t *sb,
+@@ -164,11 +164,11 @@ dentry_t *bpath_walk(super_block_t *sb, 
        err = vfs_path_lookup(mnt->mnt_root, mnt, bpath+1, 0, &nd);
  
        /* validate */
index b5fa64e6a19e7fff343aed59f4ddccfc34578d91..8bd9ba32447e15df6ebc7153edfe89dfd38f43f6 100644 (file)
@@ -1,6 +1,6 @@
 --- a/fs/mini_fo/super.c
 +++ b/fs/mini_fo/super.c
-@@ -84,6 +84,7 @@ mini_fo_write_inode(inode_t *inode, int
+@@ -84,6 +84,7 @@ mini_fo_write_inode(inode_t *inode, int 
  #endif /* defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) */
  
  
index 14a36844105977b20891bcef7f2886b65371b467..c09e13e11c6247e31de2705c4261f869e96e23eb 100644 (file)
@@ -20,7 +20,7 @@
  #else
  static inline int kobject_uevent(struct kobject *kobj,
                                 enum kobject_action action)
-@@ -262,6 +268,16 @@ static inline int add_uevent_var(struct
+@@ -262,6 +268,16 @@ static inline int add_uevent_var(struct 
  static inline int kobject_action_type(const char *buf, size_t count,
                                      enum kobject_action *type)
  { return -EINVAL; }
index e02d1bc317605baa14ba2173cc9687c8956cc506..286bdaec98b64a9d1e19d19e3a1ec375ff61b39a 100644 (file)
 +module_exit(connmark_cleanup_module);
 --- a/net/sched/Kconfig
 +++ b/net/sched/Kconfig
-@@ -549,6 +549,18 @@
+@@ -549,6 +549,18 @@ config NET_ACT_SKBEDIT
          To compile this code as a module, choose M here: the
          module will be called act_skbedit.
  
        depends on NET_CLS_U32 || NET_CLS_FW
 --- a/net/sched/Makefile
 +++ b/net/sched/Makefile
-@@ -15,6 +15,7 @@
+@@ -15,6 +15,7 @@ obj-$(CONFIG_NET_ACT_NAT)    += act_nat.o
  obj-$(CONFIG_NET_ACT_PEDIT)   += act_pedit.o
  obj-$(CONFIG_NET_ACT_SIMP)    += act_simple.o
  obj-$(CONFIG_NET_ACT_SKBEDIT) += act_skbedit.o
index ef8017b95d5655fa2a6ba36f8fc1bd44dfd419cc..9630940bfeebeb2d7d3eb31f4fd3abc57a0ef205 100644 (file)
@@ -11,7 +11,7 @@
  endif # NEW_LEDS
 --- a/drivers/leds/Makefile
 +++ b/drivers/leds/Makefile
-@@ -48,3 +48,4 @@ obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) +=
+@@ -48,3 +48,4 @@ obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += 
  obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT)  += ledtrig-backlight.o
  obj-$(CONFIG_LEDS_TRIGGER_GPIO)               += ledtrig-gpio.o
  obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
index 0c52f633659355fc0aa1a964b197592da2b018b8..100dea60d7bffc312187cc817db0a7cd58422c3f 100644 (file)
@@ -14,7 +14,7 @@
  endif # NEW_LEDS
 --- a/drivers/leds/Makefile
 +++ b/drivers/leds/Makefile
-@@ -49,3 +49,4 @@ obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) +=
+@@ -49,3 +49,4 @@ obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) += 
  obj-$(CONFIG_LEDS_TRIGGER_GPIO)               += ledtrig-gpio.o
  obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
  obj-$(CONFIG_LEDS_TRIGGER_MORSE)      += ledtrig-morse.o
index c334b17d0872a877f52cd9c0e4234ad118df7d09..5c70e79a058d050e90224ac0ef80dcb1180235ab 100644 (file)
                        dev->checkpointBlockList[i] = -1;
        }
  
-@@ -191,18 +185,17 @@ int yaffs_GetCheckpointSum(yaffs_Device
+@@ -191,18 +185,17 @@ int yaffs_GetCheckpointSum(yaffs_Device 
  
  static int yaffs_CheckpointFlushBuffer(yaffs_Device *dev)
  {
  {
        unsigned char cDelta;   /* column parity delta */
        unsigned lDelta;        /* line parity delta */
-@@ -294,8 +292,7 @@ int yaffs_ECCCorrectOther(unsigned char
+@@ -294,8 +292,7 @@ int yaffs_ECCCorrectOther(unsigned char 
                return 0; /* no error */
  
        if (lDelta == ~lDeltaPrime &&
                /* Single bit (recoverable) error in data */
  
                bit = 0;
-@@ -307,7 +304,7 @@ int yaffs_ECCCorrectOther(unsigned char
+@@ -307,7 +304,7 @@ int yaffs_ECCCorrectOther(unsigned char 
                if (cDelta & 0x02)
                        bit |= 0x01;
  
                        return -1;
  
                data[lDelta] ^= (1 << bit);
-@@ -316,7 +313,7 @@ int yaffs_ECCCorrectOther(unsigned char
+@@ -316,7 +313,7 @@ int yaffs_ECCCorrectOther(unsigned char 
        }
  
        if ((yaffs_CountBits32(lDelta) + yaffs_CountBits32(lDeltaPrime) +
                /* Reccoverable error in ecc */
  
                *read_ecc = *test_ecc;
-@@ -326,6 +323,4 @@ int yaffs_ECCCorrectOther(unsigned char
+@@ -326,6 +323,4 @@ int yaffs_ECCCorrectOther(unsigned char 
        /* Unrecoverable error */
  
        return -1;
  {
        unsigned char *alias;
        int ret;
-@@ -329,7 +395,7 @@ static int yaffs_readlink(struct dentry
+@@ -329,7 +395,7 @@ static int yaffs_readlink(struct dentry 
        return ret;
  }
  
  static int yaffs_file_flush(struct file *file, fl_owner_t id)
  #else
  static int yaffs_file_flush(struct file *file)
-@@ -513,8 +579,8 @@ static int yaffs_file_flush(struct file
+@@ -513,8 +579,8 @@ static int yaffs_file_flush(struct file 
        yaffs_Device *dev = obj->myDev;
  
        T(YAFFS_TRACE_OS,
  
        yaffs_GrossLock(dev);
  
-@@ -535,15 +601,15 @@ static int yaffs_readpage_nolock(struct
+@@ -535,15 +601,15 @@ static int yaffs_readpage_nolock(struct 
  
        yaffs_Device *dev;
  
        BUG_ON(!PageLocked(pg));
  #else
        if (!PageLocked(pg))
-@@ -555,9 +621,9 @@ static int yaffs_readpage_nolock(struct
+@@ -555,9 +621,9 @@ static int yaffs_readpage_nolock(struct 
  
        yaffs_GrossLock(dev);
  
  
        yaffs_GrossUnlock(dev);
  
-@@ -575,7 +641,7 @@ static int yaffs_readpage_nolock(struct
+@@ -575,7 +641,7 @@ static int yaffs_readpage_nolock(struct 
        flush_dcache_page(pg);
        kunmap(pg);
  
                if (n < step) {
                        n++;
                        continue;
-@@ -2119,7 +2356,7 @@ static int yaffs_proc_write(struct file
+@@ -2119,7 +2356,7 @@ static int yaffs_proc_write(struct file 
        char *end;
        char *mask_name;
        const char *x;
        int i;
        int done = 0;
        int add, len = 0;
-@@ -2129,9 +2366,8 @@ static int yaffs_proc_write(struct file
+@@ -2129,9 +2366,8 @@ static int yaffs_proc_write(struct file 
  
        while (!done && (pos < count)) {
                done = 1;
  
                switch (buf[pos]) {
                case '+':
-@@ -2148,20 +2384,21 @@ static int yaffs_proc_write(struct file
+@@ -2148,20 +2384,21 @@ static int yaffs_proc_write(struct file 
                mask_name = NULL;
  
                mask_bitfield = simple_strtoul(buf + pos, &end, 0);
                                        mask_name = mask_flags[i].mask_name;
                                        mask_bitfield = mask_flags[i].mask_bitfield;
                                        done = 0;
-@@ -2172,7 +2409,7 @@ static int yaffs_proc_write(struct file
+@@ -2172,7 +2409,7 @@ static int yaffs_proc_write(struct file 
  
                if (mask_name != NULL) {
                        done = 0;
                        case '-':
                                rg &= ~mask_bitfield;
                                break;
-@@ -2191,13 +2428,13 @@ static int yaffs_proc_write(struct file
+@@ -2191,13 +2428,13 @@ static int yaffs_proc_write(struct file 
  
        yaffs_traceMask = rg | YAFFS_TRACE_ALWAYS;
  
  {
        /* Get the real object in case we were fed a hard link as an equivalent object */
        equivalentObject = yaffs_GetEquivalentObject(equivalentObject);
-@@ -2363,33 +2396,31 @@ yaffs_Object *yaffs_Link(yaffs_Object *
+@@ -2363,33 +2396,31 @@ yaffs_Object *yaffs_Link(yaffs_Object * 
  
  }
  
        int nToCopy;
        int n = nBytes;
        int nDone = 0;
-@@ -4600,27 +4665,26 @@ int yaffs_ReadDataFromFile(yaffs_Object
+@@ -4600,27 +4665,26 @@ int yaffs_ReadDataFromFile(yaffs_Object 
        dev = in->myDev;
  
        while (n > 0) {
                        if (dev->nShortOpCaches > 0) {
  
                                /* If we can't find the data in the cache, then load it up. */
-@@ -4641,14 +4705,9 @@ int yaffs_ReadDataFromFile(yaffs_Object
+@@ -4641,14 +4705,9 @@ int yaffs_ReadDataFromFile(yaffs_Object 
  
                                cache->locked = 1;
  
                                cache->locked = 0;
                        } else {
                                /* Read into the local buffer then copy..*/
-@@ -4657,41 +4716,19 @@ int yaffs_ReadDataFromFile(yaffs_Object
+@@ -4657,41 +4716,19 @@ int yaffs_ReadDataFromFile(yaffs_Object 
                                    yaffs_GetTempBuffer(dev, __LINE__);
                                yaffs_ReadChunkDataFromObject(in, chunk,
                                                              localBuffer);
                }
  
                n -= nToCopy;
-@@ -4704,28 +4741,37 @@ int yaffs_ReadDataFromFile(yaffs_Object
+@@ -4704,28 +4741,37 @@ int yaffs_ReadDataFromFile(yaffs_Object 
        return nDone;
  }
  
        int newFullChunks;
  
        yaffs_Device *dev = in->myDev;
-@@ -4955,13 +4981,11 @@ int yaffs_ResizeFile(yaffs_Object * in,
+@@ -4955,13 +4981,11 @@ int yaffs_ResizeFile(yaffs_Object * in, 
  
        yaffs_CheckGarbageCollection(dev);
  
  
        if (newSize < oldFileSize) {
  
-@@ -4994,21 +5018,20 @@ int yaffs_ResizeFile(yaffs_Object * in,
+@@ -4994,21 +5018,20 @@ int yaffs_ResizeFile(yaffs_Object * in, 
        }
  
  
  {
        obj = yaffs_GetEquivalentObject(obj);
  
-@@ -5024,7 +5047,7 @@ loff_t yaffs_GetFileSize(yaffs_Object *
+@@ -5024,7 +5047,7 @@ loff_t yaffs_GetFileSize(yaffs_Object * 
  
  
  
  {
        int init_failed = 0;
        unsigned x;
-@@ -7040,6 +7126,8 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7040,6 +7126,8 @@ int yaffs_GutsInitialise(yaffs_Device * 
        dev->chunkOffset = 0;
        dev->nFreeChunks = 0;
  
        if (dev->startBlock == 0) {
                dev->internalStartBlock = dev->startBlock + 1;
                dev->internalEndBlock = dev->endBlock + 1;
-@@ -7049,18 +7137,18 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7049,18 +7137,18 @@ int yaffs_GutsInitialise(yaffs_Device * 
  
        /* Check geometry parameters. */
  
                return YAFFS_FAIL;
        }
  
-@@ -7070,6 +7158,12 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7070,6 +7158,12 @@ int yaffs_GutsInitialise(yaffs_Device * 
                return YAFFS_FAIL;
        }
  
        /* Got the right mix of functions? */
        if (!yaffs_CheckDevFunctions(dev)) {
                /* Function missing */
-@@ -7097,31 +7191,18 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7097,31 +7191,18 @@ int yaffs_GutsInitialise(yaffs_Device * 
  
        dev->isMounted = 1;
  
  
        /*
         * Calculate chunkGroupBits.
-@@ -7133,16 +7214,15 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7133,16 +7214,15 @@ int yaffs_GutsInitialise(yaffs_Device * 
        bits = ShiftsGE(x);
  
        /* Set up tnode width if wide tnodes are enabled. */
                dev->tnodeWidth = 16;
  
        dev->tnodeMask = (1<<dev->tnodeWidth)-1;
-@@ -7193,7 +7273,7 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7193,7 +7273,7 @@ int yaffs_GutsInitialise(yaffs_Device * 
        dev->hasPendingPrioritisedGCs = 1; /* Assume the worst for now, will get fixed on first GC */
  
        /* Initialise temporary buffers and caches. */
                init_failed = 1;
  
        dev->srCache = NULL;
-@@ -7203,25 +7283,26 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7203,25 +7283,26 @@ int yaffs_GutsInitialise(yaffs_Device * 
        if (!init_failed &&
            dev->nShortOpCaches > 0) {
                int i;
                        init_failed = 1;
  
                dev->srLastUse = 0;
-@@ -7229,29 +7310,30 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7229,29 +7310,30 @@ int yaffs_GutsInitialise(yaffs_Device * 
  
        dev->cacheHits = 0;
  
                                T(YAFFS_TRACE_ALWAYS,
                                  (TSTR("yaffs: restored from checkpoint" TENDSTR)));
                        } else {
-@@ -7273,24 +7355,25 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7273,24 +7355,25 @@ int yaffs_GutsInitialise(yaffs_Device * 
                                dev->nBackgroundDeletions = 0;
                                dev->oldestDirtySequence = 0;
  
                /* Clean up the mess */
                T(YAFFS_TRACE_TRACING,
                  (TSTR("yaffs: yaffs_GutsInitialise() aborted.\n" TENDSTR)));
-@@ -7318,7 +7401,7 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7318,7 +7401,7 @@ int yaffs_GutsInitialise(yaffs_Device * 
  
  }
  
  {
        if (etags) {
                memset(etags, 0, sizeof(*etags));
-@@ -169,9 +169,9 @@ static int rettags(yaffs_ExtendedTags *
+@@ -169,9 +169,9 @@ static int rettags(yaffs_ExtendedTags * 
   * Returns YAFFS_OK or YAFFS_FAIL.
   */
  int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device *dev,
 +                      yaffs_UnpackTags2(tags, &pt);
 +              }
 +      }
-+
+-      if(tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR)
+-              tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
 +      if (localData)
 +              yaffs_ReleaseTempBuffer(dev, data, __LINE__);
  
--      if(tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR)
 +      if (tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR)
-               tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
--
++              tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
        if (retval == 0)
                return YAFFS_OK;
        else
index 0fa81eb9e49d82df0354115a15a9b17e387a7afb..5c2d3825e05950670dc40b14566d96ce2ba04612 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/hostap/hostap_ap.c
 +++ b/drivers/net/wireless/hostap/hostap_ap.c
-@@ -2336,13 +2336,13 @@ int prism2_ap_get_sta_qual(local_info_t
+@@ -2336,13 +2336,13 @@ int prism2_ap_get_sta_qual(local_info_t 
                addr[count].sa_family = ARPHRD_ETHER;
                memcpy(addr[count].sa_data, sta->addr, ETH_ALEN);
                if (sta->last_rx_silence == 0)
index 3b6b7d9a48e2ff0e8d7d1c5214559ae5afcd1096..fe96d7937a22c0971b94bdead0f2bb999159a118 100644 (file)
@@ -24,7 +24,7 @@
   * All of these routines try to estimate how many bits of randomness a
   * particular randomness source.  They do this by keeping track of the
   * first and second order deltas of the event timings.
-@@ -715,6 +725,61 @@ void add_disk_randomness(struct gendisk
+@@ -715,6 +725,61 @@ void add_disk_randomness(struct gendisk 
  }
  #endif
  
index 35d0515160745573811d6dbbf17efe1acd679dce..35c97ab1ad6a4dc7e1738473862c0a21b4b921b9 100644 (file)
        u32 pmucap;
  
        if (!(cc->capabilities & SSB_CHIPCO_CAP_PMU))
-@@ -516,15 +516,12 @@ void ssb_pmu_init(struct ssb_chipcommon
+@@ -516,15 +516,12 @@ void ssb_pmu_init(struct ssb_chipcommon 
        ssb_dprintk(KERN_DEBUG PFX "Found rev %u PMU (capabilities 0x%08X)\n",
                    cc->pmu.rev, pmucap);
  
index 77161f684d0fbf11bd95c43444fd7ff7d6716b99..e63d733be9137f603390ecdf4ecd997c3f104047 100644 (file)
@@ -1,6 +1,6 @@
 --- a/scripts/Makefile.lib
 +++ b/scripts/Makefile.lib
-@@ -238,7 +238,7 @@ cmd_bzip2 = (cat $(filter-out FORCE,$^)
+@@ -238,7 +238,7 @@ cmd_bzip2 = (cat $(filter-out FORCE,$^) 
  
  quiet_cmd_lzma = LZMA    $@
  cmd_lzma = (cat $(filter-out FORCE,$^) | \
index 5e16d96486973cf77717309dd024cfe1cfb3a513..2015aa0c3bdbf8777bffc1864df3669a3a84c172 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/mtd/chips/cfi_cmdset_0002.c
 +++ b/drivers/mtd/chips/cfi_cmdset_0002.c
-@@ -418,9 +418,9 @@ struct mtd_info *cfi_cmdset_0002(struct
+@@ -418,9 +418,9 @@ struct mtd_info *cfi_cmdset_0002(struct 
  
                        /*
                         * Valid primary extension versions are: 1.0, 1.1, 1.2, 1.3, 1.4
index a77913d281759e8927fb14cd68934caf0f60aa2f..64b978197643722eaa77f64d453776f99fb549d5 100644 (file)
  
  unsigned int vced_count, vcei_count;
  
-@@ -31,8 +32,12 @@ static int show_cpuinfo(struct seq_file
+@@ -31,8 +32,12 @@ static int show_cpuinfo(struct seq_file 
        /*
         * For the first processor also print the system type
         */
index faea9a4fbfc075aa132e5a57b7bd49624cdc55e7..9c90fc7d8872b3e32930f792942a86bfd0034e68 100644 (file)
@@ -81,7 +81,7 @@
  htc_excalibur_s620    MACH_HTC_EXCALIBUR_S620 HTC_EXCALIBUR_S620      2391
  htc_opal              MACH_HTC_OPAL           HTC_OPAL                2392
  touchbook             MACH_TOUCHBOOK          TOUCHBOOK               2393
-@@ -2446,7 +2446,7 @@ siogentoo1               MACH_SIOGENTOO1         SIOGENTOO1
+@@ -2446,7 +2446,7 @@ siogentoo1               MACH_SIOGENTOO1         SIOGENTOO1      
  siogentoo2            MACH_SIOGENTOO2         SIOGENTOO2              2459
  sm3k                  MACH_SM3K               SM3K                    2460
  acer_tempo_f900               MACH_ACER_TEMPO_F900    ACER_TEMPO_F900         2461
index fac77f59f3843c078187b130fc7da81e15495df6..74471f18ba61b8f0ba4f46860d1dde537fa0cbf6 100644 (file)
  
  #include <linux/mtd/mtd.h>
  #include <linux/mtd/map.h>
-@@ -854,6 +855,13 @@ static int mtd_ioctl(struct file *file,
+@@ -854,6 +855,13 @@ static int mtd_ioctl(struct file *file, 
                file->f_pos = 0;
                break;
        }
index bdbb325b86b9f387aee94d9a6fb42c634e97219e..876e2dc10fd04c40b4b995db56d4b0ebe529a6ca 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/mtd/chips/cfi_cmdset_0002.c
 +++ b/drivers/mtd/chips/cfi_cmdset_0002.c
-@@ -371,9 +371,34 @@ static struct cfi_fixup fixup_table[] =
+@@ -371,9 +371,34 @@ static struct cfi_fixup fixup_table[] = 
  static void cfi_fixup_major_minor(struct cfi_private *cfi,
                                  struct cfi_pri_amdstd *extp)
  {
index 4d969e290b025d80d48ac17fa747cf58de410084..606ff07815c5219c31c7a483771e96a12b4d61b3 100644 (file)
@@ -30,7 +30,7 @@
        depends on NETFILTER_ADVANCED
 --- a/net/netfilter/Makefile
 +++ b/net/netfilter/Makefile
-@@ -95,6 +95,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_RECENT)
+@@ -95,6 +95,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_RECENT) 
  obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o
  obj-$(CONFIG_NETFILTER_XT_MATCH_SOCKET) += xt_socket.o
  obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o
index b146502f01b628597f2936f87a864609e60b09ef..a99eb084c35e6c10160f43ca6a7b14dce58b672f 100644 (file)
  
                e = (struct ipt_entry *)(loc_cpu_entry + off);
                if (copy_to_user(userptr + off
-@@ -983,6 +1024,14 @@ copy_entries_to_user(unsigned int total_
-                       ret = -EFAULT;
+@@ -984,6 +1025,14 @@ copy_entries_to_user(unsigned int total_
                        goto free_counters;
                }
-+
 +              flags = e->ip.flags & ~IPT_F_NO_DEF_MATCH;
 +              if (copy_to_user(userptr + off
 +                               + offsetof(struct ipt_entry, ip.flags),
 +                      ret = -EFAULT;
 +                      goto free_counters;
 +              }
++
                for (i = sizeof(struct ipt_entry);
                     i < e->target_offset;
+                    i += m->u.match_size) {
diff --git a/target/linux/generic/patches-2.6.36/150-netfilter_imq.patch b/target/linux/generic/patches-2.6.36/150-netfilter_imq.patch
deleted file mode 100644 (file)
index 2fb90cf..0000000
+++ /dev/null
@@ -1,1342 +0,0 @@
---- /dev/null
-+++ b/drivers/net/imq.c
-@@ -0,0 +1,638 @@
-+/*
-+ *             Pseudo-driver for the intermediate queue device.
-+ *
-+ *             This program is free software; you can redistribute it and/or
-+ *             modify it under the terms of the GNU General Public License
-+ *             as published by the Free Software Foundation; either version
-+ *             2 of the License, or (at your option) any later version.
-+ *
-+ * Authors:    Patrick McHardy, <kaber@trash.net>
-+ *
-+ *            The first version was written by Martin Devera, <devik@cdi.cz>
-+ *
-+ * Credits:    Jan Rafaj <imq2t@cedric.vabo.cz>
-+ *              - Update patch to 2.4.21
-+ *             Sebastian Strollo <sstrollo@nortelnetworks.com>
-+ *              - Fix "Dead-loop on netdevice imq"-issue
-+ *             Marcel Sebek <sebek64@post.cz>
-+ *              - Update to 2.6.2-rc1
-+ *
-+ *           After some time of inactivity there is a group taking care
-+ *           of IMQ again: http://www.linuximq.net
-+ *
-+ *
-+ *           2004/06/30 - New version of IMQ patch to kernels <=2.6.7
-+ *             including the following changes:
-+ *
-+ *           - Correction of ipv6 support "+"s issue (Hasso Tepper)
-+ *           - Correction of imq_init_devs() issue that resulted in
-+ *           kernel OOPS unloading IMQ as module (Norbert Buchmuller)
-+ *           - Addition of functionality to choose number of IMQ devices
-+ *           during kernel config (Andre Correa)
-+ *           - Addition of functionality to choose how IMQ hooks on
-+ *           PRE and POSTROUTING (after or before NAT) (Andre Correa)
-+ *           - Cosmetic corrections (Norbert Buchmuller) (Andre Correa)
-+ *
-+ *
-+ *             2005/12/16 - IMQ versions between 2.6.7 and 2.6.13 were
-+ *             released with almost no problems. 2.6.14-x was released
-+ *             with some important changes: nfcache was removed; After
-+ *             some weeks of trouble we figured out that some IMQ fields
-+ *             in skb were missing in skbuff.c - skb_clone and copy_skb_header.
-+ *             These functions are correctly patched by this new patch version.
-+ *
-+ *             Thanks for all who helped to figure out all the problems with
-+ *             2.6.14.x: Patrick McHardy, Rune Kock, VeNoMouS, Max CtRiX,
-+ *             Kevin Shanahan, Richard Lucassen, Valery Dachev (hopefully
-+ *             I didn't forget anybody). I apologize again for my lack of time.
-+ *
-+ *
-+ *             2008/06/17 - 2.6.25 - Changed imq.c to use qdisc_run() instead 
-+ *             of qdisc_restart() and moved qdisc_run() to tasklet to avoid
-+ *             recursive locking. New initialization routines to fix 'rmmod' not
-+ *             working anymore. Used code from ifb.c. (Jussi Kivilinna)
-+ *
-+ *             2008/08/06 - 2.6.26 - (JK)
-+ *              - Replaced tasklet with 'netif_schedule()'.
-+ *              - Cleaned up and added comments for imq_nf_queue().
-+ *
-+ *             2009/04/12
-+ *              - Add skb_save_cb/skb_restore_cb helper functions for backuping
-+ *                control buffer. This is needed because qdisc-layer on kernels
-+ *                2.6.27 and newer overwrite control buffer. (Jussi Kivilinna)
-+ *              - Add better locking for IMQ device. Hopefully this will solve
-+ *                SMP issues. (Jussi Kivilinna)
-+ *              - Port to 2.6.27
-+ *              - Port to 2.6.28
-+ *              - Port to 2.6.29 + fix rmmod not working
-+ *
-+ *             2009/04/20 - (Jussi Kivilinna)
-+ *              - Use netdevice feature flags to avoid extra packet handling
-+ *                by core networking layer and possibly increase performance.
-+ *
-+ *             2009/09/26 - (Jussi Kivilinna)
-+ *              - Add imq_nf_reinject_lockless to fix deadlock with
-+ *                imq_nf_queue/imq_nf_reinject.
-+ *
-+ *             2009/12/08 - (Jussi Kivilinna)
-+ *              - Port to 2.6.32
-+ *              - Add check for skb->nf_queue_entry==NULL in imq_dev_xmit()
-+ *              - Also add better error checking for skb->nf_queue_entry usage
-+ *
-+ *             2010/02/25 - (Jussi Kivilinna)
-+ *              - Port to 2.6.33
-+ *
-+ *             2010/08/12 - (Jussi Kivilinna)
-+ *              - Port to 2.6.35
-+ *
-+ *           Also, many thanks to pablo Sebastian Greco for making the initial
-+ *           patch and to those who helped the testing.
-+ *
-+ *             More info at: http://www.linuximq.net/ (Andre Correa)
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/moduleparam.h>
-+#include <linux/list.h>
-+#include <linux/skbuff.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/rtnetlink.h>
-+#include <linux/if_arp.h>
-+#include <linux/netfilter.h>
-+#include <linux/netfilter_ipv4.h>
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+      #include <linux/netfilter_ipv6.h>
-+#endif
-+#include <linux/imq.h>
-+#include <net/pkt_sched.h>
-+#include <net/netfilter/nf_queue.h>
-+
-+static nf_hookfn imq_nf_hook;
-+
-+static struct nf_hook_ops imq_ingress_ipv4 = {
-+      .hook           = imq_nf_hook,
-+      .owner          = THIS_MODULE,
-+      .pf             = PF_INET,
-+      .hooknum        = NF_INET_PRE_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+      .priority       = NF_IP_PRI_MANGLE + 1
-+#else
-+      .priority       = NF_IP_PRI_NAT_DST + 1
-+#endif
-+};
-+
-+static struct nf_hook_ops imq_egress_ipv4 = {
-+      .hook           = imq_nf_hook,
-+      .owner          = THIS_MODULE,
-+      .pf             = PF_INET,
-+      .hooknum        = NF_INET_POST_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
-+      .priority       = NF_IP_PRI_LAST
-+#else
-+      .priority       = NF_IP_PRI_NAT_SRC - 1
-+#endif
-+};
-+
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+static struct nf_hook_ops imq_ingress_ipv6 = {
-+      .hook           = imq_nf_hook,
-+      .owner          = THIS_MODULE,
-+      .pf             = PF_INET6,
-+      .hooknum        = NF_INET_PRE_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+      .priority       = NF_IP6_PRI_MANGLE + 1
-+#else
-+      .priority       = NF_IP6_PRI_NAT_DST + 1
-+#endif
-+};
-+
-+static struct nf_hook_ops imq_egress_ipv6 = {
-+      .hook           = imq_nf_hook,
-+      .owner          = THIS_MODULE,
-+      .pf             = PF_INET6,
-+      .hooknum        = NF_INET_POST_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
-+      .priority       = NF_IP6_PRI_LAST
-+#else
-+      .priority       = NF_IP6_PRI_NAT_SRC - 1
-+#endif
-+};
-+#endif
-+
-+#if defined(CONFIG_IMQ_NUM_DEVS)
-+static unsigned int numdevs = CONFIG_IMQ_NUM_DEVS;
-+#else
-+static unsigned int numdevs = IMQ_MAX_DEVS;
-+#endif
-+
-+static DEFINE_SPINLOCK(imq_nf_queue_lock);
-+
-+static struct net_device *imq_devs_cache[IMQ_MAX_DEVS];
-+
-+
-+static struct net_device_stats *imq_get_stats(struct net_device *dev)
-+{
-+      return &dev->stats;
-+}
-+
-+/* called for packets kfree'd in qdiscs at places other than enqueue */
-+static void imq_skb_destructor(struct sk_buff *skb)
-+{
-+      struct nf_queue_entry *entry = skb->nf_queue_entry;
-+
-+      skb->nf_queue_entry = NULL;
-+
-+      if (entry) {
-+              nf_queue_entry_release_refs(entry);
-+              kfree(entry);
-+      }
-+
-+      skb_restore_cb(skb); /* kfree backup */
-+}
-+
-+/* locking not needed when called from imq_nf_queue */
-+static void imq_nf_reinject_lockless(struct nf_queue_entry *entry,
-+                                              unsigned int verdict)
-+{
-+      int status;
-+
-+      if (!entry->next_outfn) {
-+              nf_reinject(entry, verdict);
-+              return;
-+      }
-+
-+      status = entry->next_outfn(entry, entry->next_queuenum);
-+      if (status < 0) {
-+              nf_queue_entry_release_refs(entry);
-+              kfree_skb(entry->skb);
-+              kfree(entry);
-+      }
-+}
-+
-+static void imq_nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
-+{
-+      int status;
-+
-+      if (!entry->next_outfn) {
-+              spin_lock_bh(&imq_nf_queue_lock);
-+              nf_reinject(entry, verdict);
-+              spin_unlock_bh(&imq_nf_queue_lock);
-+              return;
-+      }
-+
-+      rcu_read_lock();
-+      local_bh_disable();
-+      status = entry->next_outfn(entry, entry->next_queuenum);
-+      local_bh_enable();
-+      if (status < 0) {
-+              nf_queue_entry_release_refs(entry);
-+              kfree_skb(entry->skb);
-+              kfree(entry);
-+      }
-+
-+      rcu_read_unlock();
-+}
-+
-+static netdev_tx_t imq_dev_xmit(struct sk_buff *skb, struct net_device *dev)
-+{
-+      struct nf_queue_entry *entry = skb->nf_queue_entry;
-+
-+      skb->nf_queue_entry = NULL;
-+      dev->trans_start = jiffies;
-+
-+      dev->stats.tx_bytes += skb->len;
-+      dev->stats.tx_packets++;
-+
-+      if (entry == NULL) {
-+              /* We don't know what is going on here.. packet is queued for
-+               * imq device, but (probably) not by us.
-+               *
-+               * If this packet was not send here by imq_nf_queue(), then
-+               * skb_save_cb() was not used and skb_free() should not show:
-+               *   WARNING: IMQ: kfree_skb: skb->cb_next:..
-+               * and/or
-+               *   WARNING: IMQ: kfree_skb: skb->nf_queue_entry...
-+               *
-+               * However if this message is shown, then IMQ is somehow broken
-+               * and you should report this to linuximq.net.
-+               */
-+
-+              /* imq_dev_xmit is black hole that eats all packets, report that
-+               * we eat this packet happily and increase dropped counters.
-+               */
-+
-+              dev->stats.tx_dropped++;
-+              dev_kfree_skb(skb);
-+
-+              return NETDEV_TX_OK;
-+      }
-+
-+      skb_restore_cb(skb); /* restore skb->cb */
-+
-+      skb->imq_flags = 0;
-+      skb->destructor = NULL;
-+
-+      imq_nf_reinject(entry, NF_ACCEPT);
-+
-+      return NETDEV_TX_OK;
-+}
-+
-+static int imq_nf_queue(struct nf_queue_entry *entry, unsigned queue_num)
-+{
-+      struct net_device *dev;
-+      struct sk_buff *skb_orig, *skb, *skb_shared;
-+      struct Qdisc *q;
-+      struct netdev_queue *txq;
-+      int users, index;
-+      int retval = -EINVAL;
-+
-+      index = entry->skb->imq_flags & IMQ_F_IFMASK;
-+      if (unlikely(index > numdevs - 1)) {
-+              if (net_ratelimit())
-+                      printk(KERN_WARNING
-+                             "IMQ: invalid device specified, highest is %u\n",
-+                             numdevs - 1);
-+              retval = -EINVAL;
-+              goto out;
-+      }
-+
-+      /* check for imq device by index from cache */
-+      dev = imq_devs_cache[index];
-+      if (unlikely(!dev)) {
-+              char buf[8];
-+
-+              /* get device by name and cache result */
-+              snprintf(buf, sizeof(buf), "imq%d", index);
-+              dev = dev_get_by_name(&init_net, buf);
-+              if (!dev) {
-+                      /* not found ?!*/
-+                      BUG();
-+                      retval = -ENODEV;
-+                      goto out;
-+              }
-+
-+              imq_devs_cache[index] = dev;
-+              dev_put(dev);
-+      }
-+
-+      if (unlikely(!(dev->flags & IFF_UP))) {
-+              entry->skb->imq_flags = 0;
-+              imq_nf_reinject_lockless(entry, NF_ACCEPT);
-+              retval = 0;
-+              goto out;
-+      }
-+      dev->last_rx = jiffies;
-+
-+      skb = entry->skb;
-+      skb_orig = NULL;
-+
-+      /* skb has owner? => make clone */
-+      if (unlikely(skb->destructor)) {
-+              skb_orig = skb;
-+              skb = skb_clone(skb, GFP_ATOMIC);
-+              if (!skb) {
-+                      retval = -ENOMEM;
-+                      goto out;
-+              }
-+              entry->skb = skb;
-+      }
-+
-+      skb->nf_queue_entry = entry;
-+
-+      dev->stats.rx_bytes += skb->len;
-+      dev->stats.rx_packets++;
-+
-+      txq = dev_pick_tx(dev, skb);
-+
-+      q = rcu_dereference(txq->qdisc);
-+      if (unlikely(!q->enqueue))
-+              goto packet_not_eaten_by_imq_dev;
-+
-+      spin_lock_bh(qdisc_lock(q));
-+
-+      users = atomic_read(&skb->users);
-+
-+      skb_shared = skb_get(skb); /* increase reference count by one */
-+      skb_save_cb(skb_shared); /* backup skb->cb, as qdisc layer will
-+                                      overwrite it */
-+      qdisc_enqueue_root(skb_shared, q); /* might kfree_skb */
-+
-+      if (likely(atomic_read(&skb_shared->users) == users + 1)) {
-+              kfree_skb(skb_shared); /* decrease reference count by one */
-+
-+              skb->destructor = &imq_skb_destructor;
-+
-+              /* cloned? */
-+              if (skb_orig)
-+                      kfree_skb(skb_orig); /* free original */
-+
-+              spin_unlock_bh(qdisc_lock(q));
-+
-+              /* schedule qdisc dequeue */
-+              __netif_schedule(q);
-+
-+              retval = 0;
-+              goto out;
-+      } else {
-+              skb_restore_cb(skb_shared); /* restore skb->cb */
-+              skb->nf_queue_entry = NULL;
-+              /* qdisc dropped packet and decreased skb reference count of
-+               * skb, so we don't really want to and try refree as that would
-+               * actually destroy the skb. */
-+              spin_unlock_bh(qdisc_lock(q));
-+              goto packet_not_eaten_by_imq_dev;
-+      }
-+
-+packet_not_eaten_by_imq_dev:
-+      /* cloned? restore original */
-+      if (skb_orig) {
-+              kfree_skb(skb);
-+              entry->skb = skb_orig;
-+      }
-+      retval = -1;
-+out:
-+      return retval;
-+}
-+
-+static struct nf_queue_handler nfqh = {
-+      .name  = "imq",
-+      .outfn = imq_nf_queue,
-+};
-+
-+static unsigned int imq_nf_hook(unsigned int hook, struct sk_buff *pskb,
-+                              const struct net_device *indev,
-+                              const struct net_device *outdev,
-+                              int (*okfn)(struct sk_buff *))
-+{
-+      if (pskb->imq_flags & IMQ_F_ENQUEUE)
-+              return NF_QUEUE;
-+
-+      return NF_ACCEPT;
-+}
-+
-+static int imq_close(struct net_device *dev)
-+{
-+      netif_stop_queue(dev);
-+      return 0;
-+}
-+
-+static int imq_open(struct net_device *dev)
-+{
-+      netif_start_queue(dev);
-+      return 0;
-+}
-+
-+static const struct net_device_ops imq_netdev_ops = {
-+      .ndo_open               = imq_open,
-+      .ndo_stop               = imq_close,
-+      .ndo_start_xmit         = imq_dev_xmit,
-+      .ndo_get_stats          = imq_get_stats,
-+};
-+
-+static void imq_setup(struct net_device *dev)
-+{
-+      dev->netdev_ops         = &imq_netdev_ops;
-+      dev->type               = ARPHRD_VOID;
-+      dev->mtu                = 16000;
-+      dev->tx_queue_len       = 11000;
-+      dev->flags              = IFF_NOARP;
-+      dev->features           = NETIF_F_SG | NETIF_F_FRAGLIST |
-+                                NETIF_F_GSO | NETIF_F_HW_CSUM |
-+                                NETIF_F_HIGHDMA;
-+      dev->priv_flags         &= ~IFF_XMIT_DST_RELEASE;
-+}
-+
-+static int imq_validate(struct nlattr *tb[], struct nlattr *data[])
-+{
-+      int ret = 0;
-+
-+      if (tb[IFLA_ADDRESS]) {
-+              if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) {
-+                      ret = -EINVAL;
-+                      goto end;
-+              }
-+              if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) {
-+                      ret = -EADDRNOTAVAIL;
-+                      goto end;
-+              }
-+      }
-+      return 0;
-+end:
-+      printk(KERN_WARNING "IMQ: imq_validate failed (%d)\n", ret);
-+      return ret;
-+}
-+
-+static struct rtnl_link_ops imq_link_ops __read_mostly = {
-+      .kind           = "imq",
-+      .priv_size      = 0,
-+      .setup          = imq_setup,
-+      .validate       = imq_validate,
-+};
-+
-+static int __init imq_init_hooks(void)
-+{
-+      int err;
-+
-+      nf_register_queue_imq_handler(&nfqh);
-+
-+      err = nf_register_hook(&imq_ingress_ipv4);
-+      if (err)
-+              goto err1;
-+
-+      err = nf_register_hook(&imq_egress_ipv4);
-+      if (err)
-+              goto err2;
-+
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+      err = nf_register_hook(&imq_ingress_ipv6);
-+      if (err)
-+              goto err3;
-+
-+      err = nf_register_hook(&imq_egress_ipv6);
-+      if (err)
-+              goto err4;
-+#endif
-+
-+      return 0;
-+
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+err4:
-+      nf_unregister_hook(&imq_ingress_ipv6);
-+err3:
-+      nf_unregister_hook(&imq_egress_ipv4);
-+#endif
-+err2:
-+      nf_unregister_hook(&imq_ingress_ipv4);
-+err1:
-+      nf_unregister_queue_imq_handler();
-+      return err;
-+}
-+
-+static int __init imq_init_one(int index)
-+{
-+      struct net_device *dev;
-+      int ret;
-+
-+      dev = alloc_netdev(0, "imq%d", imq_setup);
-+      if (!dev)
-+              return -ENOMEM;
-+
-+      ret = dev_alloc_name(dev, dev->name);
-+      if (ret < 0)
-+              goto fail;
-+
-+      dev->rtnl_link_ops = &imq_link_ops;
-+      ret = register_netdevice(dev);
-+      if (ret < 0)
-+              goto fail;
-+
-+      return 0;
-+fail:
-+      free_netdev(dev);
-+      return ret;
-+}
-+
-+static int __init imq_init_devs(void)
-+{
-+      int err, i;
-+
-+      if (numdevs < 1 || numdevs > IMQ_MAX_DEVS) {
-+              printk(KERN_ERR "IMQ: numdevs has to be betweed 1 and %u\n",
-+                     IMQ_MAX_DEVS);
-+              return -EINVAL;
-+      }
-+
-+      rtnl_lock();
-+      err = __rtnl_link_register(&imq_link_ops);
-+
-+      for (i = 0; i < numdevs && !err; i++)
-+              err = imq_init_one(i);
-+
-+      if (err) {
-+              __rtnl_link_unregister(&imq_link_ops);
-+              memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
-+      }
-+      rtnl_unlock();
-+
-+      return err;
-+}
-+
-+static int __init imq_init_module(void)
-+{
-+      int err;
-+
-+#if defined(CONFIG_IMQ_NUM_DEVS)
-+      BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS > 16);
-+      BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS < 2);
-+      BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS - 1 > IMQ_F_IFMASK);
-+#endif
-+
-+      err = imq_init_devs();
-+      if (err) {
-+              printk(KERN_ERR "IMQ: Error trying imq_init_devs(net)\n");
-+              return err;
-+      }
-+
-+      err = imq_init_hooks();
-+      if (err) {
-+              printk(KERN_ERR "IMQ: Error trying imq_init_hooks()\n");
-+              rtnl_link_unregister(&imq_link_ops);
-+              memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
-+              return err;
-+      }
-+
-+      printk(KERN_INFO "IMQ driver loaded successfully.\n");
-+
-+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+      printk(KERN_INFO "\tHooking IMQ before NAT on PREROUTING.\n");
-+#else
-+      printk(KERN_INFO "\tHooking IMQ after NAT on PREROUTING.\n");
-+#endif
-+#if defined(CONFIG_IMQ_BEHAVIOR_AB) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+      printk(KERN_INFO "\tHooking IMQ before NAT on POSTROUTING.\n");
-+#else
-+      printk(KERN_INFO "\tHooking IMQ after NAT on POSTROUTING.\n");
-+#endif
-+
-+      return 0;
-+}
-+
-+static void __exit imq_unhook(void)
-+{
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+      nf_unregister_hook(&imq_ingress_ipv6);
-+      nf_unregister_hook(&imq_egress_ipv6);
-+#endif
-+      nf_unregister_hook(&imq_ingress_ipv4);
-+      nf_unregister_hook(&imq_egress_ipv4);
-+
-+      nf_unregister_queue_imq_handler();
-+}
-+
-+static void __exit imq_cleanup_devs(void)
-+{
-+      rtnl_link_unregister(&imq_link_ops);
-+      memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
-+}
-+
-+static void __exit imq_exit_module(void)
-+{
-+      imq_unhook();
-+      imq_cleanup_devs();
-+      printk(KERN_INFO "IMQ driver unloaded successfully.\n");
-+}
-+
-+module_init(imq_init_module);
-+module_exit(imq_exit_module);
-+
-+module_param(numdevs, int, 0);
-+MODULE_PARM_DESC(numdevs, "number of IMQ devices (how many imq* devices will "
-+                      "be created)");
-+MODULE_AUTHOR("http://www.linuximq.net");
-+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See "
-+                      "http://www.linuximq.net/ for more information.");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS_RTNL_LINK("imq");
-+
---- a/drivers/net/Kconfig
-+++ b/drivers/net/Kconfig
-@@ -121,6 +121,129 @@ config EQUALIZER
-         To compile this driver as a module, choose M here: the module
-         will be called eql.  If unsure, say N.
-+config IMQ
-+      tristate "IMQ (intermediate queueing device) support"
-+      depends on NETDEVICES && NETFILTER
-+      ---help---
-+        The IMQ device(s) is used as placeholder for QoS queueing
-+        disciplines. Every packet entering/leaving the IP stack can be
-+        directed through the IMQ device where it's enqueued/dequeued to the
-+        attached qdisc. This allows you to treat network devices as classes
-+        and distribute bandwidth among them. Iptables is used to specify
-+        through which IMQ device, if any, packets travel.
-+
-+        More information at: http://www.linuximq.net/
-+
-+        To compile this driver as a module, choose M here: the module
-+        will be called imq.  If unsure, say N.
-+
-+choice
-+      prompt "IMQ behavior (PRE/POSTROUTING)"
-+      depends on IMQ
-+      default IMQ_BEHAVIOR_AB
-+      help
-+
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              IMQ can work in any of the following ways:
-+
-+                  PREROUTING   |      POSTROUTING
-+              -----------------|-------------------
-+              #1  After NAT    |      After NAT
-+              #2  After NAT    |      Before NAT
-+              #3  Before NAT   |      After NAT
-+              #4  Before NAT   |      Before NAT
-+
-+              The default behavior is to hook before NAT on PREROUTING
-+              and after NAT on POSTROUTING (#3).
-+
-+              This settings are specially usefull when trying to use IMQ
-+              to shape NATed clients.
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_AA
-+      bool "IMQ AA"
-+      help
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              Choosing this option will make IMQ hook like this:
-+
-+              PREROUTING:   After NAT
-+              POSTROUTING:  After NAT
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_AB
-+      bool "IMQ AB"
-+      help
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              Choosing this option will make IMQ hook like this:
-+
-+              PREROUTING:   After NAT
-+              POSTROUTING:  Before NAT
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_BA
-+      bool "IMQ BA"
-+      help
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              Choosing this option will make IMQ hook like this:
-+
-+              PREROUTING:   Before NAT
-+              POSTROUTING:  After NAT
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_BB
-+      bool "IMQ BB"
-+      help
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              Choosing this option will make IMQ hook like this:
-+
-+              PREROUTING:   Before NAT
-+              POSTROUTING:  Before NAT
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+endchoice
-+
-+config IMQ_NUM_DEVS
-+
-+      int "Number of IMQ devices"
-+      range 2 16
-+      depends on IMQ
-+      default "16"
-+      help
-+
-+              This settings defines how many IMQ devices will be
-+              created.
-+
-+              The default value is 16.
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
- config TUN
-       tristate "Universal TUN/TAP device driver support"
-       select CRC32
---- a/drivers/net/Makefile
-+++ b/drivers/net/Makefile
-@@ -169,6 +169,7 @@ obj-$(CONFIG_SLHC) += slhc.o
- obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o
- obj-$(CONFIG_DUMMY) += dummy.o
-+obj-$(CONFIG_IMQ) += imq.o
- obj-$(CONFIG_IFB) += ifb.o
- obj-$(CONFIG_MACVLAN) += macvlan.o
- obj-$(CONFIG_MACVTAP) += macvtap.o
---- /dev/null
-+++ b/include/linux/imq.h
-@@ -0,0 +1,13 @@
-+#ifndef _IMQ_H
-+#define _IMQ_H
-+
-+/* IFMASK (16 device indexes, 0 to 15) and flag(s) fit in 5 bits */
-+#define IMQ_F_BITS    5
-+
-+#define IMQ_F_IFMASK  0x0f
-+#define IMQ_F_ENQUEUE 0x10
-+
-+#define IMQ_MAX_DEVS  (IMQ_F_IFMASK + 1)
-+
-+#endif /* _IMQ_H */
-+
---- a/include/linux/netdevice.h
-+++ b/include/linux/netdevice.h
-@@ -1295,6 +1295,7 @@ extern int               dev_alloc_name(struct net_de
- extern int            dev_open(struct net_device *dev);
- extern int            dev_close(struct net_device *dev);
- extern void           dev_disable_lro(struct net_device *dev);
-+extern struct netdev_queue *dev_pick_tx(struct net_device *dev, struct sk_buff *skb);
- extern int            dev_queue_xmit(struct sk_buff *skb);
- extern int            register_netdevice(struct net_device *dev);
- extern void           unregister_netdevice_queue(struct net_device *dev,
---- /dev/null
-+++ b/include/linux/netfilter/xt_IMQ.h
-@@ -0,0 +1,9 @@
-+#ifndef _XT_IMQ_H
-+#define _XT_IMQ_H
-+
-+struct xt_imq_info {
-+      unsigned int todev;     /* target imq device */
-+};
-+
-+#endif /* _XT_IMQ_H */
-+
---- /dev/null
-+++ b/include/linux/netfilter_ipv4/ipt_IMQ.h
-@@ -0,0 +1,10 @@
-+#ifndef _IPT_IMQ_H
-+#define _IPT_IMQ_H
-+
-+/* Backwards compatibility for old userspace */
-+#include <linux/netfilter/xt_IMQ.h>
-+
-+#define ipt_imq_info xt_imq_info
-+
-+#endif /* _IPT_IMQ_H */
-+
---- /dev/null
-+++ b/include/linux/netfilter_ipv6/ip6t_IMQ.h
-@@ -0,0 +1,10 @@
-+#ifndef _IP6T_IMQ_H
-+#define _IP6T_IMQ_H
-+
-+/* Backwards compatibility for old userspace */
-+#include <linux/netfilter/xt_IMQ.h>
-+
-+#define ip6t_imq_info xt_imq_info
-+
-+#endif /* _IP6T_IMQ_H */
-+
---- a/include/linux/skbuff.h
-+++ b/include/linux/skbuff.h
-@@ -29,6 +29,9 @@
- #include <linux/rcupdate.h>
- #include <linux/dmaengine.h>
- #include <linux/hrtimer.h>
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+#include <linux/imq.h>
-+#endif
- /* Don't change this without changing skb_csum_unnecessary! */
- #define CHECKSUM_NONE 0
-@@ -330,6 +333,9 @@ struct sk_buff {
-        * first. This is owned by whoever has the skb queued ATM.
-        */
-       char                    cb[48] __aligned(8);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      void                    *cb_next;
-+#endif
-       unsigned long           _skb_refdst;
- #ifdef CONFIG_XFRM
-@@ -366,6 +372,9 @@ struct sk_buff {
-       struct nf_conntrack     *nfct;
-       struct sk_buff          *nfct_reasm;
- #endif
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      struct nf_queue_entry   *nf_queue_entry;
-+#endif
- #ifdef CONFIG_BRIDGE_NETFILTER
-       struct nf_bridge_info   *nf_bridge;
- #endif
-@@ -392,6 +401,10 @@ struct sk_buff {
-       /* 0/14 bit hole */
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      __u8                    imq_flags:IMQ_F_BITS;
-+#endif
-+
- #ifdef CONFIG_NET_DMA
-       dma_cookie_t            dma_cookie;
- #endif
-@@ -490,6 +503,12 @@ static inline struct rtable *skb_rtable(
-       return (struct rtable *)skb_dst(skb);
- }
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+extern int skb_save_cb(struct sk_buff *skb);
-+extern int skb_restore_cb(struct sk_buff *skb);
-+#endif
-+
- extern void kfree_skb(struct sk_buff *skb);
- extern void consume_skb(struct sk_buff *skb);
- extern void          __kfree_skb(struct sk_buff *skb);
-@@ -2096,6 +2115,10 @@ static inline void __nf_copy(struct sk_b
-       dst->nfct_reasm = src->nfct_reasm;
-       nf_conntrack_get_reasm(src->nfct_reasm);
- #endif
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      dst->imq_flags = src->imq_flags;
-+      dst->nf_queue_entry = src->nf_queue_entry;
-+#endif
- #ifdef CONFIG_BRIDGE_NETFILTER
-       dst->nf_bridge  = src->nf_bridge;
-       nf_bridge_get(src->nf_bridge);
---- a/include/net/netfilter/nf_queue.h
-+++ b/include/net/netfilter/nf_queue.h
-@@ -13,6 +13,12 @@ struct nf_queue_entry {
-       struct net_device       *indev;
-       struct net_device       *outdev;
-       int                     (*okfn)(struct sk_buff *);
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      int                     (*next_outfn)(struct nf_queue_entry *entry,
-+                                            unsigned int queuenum);
-+      unsigned int            next_queuenum;
-+#endif
- };
- #define nf_queue_entry_reroute(x) ((void *)x + sizeof(struct nf_queue_entry))
-@@ -30,5 +36,11 @@ extern int nf_unregister_queue_handler(u
-                                      const struct nf_queue_handler *qh);
- extern void nf_unregister_queue_handlers(const struct nf_queue_handler *qh);
- extern void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
-+extern void nf_queue_entry_release_refs(struct nf_queue_entry *entry);
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+extern void nf_register_queue_imq_handler(const struct nf_queue_handler *qh);
-+extern void nf_unregister_queue_imq_handler(void);
-+#endif
- #endif /* _NF_QUEUE_H */
---- a/net/core/dev.c
-+++ b/net/core/dev.c
-@@ -98,6 +98,9 @@
- #include <net/net_namespace.h>
- #include <net/sock.h>
- #include <linux/rtnetlink.h>
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+#include <linux/imq.h>
-+#endif
- #include <linux/proc_fs.h>
- #include <linux/seq_file.h>
- #include <linux/stat.h>
-@@ -1942,7 +1945,11 @@ int dev_hard_start_xmit(struct sk_buff *
-       int rc = NETDEV_TX_OK;
-       if (likely(!skb->next)) {
--              if (!list_empty(&ptype_all))
-+              if (!list_empty(&ptype_all)
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+                      && !(skb->imq_flags & IMQ_F_ENQUEUE)
-+#endif
-+                 )
-                       dev_queue_xmit_nit(skb, dev);
-               /*
-@@ -2054,8 +2061,7 @@ static inline u16 dev_cap_txqueue(struct
-       return queue_index;
- }
--static struct netdev_queue *dev_pick_tx(struct net_device *dev,
--                                      struct sk_buff *skb)
-+struct netdev_queue *dev_pick_tx(struct net_device *dev, struct sk_buff *skb)
- {
-       int queue_index;
-       const struct net_device_ops *ops = dev->netdev_ops;
-@@ -2084,6 +2090,7 @@ static struct netdev_queue *dev_pick_tx(
-       skb_set_queue_mapping(skb, queue_index);
-       return netdev_get_tx_queue(dev, queue_index);
- }
-+EXPORT_SYMBOL(dev_pick_tx);
- static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
-                                struct net_device *dev,
---- a/net/core/skbuff.c
-+++ b/net/core/skbuff.c
-@@ -72,6 +72,9 @@
- static struct kmem_cache *skbuff_head_cache __read_mostly;
- static struct kmem_cache *skbuff_fclone_cache __read_mostly;
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+static struct kmem_cache *skbuff_cb_store_cache __read_mostly;
-+#endif
- static void sock_pipe_buf_release(struct pipe_inode_info *pipe,
-                                 struct pipe_buffer *buf)
-@@ -91,6 +94,83 @@ static int sock_pipe_buf_steal(struct pi
-       return 1;
- }
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+/* Control buffer save/restore for IMQ devices */
-+struct skb_cb_table {
-+      void                    *cb_next;
-+      atomic_t                refcnt;
-+      char                    cb[48];
-+};
-+
-+static DEFINE_SPINLOCK(skb_cb_store_lock);
-+
-+int skb_save_cb(struct sk_buff *skb)
-+{
-+      struct skb_cb_table *next;
-+
-+      next = kmem_cache_alloc(skbuff_cb_store_cache, GFP_ATOMIC);
-+      if (!next)
-+              return -ENOMEM;
-+
-+      BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb));
-+
-+      memcpy(next->cb, skb->cb, sizeof(skb->cb));
-+      next->cb_next = skb->cb_next;
-+
-+      atomic_set(&next->refcnt, 1);
-+
-+      skb->cb_next = next;
-+      return 0;
-+}
-+EXPORT_SYMBOL(skb_save_cb);
-+
-+int skb_restore_cb(struct sk_buff *skb)
-+{
-+      struct skb_cb_table *next;
-+
-+      if (!skb->cb_next)
-+              return 0;
-+
-+      next = skb->cb_next;
-+
-+      BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb));
-+
-+      memcpy(skb->cb, next->cb, sizeof(skb->cb));
-+      skb->cb_next = next->cb_next;
-+
-+      spin_lock(&skb_cb_store_lock);
-+
-+      if (atomic_dec_and_test(&next->refcnt)) {
-+              kmem_cache_free(skbuff_cb_store_cache, next);
-+      }
-+
-+      spin_unlock(&skb_cb_store_lock);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL(skb_restore_cb);
-+
-+static void skb_copy_stored_cb(struct sk_buff *new, const struct sk_buff *__old)
-+{
-+      struct skb_cb_table *next;
-+      struct sk_buff *old;
-+
-+      if (!__old->cb_next) {
-+              new->cb_next = NULL;
-+              return;
-+      }
-+
-+      spin_lock(&skb_cb_store_lock);
-+
-+      old = (struct sk_buff *)__old;
-+
-+      next = old->cb_next;
-+      atomic_inc(&next->refcnt);
-+      new->cb_next = next;
-+
-+      spin_unlock(&skb_cb_store_lock);
-+}
-+#endif
- /* Pipe buffer operations for a socket. */
- static const struct pipe_buf_operations sock_pipe_buf_ops = {
-@@ -391,6 +471,26 @@ static void skb_release_head_state(struc
-               WARN_ON(in_irq());
-               skb->destructor(skb);
-       }
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      /* This should not happen. When it does, avoid memleak by restoring
-+      the chain of cb-backups. */
-+      while(skb->cb_next != NULL) {
-+              if (net_ratelimit())
-+                      printk(KERN_WARNING "IMQ: kfree_skb: skb->cb_next: "
-+                              "%08x\n", (unsigned int)skb->cb_next);
-+
-+              skb_restore_cb(skb);
-+      }
-+      /* This should not happen either, nf_queue_entry is nullified in
-+       * imq_dev_xmit(). If we have non-NULL nf_queue_entry then we are
-+       * leaking entry pointers, maybe memory. We don't know if this is
-+       * pointer to already freed memory, or should this be freed.
-+       * If this happens we need to add refcounting, etc for nf_queue_entry.
-+       */
-+      if (skb->nf_queue_entry && net_ratelimit())
-+              printk(KERN_WARNING
-+                              "IMQ: kfree_skb: skb->nf_queue_entry != NULL");
-+#endif
- #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
-       nf_conntrack_put(skb->nfct);
-       nf_conntrack_put_reasm(skb->nfct_reasm);
-@@ -526,6 +626,9 @@ static void __copy_skb_header(struct sk_
-       new->sp                 = secpath_get(old->sp);
- #endif
-       memcpy(new->cb, old->cb, sizeof(old->cb));
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      skb_copy_stored_cb(new, old);
-+#endif
-       new->csum               = old->csum;
-       new->local_df           = old->local_df;
-       new->pkt_type           = old->pkt_type;
-@@ -2779,6 +2882,13 @@ void __init skb_init(void)
-                                               0,
-                                               SLAB_HWCACHE_ALIGN|SLAB_PANIC,
-                                               NULL);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      skbuff_cb_store_cache = kmem_cache_create("skbuff_cb_store_cache",
-+                                                sizeof(struct skb_cb_table),
-+                                                0,
-+                                                SLAB_HWCACHE_ALIGN|SLAB_PANIC,
-+                                                NULL);
-+#endif
- }
- /**
---- a/net/netfilter/Kconfig
-+++ b/net/netfilter/Kconfig
-@@ -455,6 +455,18 @@ config NETFILTER_XT_TARGET_LED
-         For more information on the LEDs available on your system, see
-         Documentation/leds-class.txt
-+config NETFILTER_XT_TARGET_IMQ
-+        tristate '"IMQ" target support'
-+      depends on NETFILTER_XTABLES
-+      depends on IP_NF_MANGLE || IP6_NF_MANGLE
-+      select IMQ
-+      default m if NETFILTER_ADVANCED=n
-+        help
-+          This option adds a `IMQ' target which is used to specify if and
-+          to which imq device packets should get enqueued/dequeued.
-+
-+          To compile it as a module, choose M here.  If unsure, say N.
-+
- config NETFILTER_XT_TARGET_MARK
-       tristate '"MARK" target support'
-       depends on NETFILTER_ADVANCED
---- a/net/netfilter/Makefile
-+++ b/net/netfilter/Makefile
-@@ -51,6 +51,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSEC
- obj-$(CONFIG_NETFILTER_XT_TARGET_CT) += xt_CT.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o
-+obj-$(CONFIG_NETFILTER_XT_TARGET_IMQ) += xt_IMQ.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
---- a/net/netfilter/nf_queue.c
-+++ b/net/netfilter/nf_queue.c
-@@ -22,6 +22,26 @@ static const struct nf_queue_handler *qu
- static DEFINE_MUTEX(queue_handler_mutex);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+static const struct nf_queue_handler *queue_imq_handler;
-+
-+void nf_register_queue_imq_handler(const struct nf_queue_handler *qh)
-+{
-+      mutex_lock(&queue_handler_mutex);
-+      rcu_assign_pointer(queue_imq_handler, qh);
-+      mutex_unlock(&queue_handler_mutex);
-+}
-+EXPORT_SYMBOL(nf_register_queue_imq_handler);
-+
-+void nf_unregister_queue_imq_handler(void)
-+{
-+      mutex_lock(&queue_handler_mutex);
-+      rcu_assign_pointer(queue_imq_handler, NULL);
-+      mutex_unlock(&queue_handler_mutex);
-+}
-+EXPORT_SYMBOL(nf_unregister_queue_imq_handler);
-+#endif
-+
- /* return EBUSY when somebody else is registered, return EEXIST if the
-  * same handler is registered, return 0 in case of success. */
- int nf_register_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh)
-@@ -82,7 +102,7 @@ void nf_unregister_queue_handlers(const
- }
- EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers);
--static void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
-+void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
- {
-       /* Release those devices we held, or Alexey will kill me. */
-       if (entry->indev)
-@@ -102,6 +122,7 @@ static void nf_queue_entry_release_refs(
-       /* Drop reference to owner of hook which queued us. */
-       module_put(entry->elem->owner);
- }
-+EXPORT_SYMBOL_GPL(nf_queue_entry_release_refs);
- /*
-  * Any packet that leaves via this function must come back
-@@ -123,12 +144,26 @@ static int __nf_queue(struct sk_buff *sk
- #endif
-       const struct nf_afinfo *afinfo;
-       const struct nf_queue_handler *qh;
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      const struct nf_queue_handler *qih = NULL;
-+#endif
-       /* QUEUE == DROP if noone is waiting, to be safe. */
-       rcu_read_lock();
-       qh = rcu_dereference(queue_handler[pf]);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+      if (pf == PF_INET || pf == PF_INET6)
-+#else
-+      if (pf == PF_INET)
-+#endif
-+              qih = rcu_dereference(queue_imq_handler);
-+
-+      if (!qh && !qih)
-+#else /* !IMQ */
-       if (!qh)
-+#endif
-               goto err_unlock;
-       afinfo = nf_get_afinfo(pf);
-@@ -147,6 +182,10 @@ static int __nf_queue(struct sk_buff *sk
-               .indev  = indev,
-               .outdev = outdev,
-               .okfn   = okfn,
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+              .next_outfn = qh ? qh->outfn : NULL,
-+              .next_queuenum = queuenum,
-+#endif
-       };
-       /* If it's going away, ignore hook. */
-@@ -173,8 +212,19 @@ static int __nf_queue(struct sk_buff *sk
- #endif
-       skb_dst_force(skb);
-       afinfo->saveroute(skb, entry);
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      if (qih) {
-+              status = qih->outfn(entry, queuenum);
-+              goto imq_skip_queue;
-+      }
-+#endif
-+
-       status = qh->outfn(entry, queuenum);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+imq_skip_queue:
-+#endif
-       rcu_read_unlock();
-       if (status < 0) {
---- /dev/null
-+++ b/net/netfilter/xt_IMQ.c
-@@ -0,0 +1,73 @@
-+/*
-+ * This target marks packets to be enqueued to an imq device
-+ */
-+#include <linux/module.h>
-+#include <linux/skbuff.h>
-+#include <linux/netfilter/x_tables.h>
-+#include <linux/netfilter/xt_IMQ.h>
-+#include <linux/imq.h>
-+
-+static unsigned int imq_target(struct sk_buff *pskb,
-+                              const struct xt_action_param *par)
-+{
-+      const struct xt_imq_info *mr = par->targinfo;
-+
-+      pskb->imq_flags = (mr->todev & IMQ_F_IFMASK) | IMQ_F_ENQUEUE;
-+
-+      return XT_CONTINUE;
-+}
-+
-+static int imq_checkentry(const struct xt_tgchk_param *par)
-+{
-+      struct xt_imq_info *mr = par->targinfo;
-+
-+      if (mr->todev > IMQ_MAX_DEVS - 1) {
-+              printk(KERN_WARNING
-+                     "IMQ: invalid device specified, highest is %u\n",
-+                     IMQ_MAX_DEVS - 1);
-+              return -EINVAL;
-+      }
-+
-+      return 0;
-+}
-+
-+static struct xt_target xt_imq_reg[] __read_mostly = {
-+      {
-+              .name           = "IMQ",
-+              .family         = AF_INET,
-+              .checkentry     = imq_checkentry,
-+              .target         = imq_target,
-+              .targetsize     = sizeof(struct xt_imq_info),
-+              .table          = "mangle",
-+              .me             = THIS_MODULE
-+      },
-+      {
-+              .name           = "IMQ",
-+              .family         = AF_INET6,
-+              .checkentry     = imq_checkentry,
-+              .target         = imq_target,
-+              .targetsize     = sizeof(struct xt_imq_info),
-+              .table          = "mangle",
-+              .me             = THIS_MODULE
-+      },
-+};
-+
-+static int __init imq_init(void)
-+{
-+      return xt_register_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg));
-+}
-+
-+static void __exit imq_fini(void)
-+{
-+      xt_unregister_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg));
-+}
-+
-+module_init(imq_init);
-+module_exit(imq_fini);
-+
-+MODULE_AUTHOR("http://www.linuximq.net");
-+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information.");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS("ipt_IMQ");
-+MODULE_ALIAS("ip6t_IMQ");
-+
index 4cf9fcf158c8ebd7567a4edfaff707f01cb777a1..65c4d44c2b3b652ce0897820a74b11de6f51f3df 100644 (file)
@@ -8,7 +8,7 @@
        depends on NETFILTER_ADVANCED
        help
          H.323 is a VoIP signalling protocol from ITU-T. As one of the most
-@@ -569,7 +568,6 @@ config NETFILTER_XT_TARGET_SECMARK
+@@ -557,7 +556,6 @@ config NETFILTER_XT_TARGET_SECMARK
  
  config NETFILTER_XT_TARGET_TCPMSS
        tristate '"TCPMSS" target support'
index e4324717b4459ce1f1009053e6317c930b01b6e4..6ea9ba51ee0d24cf3a3ac657278109d9b11de859 100644 (file)
@@ -1,6 +1,6 @@
 --- a/arch/mips/include/asm/string.h
 +++ b/arch/mips/include/asm/string.h
-@@ -133,11 +133,44 @@ strncmp(__const__ char *__cs, __const__
+@@ -133,11 +133,44 @@ strncmp(__const__ char *__cs, __const__ 
  
  #define __HAVE_ARCH_MEMSET
  extern void *memset(void *__s, int __c, size_t __count);
index fe8cecfc771ed7a1cd16d22361475b2151e8bb98..83fd6c309928d78bdbdc7db87abdd7b06383d9cd 100644 (file)
@@ -1,6 +1,6 @@
 --- a/include/linux/slab.h
 +++ b/include/linux/slab.h
-@@ -130,8 +130,8 @@ int kmem_ptr_validate(struct kmem_cache
+@@ -130,8 +130,8 @@ int kmem_ptr_validate(struct kmem_cache 
   * to do various tricks to work around compiler limitations in order to
   * ensure proper constant folding.
   */
index d021ec1b309347e8ece84b6885d6f2ac97f22ed9..826eb44dff3e214d78027bef349ff5ae7f4e2db1 100644 (file)
@@ -61,7 +61,7 @@
  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
  extern int mini_fo_create(inode_t *dir, dentry_t *dentry, int mode, struct nameidata *nd);
  
-@@ -501,6 +505,29 @@ static inline void double_unlock(struct
+@@ -501,6 +505,29 @@ static inline void double_unlock(struct 
  #endif  /* if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) */
  #endif /* __KERNEL__ */
  
  #endif /* defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) */
 --- a/fs/mini_fo/aux.c
 +++ b/fs/mini_fo/aux.c
-@@ -164,11 +164,11 @@ dentry_t *bpath_walk(super_block_t *sb,
+@@ -164,11 +164,11 @@ dentry_t *bpath_walk(super_block_t *sb, 
        err = vfs_path_lookup(mnt->mnt_root, mnt, bpath+1, 0, &nd);
  
        /* validate */
index d2a843c82ee77b1c57f51b935313443eabc290de..37503710c83afd8e41705eaf8397e6740273b33a 100644 (file)
@@ -1,6 +1,6 @@
 --- a/fs/mini_fo/super.c
 +++ b/fs/mini_fo/super.c
-@@ -84,6 +84,7 @@ mini_fo_write_inode(inode_t *inode, int
+@@ -84,6 +84,7 @@ mini_fo_write_inode(inode_t *inode, int 
  #endif /* defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) */
  
  
index cfe96f194e85d59fce30c645f113a88a42b69eb8..7f50a199d4f9267b23cb17c46c0b89ebef7bedcc 100644 (file)
@@ -20,7 +20,7 @@
  #else
  static inline int kobject_uevent(struct kobject *kobj,
                                 enum kobject_action action)
-@@ -229,6 +235,16 @@ static inline int add_uevent_var(struct
+@@ -229,6 +235,16 @@ static inline int add_uevent_var(struct 
  static inline int kobject_action_type(const char *buf, size_t count,
                                      enum kobject_action *type)
  { return -EINVAL; }
index e02d1bc317605baa14ba2173cc9687c8956cc506..286bdaec98b64a9d1e19d19e3a1ec375ff61b39a 100644 (file)
 +module_exit(connmark_cleanup_module);
 --- a/net/sched/Kconfig
 +++ b/net/sched/Kconfig
-@@ -549,6 +549,18 @@
+@@ -549,6 +549,18 @@ config NET_ACT_SKBEDIT
          To compile this code as a module, choose M here: the
          module will be called act_skbedit.
  
        depends on NET_CLS_U32 || NET_CLS_FW
 --- a/net/sched/Makefile
 +++ b/net/sched/Makefile
-@@ -15,6 +15,7 @@
+@@ -15,6 +15,7 @@ obj-$(CONFIG_NET_ACT_NAT)    += act_nat.o
  obj-$(CONFIG_NET_ACT_PEDIT)   += act_pedit.o
  obj-$(CONFIG_NET_ACT_SIMP)    += act_simple.o
  obj-$(CONFIG_NET_ACT_SKBEDIT) += act_skbedit.o
index f3f342f866dd3c268e50ca87ae14511e1d2f30eb..e3398a027014a879c189ce41db5c2a04aaac96b8 100644 (file)
@@ -11,7 +11,7 @@
  endif # NEW_LEDS
 --- a/drivers/leds/Makefile
 +++ b/drivers/leds/Makefile
-@@ -49,3 +49,4 @@ obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) +=
+@@ -49,3 +49,4 @@ obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += 
  obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT)  += ledtrig-backlight.o
  obj-$(CONFIG_LEDS_TRIGGER_GPIO)               += ledtrig-gpio.o
  obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
index 4eb139b9ba9b498f7ff1bf1df4046b9626fa0bb4..d229a2e4206ed99359cf5b85f9d42a3dfba314af 100644 (file)
@@ -14,7 +14,7 @@
  endif # NEW_LEDS
 --- a/drivers/leds/Makefile
 +++ b/drivers/leds/Makefile
-@@ -50,3 +50,4 @@ obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) +=
+@@ -50,3 +50,4 @@ obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) += 
  obj-$(CONFIG_LEDS_TRIGGER_GPIO)               += ledtrig-gpio.o
  obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
  obj-$(CONFIG_LEDS_TRIGGER_MORSE)      += ledtrig-morse.o
index 3b7063223ecda6601e050f7f19b8719af17b00dc..6609a1670af5e5d3297b09bbc6baf6cc0c67880b 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/char/gpio_dev.c
 +++ b/drivers/char/gpio_dev.c
-@@ -114,7 +114,7 @@ gpio_close(struct inode * inode, struct
+@@ -114,7 +114,7 @@ gpio_close(struct inode * inode, struct 
  }
  
  struct file_operations gpio_fops = {
index c334b17d0872a877f52cd9c0e4234ad118df7d09..5c70e79a058d050e90224ac0ef80dcb1180235ab 100644 (file)
                        dev->checkpointBlockList[i] = -1;
        }
  
-@@ -191,18 +185,17 @@ int yaffs_GetCheckpointSum(yaffs_Device
+@@ -191,18 +185,17 @@ int yaffs_GetCheckpointSum(yaffs_Device 
  
  static int yaffs_CheckpointFlushBuffer(yaffs_Device *dev)
  {
  {
        unsigned char cDelta;   /* column parity delta */
        unsigned lDelta;        /* line parity delta */
-@@ -294,8 +292,7 @@ int yaffs_ECCCorrectOther(unsigned char
+@@ -294,8 +292,7 @@ int yaffs_ECCCorrectOther(unsigned char 
                return 0; /* no error */
  
        if (lDelta == ~lDeltaPrime &&
                /* Single bit (recoverable) error in data */
  
                bit = 0;
-@@ -307,7 +304,7 @@ int yaffs_ECCCorrectOther(unsigned char
+@@ -307,7 +304,7 @@ int yaffs_ECCCorrectOther(unsigned char 
                if (cDelta & 0x02)
                        bit |= 0x01;
  
                        return -1;
  
                data[lDelta] ^= (1 << bit);
-@@ -316,7 +313,7 @@ int yaffs_ECCCorrectOther(unsigned char
+@@ -316,7 +313,7 @@ int yaffs_ECCCorrectOther(unsigned char 
        }
  
        if ((yaffs_CountBits32(lDelta) + yaffs_CountBits32(lDeltaPrime) +
                /* Reccoverable error in ecc */
  
                *read_ecc = *test_ecc;
-@@ -326,6 +323,4 @@ int yaffs_ECCCorrectOther(unsigned char
+@@ -326,6 +323,4 @@ int yaffs_ECCCorrectOther(unsigned char 
        /* Unrecoverable error */
  
        return -1;
  {
        unsigned char *alias;
        int ret;
-@@ -329,7 +395,7 @@ static int yaffs_readlink(struct dentry
+@@ -329,7 +395,7 @@ static int yaffs_readlink(struct dentry 
        return ret;
  }
  
  static int yaffs_file_flush(struct file *file, fl_owner_t id)
  #else
  static int yaffs_file_flush(struct file *file)
-@@ -513,8 +579,8 @@ static int yaffs_file_flush(struct file
+@@ -513,8 +579,8 @@ static int yaffs_file_flush(struct file 
        yaffs_Device *dev = obj->myDev;
  
        T(YAFFS_TRACE_OS,
  
        yaffs_GrossLock(dev);
  
-@@ -535,15 +601,15 @@ static int yaffs_readpage_nolock(struct
+@@ -535,15 +601,15 @@ static int yaffs_readpage_nolock(struct 
  
        yaffs_Device *dev;
  
        BUG_ON(!PageLocked(pg));
  #else
        if (!PageLocked(pg))
-@@ -555,9 +621,9 @@ static int yaffs_readpage_nolock(struct
+@@ -555,9 +621,9 @@ static int yaffs_readpage_nolock(struct 
  
        yaffs_GrossLock(dev);
  
  
        yaffs_GrossUnlock(dev);
  
-@@ -575,7 +641,7 @@ static int yaffs_readpage_nolock(struct
+@@ -575,7 +641,7 @@ static int yaffs_readpage_nolock(struct 
        flush_dcache_page(pg);
        kunmap(pg);
  
                if (n < step) {
                        n++;
                        continue;
-@@ -2119,7 +2356,7 @@ static int yaffs_proc_write(struct file
+@@ -2119,7 +2356,7 @@ static int yaffs_proc_write(struct file 
        char *end;
        char *mask_name;
        const char *x;
        int i;
        int done = 0;
        int add, len = 0;
-@@ -2129,9 +2366,8 @@ static int yaffs_proc_write(struct file
+@@ -2129,9 +2366,8 @@ static int yaffs_proc_write(struct file 
  
        while (!done && (pos < count)) {
                done = 1;
  
                switch (buf[pos]) {
                case '+':
-@@ -2148,20 +2384,21 @@ static int yaffs_proc_write(struct file
+@@ -2148,20 +2384,21 @@ static int yaffs_proc_write(struct file 
                mask_name = NULL;
  
                mask_bitfield = simple_strtoul(buf + pos, &end, 0);
                                        mask_name = mask_flags[i].mask_name;
                                        mask_bitfield = mask_flags[i].mask_bitfield;
                                        done = 0;
-@@ -2172,7 +2409,7 @@ static int yaffs_proc_write(struct file
+@@ -2172,7 +2409,7 @@ static int yaffs_proc_write(struct file 
  
                if (mask_name != NULL) {
                        done = 0;
                        case '-':
                                rg &= ~mask_bitfield;
                                break;
-@@ -2191,13 +2428,13 @@ static int yaffs_proc_write(struct file
+@@ -2191,13 +2428,13 @@ static int yaffs_proc_write(struct file 
  
        yaffs_traceMask = rg | YAFFS_TRACE_ALWAYS;
  
  {
        /* Get the real object in case we were fed a hard link as an equivalent object */
        equivalentObject = yaffs_GetEquivalentObject(equivalentObject);
-@@ -2363,33 +2396,31 @@ yaffs_Object *yaffs_Link(yaffs_Object *
+@@ -2363,33 +2396,31 @@ yaffs_Object *yaffs_Link(yaffs_Object * 
  
  }
  
        int nToCopy;
        int n = nBytes;
        int nDone = 0;
-@@ -4600,27 +4665,26 @@ int yaffs_ReadDataFromFile(yaffs_Object
+@@ -4600,27 +4665,26 @@ int yaffs_ReadDataFromFile(yaffs_Object 
        dev = in->myDev;
  
        while (n > 0) {
                        if (dev->nShortOpCaches > 0) {
  
                                /* If we can't find the data in the cache, then load it up. */
-@@ -4641,14 +4705,9 @@ int yaffs_ReadDataFromFile(yaffs_Object
+@@ -4641,14 +4705,9 @@ int yaffs_ReadDataFromFile(yaffs_Object 
  
                                cache->locked = 1;
  
                                cache->locked = 0;
                        } else {
                                /* Read into the local buffer then copy..*/
-@@ -4657,41 +4716,19 @@ int yaffs_ReadDataFromFile(yaffs_Object
+@@ -4657,41 +4716,19 @@ int yaffs_ReadDataFromFile(yaffs_Object 
                                    yaffs_GetTempBuffer(dev, __LINE__);
                                yaffs_ReadChunkDataFromObject(in, chunk,
                                                              localBuffer);
                }
  
                n -= nToCopy;
-@@ -4704,28 +4741,37 @@ int yaffs_ReadDataFromFile(yaffs_Object
+@@ -4704,28 +4741,37 @@ int yaffs_ReadDataFromFile(yaffs_Object 
        return nDone;
  }
  
        int newFullChunks;
  
        yaffs_Device *dev = in->myDev;
-@@ -4955,13 +4981,11 @@ int yaffs_ResizeFile(yaffs_Object * in,
+@@ -4955,13 +4981,11 @@ int yaffs_ResizeFile(yaffs_Object * in, 
  
        yaffs_CheckGarbageCollection(dev);
  
  
        if (newSize < oldFileSize) {
  
-@@ -4994,21 +5018,20 @@ int yaffs_ResizeFile(yaffs_Object * in,
+@@ -4994,21 +5018,20 @@ int yaffs_ResizeFile(yaffs_Object * in, 
        }
  
  
  {
        obj = yaffs_GetEquivalentObject(obj);
  
-@@ -5024,7 +5047,7 @@ loff_t yaffs_GetFileSize(yaffs_Object *
+@@ -5024,7 +5047,7 @@ loff_t yaffs_GetFileSize(yaffs_Object * 
  
  
  
  {
        int init_failed = 0;
        unsigned x;
-@@ -7040,6 +7126,8 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7040,6 +7126,8 @@ int yaffs_GutsInitialise(yaffs_Device * 
        dev->chunkOffset = 0;
        dev->nFreeChunks = 0;
  
        if (dev->startBlock == 0) {
                dev->internalStartBlock = dev->startBlock + 1;
                dev->internalEndBlock = dev->endBlock + 1;
-@@ -7049,18 +7137,18 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7049,18 +7137,18 @@ int yaffs_GutsInitialise(yaffs_Device * 
  
        /* Check geometry parameters. */
  
                return YAFFS_FAIL;
        }
  
-@@ -7070,6 +7158,12 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7070,6 +7158,12 @@ int yaffs_GutsInitialise(yaffs_Device * 
                return YAFFS_FAIL;
        }
  
        /* Got the right mix of functions? */
        if (!yaffs_CheckDevFunctions(dev)) {
                /* Function missing */
-@@ -7097,31 +7191,18 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7097,31 +7191,18 @@ int yaffs_GutsInitialise(yaffs_Device * 
  
        dev->isMounted = 1;
  
  
        /*
         * Calculate chunkGroupBits.
-@@ -7133,16 +7214,15 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7133,16 +7214,15 @@ int yaffs_GutsInitialise(yaffs_Device * 
        bits = ShiftsGE(x);
  
        /* Set up tnode width if wide tnodes are enabled. */
                dev->tnodeWidth = 16;
  
        dev->tnodeMask = (1<<dev->tnodeWidth)-1;
-@@ -7193,7 +7273,7 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7193,7 +7273,7 @@ int yaffs_GutsInitialise(yaffs_Device * 
        dev->hasPendingPrioritisedGCs = 1; /* Assume the worst for now, will get fixed on first GC */
  
        /* Initialise temporary buffers and caches. */
                init_failed = 1;
  
        dev->srCache = NULL;
-@@ -7203,25 +7283,26 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7203,25 +7283,26 @@ int yaffs_GutsInitialise(yaffs_Device * 
        if (!init_failed &&
            dev->nShortOpCaches > 0) {
                int i;
                        init_failed = 1;
  
                dev->srLastUse = 0;
-@@ -7229,29 +7310,30 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7229,29 +7310,30 @@ int yaffs_GutsInitialise(yaffs_Device * 
  
        dev->cacheHits = 0;
  
                                T(YAFFS_TRACE_ALWAYS,
                                  (TSTR("yaffs: restored from checkpoint" TENDSTR)));
                        } else {
-@@ -7273,24 +7355,25 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7273,24 +7355,25 @@ int yaffs_GutsInitialise(yaffs_Device * 
                                dev->nBackgroundDeletions = 0;
                                dev->oldestDirtySequence = 0;
  
                /* Clean up the mess */
                T(YAFFS_TRACE_TRACING,
                  (TSTR("yaffs: yaffs_GutsInitialise() aborted.\n" TENDSTR)));
-@@ -7318,7 +7401,7 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7318,7 +7401,7 @@ int yaffs_GutsInitialise(yaffs_Device * 
  
  }
  
  {
        if (etags) {
                memset(etags, 0, sizeof(*etags));
-@@ -169,9 +169,9 @@ static int rettags(yaffs_ExtendedTags *
+@@ -169,9 +169,9 @@ static int rettags(yaffs_ExtendedTags * 
   * Returns YAFFS_OK or YAFFS_FAIL.
   */
  int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device *dev,
 +                      yaffs_UnpackTags2(tags, &pt);
 +              }
 +      }
-+
+-      if(tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR)
+-              tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
 +      if (localData)
 +              yaffs_ReleaseTempBuffer(dev, data, __LINE__);
  
--      if(tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR)
 +      if (tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR)
-               tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
--
++              tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
        if (retval == 0)
                return YAFFS_OK;
        else
index db889badcd78d9a45fd208e97df00c623adafa89..a0c532a959fd74b4b4b2d7a6084d8a26b9017011 100644 (file)
  chunk/page state.  This byte is zeroed when the page is discarded.
  Choose this option if you have existing on-NAND data in this format
  that you need to continue to support.  New data written also uses the
-@@ -57,7 +78,7 @@ adjusted to use the older-style format.
+@@ -57,7 +78,7 @@ adjusted to use the older-style format. 
  MTD versions in yaffs_mtdif1.c.
  */
  /* Default: Not selected */
                        yaffs_ECCOther *read_ecc,
                        const yaffs_ECCOther *test_ecc)
  {
-@@ -304,7 +301,7 @@ int yaffs_ECCCorrectOther(unsigned char
+@@ -304,7 +301,7 @@ int yaffs_ECCCorrectOther(unsigned char 
                if (cDelta & 0x02)
                        bit |= 0x01;
  
                        return -1;
  
                data[lDelta] ^= (1 << bit);
-@@ -312,8 +309,8 @@ int yaffs_ECCCorrectOther(unsigned char
+@@ -312,8 +309,8 @@ int yaffs_ECCCorrectOther(unsigned char 
                return 1; /* corrected */
        }
  
index e40053170c89c6f7569699eff156072b022a8721..ad44715411263c97fc2b187c8fffd5e1dba7adae 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/hostap/hostap_ap.c
 +++ b/drivers/net/wireless/hostap/hostap_ap.c
-@@ -2335,13 +2335,13 @@ int prism2_ap_get_sta_qual(local_info_t
+@@ -2335,13 +2335,13 @@ int prism2_ap_get_sta_qual(local_info_t 
                addr[count].sa_family = ARPHRD_ETHER;
                memcpy(addr[count].sa_data, sta->addr, ETH_ALEN);
                if (sta->last_rx_silence == 0)
index e3ecbbeaa07a8509c5d36b56d5b97ad0ea548e51..ed03aa94397cb2c5cf145b75cb6a5c11bb875014 100644 (file)
@@ -24,7 +24,7 @@
   * All of these routines try to estimate how many bits of randomness a
   * particular randomness source.  They do this by keeping track of the
   * first and second order deltas of the event timings.
-@@ -715,6 +725,61 @@ void add_disk_randomness(struct gendisk
+@@ -715,6 +725,61 @@ void add_disk_randomness(struct gendisk 
  }
  #endif
  
index e1fcf448c1ba18f6f328de59bacd8095207207b3..86da2f0adbfc7f67014f592023a14f7cf875ad26 100644 (file)
@@ -23,7 +23,7 @@ Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
 +EXPORT_SYMBOL(dma_set_coherent_mask);
 --- a/arch/arm/mach-ixp4xx/common-pci.c
 +++ b/arch/arm/mach-ixp4xx/common-pci.c
-@@ -513,4 +513,4 @@ int dma_set_coherent_mask(struct device
+@@ -513,4 +513,4 @@ int dma_set_coherent_mask(struct device 
  
  EXPORT_SYMBOL(ixp4xx_pci_read);
  EXPORT_SYMBOL(ixp4xx_pci_write);
index 77161f684d0fbf11bd95c43444fd7ff7d6716b99..e63d733be9137f603390ecdf4ecd997c3f104047 100644 (file)
@@ -1,6 +1,6 @@
 --- a/scripts/Makefile.lib
 +++ b/scripts/Makefile.lib
-@@ -238,7 +238,7 @@ cmd_bzip2 = (cat $(filter-out FORCE,$^)
+@@ -238,7 +238,7 @@ cmd_bzip2 = (cat $(filter-out FORCE,$^) 
  
  quiet_cmd_lzma = LZMA    $@
  cmd_lzma = (cat $(filter-out FORCE,$^) | \
index 38ba76df4616b55cbb296f59b108771370fa837f..e1981ddd25718b7c8bef0238361e5b2a2179db3a 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/mtd/chips/cfi_cmdset_0002.c
 +++ b/drivers/mtd/chips/cfi_cmdset_0002.c
-@@ -446,9 +446,9 @@ struct mtd_info *cfi_cmdset_0002(struct
+@@ -446,9 +446,9 @@ struct mtd_info *cfi_cmdset_0002(struct 
  
                        /*
                         * Valid primary extension versions are: 1.0, 1.1, 1.2, 1.3, 1.4
index 729934f283fbe01028e2921157b235cbcfdd1e7a..ab270ff97cbccec1883a5678e0c4a84c0aaea32b 100644 (file)
  
  unsigned int vced_count, vcei_count;
  
-@@ -31,8 +32,12 @@ static int show_cpuinfo(struct seq_file
+@@ -31,8 +32,12 @@ static int show_cpuinfo(struct seq_file 
        /*
         * For the first processor also print the system type
         */
index 835f25a17915225cc6a40c343fdb8a6e6e2a51af..1223fb456d6e66e20c51a8b40a8758da430fc0cc 100644 (file)
@@ -63,7 +63,7 @@
  htc_excalibur_s620    MACH_HTC_EXCALIBUR_S620 HTC_EXCALIBUR_S620      2391
  htc_opal              MACH_HTC_OPAL           HTC_OPAL                2392
  touchbook             MACH_TOUCHBOOK          TOUCHBOOK               2393
-@@ -2446,7 +2446,7 @@ siogentoo1               MACH_SIOGENTOO1         SIOGENTOO1
+@@ -2446,7 +2446,7 @@ siogentoo1               MACH_SIOGENTOO1         SIOGENTOO1      
  siogentoo2            MACH_SIOGENTOO2         SIOGENTOO2              2459
  sm3k                  MACH_SM3K               SM3K                    2460
  acer_tempo_f900               MACH_ACER_TEMPO_F900    ACER_TEMPO_F900         2461
index a0483957cb3a5cb7e1501161248cc66b1226a3ad..e9bb1210773824518fe8db2983d271f926911649 100644 (file)
        part->name = dev->mtd.name;
 --- a/drivers/mtd/mtdchar.c
 +++ b/drivers/mtd/mtdchar.c
-@@ -841,6 +841,13 @@ static int mtd_ioctl(struct file *file,
+@@ -841,6 +841,13 @@ static int mtd_ioctl(struct file *file, 
                file->f_pos = 0;
                break;
        }
index cb9f7bfaca920368df9f974671780d0df403cd4b..9b8cc815a845b854f657aa0b3d8797d0eb7f63f5 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/mtd/chips/cfi_cmdset_0002.c
 +++ b/drivers/mtd/chips/cfi_cmdset_0002.c
-@@ -392,9 +392,35 @@ static struct cfi_fixup fixup_table[] =
+@@ -392,9 +392,35 @@ static struct cfi_fixup fixup_table[] = 
  static void cfi_fixup_major_minor(struct cfi_private *cfi,
                                  struct cfi_pri_amdstd *extp)
  {
index 88b656b5e4d7a89291d56e6c9f77c8d6c66c4f17..58732b8ffd1321aa070ae7ec9faf12191f8f2a0a 100644 (file)
@@ -30,7 +30,7 @@
        depends on NETFILTER_ADVANCED
 --- a/net/netfilter/Makefile
 +++ b/net/netfilter/Makefile
-@@ -95,6 +95,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_RECENT)
+@@ -95,6 +95,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_RECENT) 
  obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o
  obj-$(CONFIG_NETFILTER_XT_MATCH_SOCKET) += xt_socket.o
  obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o
diff --git a/target/linux/generic/patches-2.6.37/150-netfilter_imq.patch b/target/linux/generic/patches-2.6.37/150-netfilter_imq.patch
deleted file mode 100644 (file)
index b715126..0000000
+++ /dev/null
@@ -1,1342 +0,0 @@
---- /dev/null
-+++ b/drivers/net/imq.c
-@@ -0,0 +1,638 @@
-+/*
-+ *             Pseudo-driver for the intermediate queue device.
-+ *
-+ *             This program is free software; you can redistribute it and/or
-+ *             modify it under the terms of the GNU General Public License
-+ *             as published by the Free Software Foundation; either version
-+ *             2 of the License, or (at your option) any later version.
-+ *
-+ * Authors:    Patrick McHardy, <kaber@trash.net>
-+ *
-+ *            The first version was written by Martin Devera, <devik@cdi.cz>
-+ *
-+ * Credits:    Jan Rafaj <imq2t@cedric.vabo.cz>
-+ *              - Update patch to 2.4.21
-+ *             Sebastian Strollo <sstrollo@nortelnetworks.com>
-+ *              - Fix "Dead-loop on netdevice imq"-issue
-+ *             Marcel Sebek <sebek64@post.cz>
-+ *              - Update to 2.6.2-rc1
-+ *
-+ *           After some time of inactivity there is a group taking care
-+ *           of IMQ again: http://www.linuximq.net
-+ *
-+ *
-+ *           2004/06/30 - New version of IMQ patch to kernels <=2.6.7
-+ *             including the following changes:
-+ *
-+ *           - Correction of ipv6 support "+"s issue (Hasso Tepper)
-+ *           - Correction of imq_init_devs() issue that resulted in
-+ *           kernel OOPS unloading IMQ as module (Norbert Buchmuller)
-+ *           - Addition of functionality to choose number of IMQ devices
-+ *           during kernel config (Andre Correa)
-+ *           - Addition of functionality to choose how IMQ hooks on
-+ *           PRE and POSTROUTING (after or before NAT) (Andre Correa)
-+ *           - Cosmetic corrections (Norbert Buchmuller) (Andre Correa)
-+ *
-+ *
-+ *             2005/12/16 - IMQ versions between 2.6.7 and 2.6.13 were
-+ *             released with almost no problems. 2.6.14-x was released
-+ *             with some important changes: nfcache was removed; After
-+ *             some weeks of trouble we figured out that some IMQ fields
-+ *             in skb were missing in skbuff.c - skb_clone and copy_skb_header.
-+ *             These functions are correctly patched by this new patch version.
-+ *
-+ *             Thanks for all who helped to figure out all the problems with
-+ *             2.6.14.x: Patrick McHardy, Rune Kock, VeNoMouS, Max CtRiX,
-+ *             Kevin Shanahan, Richard Lucassen, Valery Dachev (hopefully
-+ *             I didn't forget anybody). I apologize again for my lack of time.
-+ *
-+ *
-+ *             2008/06/17 - 2.6.25 - Changed imq.c to use qdisc_run() instead 
-+ *             of qdisc_restart() and moved qdisc_run() to tasklet to avoid
-+ *             recursive locking. New initialization routines to fix 'rmmod' not
-+ *             working anymore. Used code from ifb.c. (Jussi Kivilinna)
-+ *
-+ *             2008/08/06 - 2.6.26 - (JK)
-+ *              - Replaced tasklet with 'netif_schedule()'.
-+ *              - Cleaned up and added comments for imq_nf_queue().
-+ *
-+ *             2009/04/12
-+ *              - Add skb_save_cb/skb_restore_cb helper functions for backuping
-+ *                control buffer. This is needed because qdisc-layer on kernels
-+ *                2.6.27 and newer overwrite control buffer. (Jussi Kivilinna)
-+ *              - Add better locking for IMQ device. Hopefully this will solve
-+ *                SMP issues. (Jussi Kivilinna)
-+ *              - Port to 2.6.27
-+ *              - Port to 2.6.28
-+ *              - Port to 2.6.29 + fix rmmod not working
-+ *
-+ *             2009/04/20 - (Jussi Kivilinna)
-+ *              - Use netdevice feature flags to avoid extra packet handling
-+ *                by core networking layer and possibly increase performance.
-+ *
-+ *             2009/09/26 - (Jussi Kivilinna)
-+ *              - Add imq_nf_reinject_lockless to fix deadlock with
-+ *                imq_nf_queue/imq_nf_reinject.
-+ *
-+ *             2009/12/08 - (Jussi Kivilinna)
-+ *              - Port to 2.6.32
-+ *              - Add check for skb->nf_queue_entry==NULL in imq_dev_xmit()
-+ *              - Also add better error checking for skb->nf_queue_entry usage
-+ *
-+ *             2010/02/25 - (Jussi Kivilinna)
-+ *              - Port to 2.6.33
-+ *
-+ *             2010/08/12 - (Jussi Kivilinna)
-+ *              - Port to 2.6.35
-+ *
-+ *           Also, many thanks to pablo Sebastian Greco for making the initial
-+ *           patch and to those who helped the testing.
-+ *
-+ *             More info at: http://www.linuximq.net/ (Andre Correa)
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/moduleparam.h>
-+#include <linux/list.h>
-+#include <linux/skbuff.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/rtnetlink.h>
-+#include <linux/if_arp.h>
-+#include <linux/netfilter.h>
-+#include <linux/netfilter_ipv4.h>
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+      #include <linux/netfilter_ipv6.h>
-+#endif
-+#include <linux/imq.h>
-+#include <net/pkt_sched.h>
-+#include <net/netfilter/nf_queue.h>
-+
-+static nf_hookfn imq_nf_hook;
-+
-+static struct nf_hook_ops imq_ingress_ipv4 = {
-+      .hook           = imq_nf_hook,
-+      .owner          = THIS_MODULE,
-+      .pf             = PF_INET,
-+      .hooknum        = NF_INET_PRE_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+      .priority       = NF_IP_PRI_MANGLE + 1
-+#else
-+      .priority       = NF_IP_PRI_NAT_DST + 1
-+#endif
-+};
-+
-+static struct nf_hook_ops imq_egress_ipv4 = {
-+      .hook           = imq_nf_hook,
-+      .owner          = THIS_MODULE,
-+      .pf             = PF_INET,
-+      .hooknum        = NF_INET_POST_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
-+      .priority       = NF_IP_PRI_LAST
-+#else
-+      .priority       = NF_IP_PRI_NAT_SRC - 1
-+#endif
-+};
-+
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+static struct nf_hook_ops imq_ingress_ipv6 = {
-+      .hook           = imq_nf_hook,
-+      .owner          = THIS_MODULE,
-+      .pf             = PF_INET6,
-+      .hooknum        = NF_INET_PRE_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+      .priority       = NF_IP6_PRI_MANGLE + 1
-+#else
-+      .priority       = NF_IP6_PRI_NAT_DST + 1
-+#endif
-+};
-+
-+static struct nf_hook_ops imq_egress_ipv6 = {
-+      .hook           = imq_nf_hook,
-+      .owner          = THIS_MODULE,
-+      .pf             = PF_INET6,
-+      .hooknum        = NF_INET_POST_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
-+      .priority       = NF_IP6_PRI_LAST
-+#else
-+      .priority       = NF_IP6_PRI_NAT_SRC - 1
-+#endif
-+};
-+#endif
-+
-+#if defined(CONFIG_IMQ_NUM_DEVS)
-+static unsigned int numdevs = CONFIG_IMQ_NUM_DEVS;
-+#else
-+static unsigned int numdevs = IMQ_MAX_DEVS;
-+#endif
-+
-+static DEFINE_SPINLOCK(imq_nf_queue_lock);
-+
-+static struct net_device *imq_devs_cache[IMQ_MAX_DEVS];
-+
-+
-+static struct net_device_stats *imq_get_stats(struct net_device *dev)
-+{
-+      return &dev->stats;
-+}
-+
-+/* called for packets kfree'd in qdiscs at places other than enqueue */
-+static void imq_skb_destructor(struct sk_buff *skb)
-+{
-+      struct nf_queue_entry *entry = skb->nf_queue_entry;
-+
-+      skb->nf_queue_entry = NULL;
-+
-+      if (entry) {
-+              nf_queue_entry_release_refs(entry);
-+              kfree(entry);
-+      }
-+
-+      skb_restore_cb(skb); /* kfree backup */
-+}
-+
-+/* locking not needed when called from imq_nf_queue */
-+static void imq_nf_reinject_lockless(struct nf_queue_entry *entry,
-+                                              unsigned int verdict)
-+{
-+      int status;
-+
-+      if (!entry->next_outfn) {
-+              nf_reinject(entry, verdict);
-+              return;
-+      }
-+
-+      status = entry->next_outfn(entry, entry->next_queuenum);
-+      if (status < 0) {
-+              nf_queue_entry_release_refs(entry);
-+              kfree_skb(entry->skb);
-+              kfree(entry);
-+      }
-+}
-+
-+static void imq_nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
-+{
-+      int status;
-+
-+      if (!entry->next_outfn) {
-+              spin_lock_bh(&imq_nf_queue_lock);
-+              nf_reinject(entry, verdict);
-+              spin_unlock_bh(&imq_nf_queue_lock);
-+              return;
-+      }
-+
-+      rcu_read_lock();
-+      local_bh_disable();
-+      status = entry->next_outfn(entry, entry->next_queuenum);
-+      local_bh_enable();
-+      if (status < 0) {
-+              nf_queue_entry_release_refs(entry);
-+              kfree_skb(entry->skb);
-+              kfree(entry);
-+      }
-+
-+      rcu_read_unlock();
-+}
-+
-+static netdev_tx_t imq_dev_xmit(struct sk_buff *skb, struct net_device *dev)
-+{
-+      struct nf_queue_entry *entry = skb->nf_queue_entry;
-+
-+      skb->nf_queue_entry = NULL;
-+      dev->trans_start = jiffies;
-+
-+      dev->stats.tx_bytes += skb->len;
-+      dev->stats.tx_packets++;
-+
-+      if (entry == NULL) {
-+              /* We don't know what is going on here.. packet is queued for
-+               * imq device, but (probably) not by us.
-+               *
-+               * If this packet was not send here by imq_nf_queue(), then
-+               * skb_save_cb() was not used and skb_free() should not show:
-+               *   WARNING: IMQ: kfree_skb: skb->cb_next:..
-+               * and/or
-+               *   WARNING: IMQ: kfree_skb: skb->nf_queue_entry...
-+               *
-+               * However if this message is shown, then IMQ is somehow broken
-+               * and you should report this to linuximq.net.
-+               */
-+
-+              /* imq_dev_xmit is black hole that eats all packets, report that
-+               * we eat this packet happily and increase dropped counters.
-+               */
-+
-+              dev->stats.tx_dropped++;
-+              dev_kfree_skb(skb);
-+
-+              return NETDEV_TX_OK;
-+      }
-+
-+      skb_restore_cb(skb); /* restore skb->cb */
-+
-+      skb->imq_flags = 0;
-+      skb->destructor = NULL;
-+
-+      imq_nf_reinject(entry, NF_ACCEPT);
-+
-+      return NETDEV_TX_OK;
-+}
-+
-+static int imq_nf_queue(struct nf_queue_entry *entry, unsigned queue_num)
-+{
-+      struct net_device *dev;
-+      struct sk_buff *skb_orig, *skb, *skb_shared;
-+      struct Qdisc *q;
-+      struct netdev_queue *txq;
-+      int users, index;
-+      int retval = -EINVAL;
-+
-+      index = entry->skb->imq_flags & IMQ_F_IFMASK;
-+      if (unlikely(index > numdevs - 1)) {
-+              if (net_ratelimit())
-+                      printk(KERN_WARNING
-+                             "IMQ: invalid device specified, highest is %u\n",
-+                             numdevs - 1);
-+              retval = -EINVAL;
-+              goto out;
-+      }
-+
-+      /* check for imq device by index from cache */
-+      dev = imq_devs_cache[index];
-+      if (unlikely(!dev)) {
-+              char buf[8];
-+
-+              /* get device by name and cache result */
-+              snprintf(buf, sizeof(buf), "imq%d", index);
-+              dev = dev_get_by_name(&init_net, buf);
-+              if (!dev) {
-+                      /* not found ?!*/
-+                      BUG();
-+                      retval = -ENODEV;
-+                      goto out;
-+              }
-+
-+              imq_devs_cache[index] = dev;
-+              dev_put(dev);
-+      }
-+
-+      if (unlikely(!(dev->flags & IFF_UP))) {
-+              entry->skb->imq_flags = 0;
-+              imq_nf_reinject_lockless(entry, NF_ACCEPT);
-+              retval = 0;
-+              goto out;
-+      }
-+      dev->last_rx = jiffies;
-+
-+      skb = entry->skb;
-+      skb_orig = NULL;
-+
-+      /* skb has owner? => make clone */
-+      if (unlikely(skb->destructor)) {
-+              skb_orig = skb;
-+              skb = skb_clone(skb, GFP_ATOMIC);
-+              if (!skb) {
-+                      retval = -ENOMEM;
-+                      goto out;
-+              }
-+              entry->skb = skb;
-+      }
-+
-+      skb->nf_queue_entry = entry;
-+
-+      dev->stats.rx_bytes += skb->len;
-+      dev->stats.rx_packets++;
-+
-+      txq = dev_pick_tx(dev, skb);
-+
-+      q = rcu_dereference(txq->qdisc);
-+      if (unlikely(!q->enqueue))
-+              goto packet_not_eaten_by_imq_dev;
-+
-+      spin_lock_bh(qdisc_lock(q));
-+
-+      users = atomic_read(&skb->users);
-+
-+      skb_shared = skb_get(skb); /* increase reference count by one */
-+      skb_save_cb(skb_shared); /* backup skb->cb, as qdisc layer will
-+                                      overwrite it */
-+      qdisc_enqueue_root(skb_shared, q); /* might kfree_skb */
-+
-+      if (likely(atomic_read(&skb_shared->users) == users + 1)) {
-+              kfree_skb(skb_shared); /* decrease reference count by one */
-+
-+              skb->destructor = &imq_skb_destructor;
-+
-+              /* cloned? */
-+              if (skb_orig)
-+                      kfree_skb(skb_orig); /* free original */
-+
-+              spin_unlock_bh(qdisc_lock(q));
-+
-+              /* schedule qdisc dequeue */
-+              __netif_schedule(q);
-+
-+              retval = 0;
-+              goto out;
-+      } else {
-+              skb_restore_cb(skb_shared); /* restore skb->cb */
-+              skb->nf_queue_entry = NULL;
-+              /* qdisc dropped packet and decreased skb reference count of
-+               * skb, so we don't really want to and try refree as that would
-+               * actually destroy the skb. */
-+              spin_unlock_bh(qdisc_lock(q));
-+              goto packet_not_eaten_by_imq_dev;
-+      }
-+
-+packet_not_eaten_by_imq_dev:
-+      /* cloned? restore original */
-+      if (skb_orig) {
-+              kfree_skb(skb);
-+              entry->skb = skb_orig;
-+      }
-+      retval = -1;
-+out:
-+      return retval;
-+}
-+
-+static struct nf_queue_handler nfqh = {
-+      .name  = "imq",
-+      .outfn = imq_nf_queue,
-+};
-+
-+static unsigned int imq_nf_hook(unsigned int hook, struct sk_buff *pskb,
-+                              const struct net_device *indev,
-+                              const struct net_device *outdev,
-+                              int (*okfn)(struct sk_buff *))
-+{
-+      if (pskb->imq_flags & IMQ_F_ENQUEUE)
-+              return NF_QUEUE;
-+
-+      return NF_ACCEPT;
-+}
-+
-+static int imq_close(struct net_device *dev)
-+{
-+      netif_stop_queue(dev);
-+      return 0;
-+}
-+
-+static int imq_open(struct net_device *dev)
-+{
-+      netif_start_queue(dev);
-+      return 0;
-+}
-+
-+static const struct net_device_ops imq_netdev_ops = {
-+      .ndo_open               = imq_open,
-+      .ndo_stop               = imq_close,
-+      .ndo_start_xmit         = imq_dev_xmit,
-+      .ndo_get_stats          = imq_get_stats,
-+};
-+
-+static void imq_setup(struct net_device *dev)
-+{
-+      dev->netdev_ops         = &imq_netdev_ops;
-+      dev->type               = ARPHRD_VOID;
-+      dev->mtu                = 16000;
-+      dev->tx_queue_len       = 11000;
-+      dev->flags              = IFF_NOARP;
-+      dev->features           = NETIF_F_SG | NETIF_F_FRAGLIST |
-+                                NETIF_F_GSO | NETIF_F_HW_CSUM |
-+                                NETIF_F_HIGHDMA;
-+      dev->priv_flags         &= ~IFF_XMIT_DST_RELEASE;
-+}
-+
-+static int imq_validate(struct nlattr *tb[], struct nlattr *data[])
-+{
-+      int ret = 0;
-+
-+      if (tb[IFLA_ADDRESS]) {
-+              if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) {
-+                      ret = -EINVAL;
-+                      goto end;
-+              }
-+              if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) {
-+                      ret = -EADDRNOTAVAIL;
-+                      goto end;
-+              }
-+      }
-+      return 0;
-+end:
-+      printk(KERN_WARNING "IMQ: imq_validate failed (%d)\n", ret);
-+      return ret;
-+}
-+
-+static struct rtnl_link_ops imq_link_ops __read_mostly = {
-+      .kind           = "imq",
-+      .priv_size      = 0,
-+      .setup          = imq_setup,
-+      .validate       = imq_validate,
-+};
-+
-+static int __init imq_init_hooks(void)
-+{
-+      int err;
-+
-+      nf_register_queue_imq_handler(&nfqh);
-+
-+      err = nf_register_hook(&imq_ingress_ipv4);
-+      if (err)
-+              goto err1;
-+
-+      err = nf_register_hook(&imq_egress_ipv4);
-+      if (err)
-+              goto err2;
-+
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+      err = nf_register_hook(&imq_ingress_ipv6);
-+      if (err)
-+              goto err3;
-+
-+      err = nf_register_hook(&imq_egress_ipv6);
-+      if (err)
-+              goto err4;
-+#endif
-+
-+      return 0;
-+
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+err4:
-+      nf_unregister_hook(&imq_ingress_ipv6);
-+err3:
-+      nf_unregister_hook(&imq_egress_ipv4);
-+#endif
-+err2:
-+      nf_unregister_hook(&imq_ingress_ipv4);
-+err1:
-+      nf_unregister_queue_imq_handler();
-+      return err;
-+}
-+
-+static int __init imq_init_one(int index)
-+{
-+      struct net_device *dev;
-+      int ret;
-+
-+      dev = alloc_netdev(0, "imq%d", imq_setup);
-+      if (!dev)
-+              return -ENOMEM;
-+
-+      ret = dev_alloc_name(dev, dev->name);
-+      if (ret < 0)
-+              goto fail;
-+
-+      dev->rtnl_link_ops = &imq_link_ops;
-+      ret = register_netdevice(dev);
-+      if (ret < 0)
-+              goto fail;
-+
-+      return 0;
-+fail:
-+      free_netdev(dev);
-+      return ret;
-+}
-+
-+static int __init imq_init_devs(void)
-+{
-+      int err, i;
-+
-+      if (numdevs < 1 || numdevs > IMQ_MAX_DEVS) {
-+              printk(KERN_ERR "IMQ: numdevs has to be betweed 1 and %u\n",
-+                     IMQ_MAX_DEVS);
-+              return -EINVAL;
-+      }
-+
-+      rtnl_lock();
-+      err = __rtnl_link_register(&imq_link_ops);
-+
-+      for (i = 0; i < numdevs && !err; i++)
-+              err = imq_init_one(i);
-+
-+      if (err) {
-+              __rtnl_link_unregister(&imq_link_ops);
-+              memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
-+      }
-+      rtnl_unlock();
-+
-+      return err;
-+}
-+
-+static int __init imq_init_module(void)
-+{
-+      int err;
-+
-+#if defined(CONFIG_IMQ_NUM_DEVS)
-+      BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS > 16);
-+      BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS < 2);
-+      BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS - 1 > IMQ_F_IFMASK);
-+#endif
-+
-+      err = imq_init_devs();
-+      if (err) {
-+              printk(KERN_ERR "IMQ: Error trying imq_init_devs(net)\n");
-+              return err;
-+      }
-+
-+      err = imq_init_hooks();
-+      if (err) {
-+              printk(KERN_ERR "IMQ: Error trying imq_init_hooks()\n");
-+              rtnl_link_unregister(&imq_link_ops);
-+              memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
-+              return err;
-+      }
-+
-+      printk(KERN_INFO "IMQ driver loaded successfully.\n");
-+
-+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+      printk(KERN_INFO "\tHooking IMQ before NAT on PREROUTING.\n");
-+#else
-+      printk(KERN_INFO "\tHooking IMQ after NAT on PREROUTING.\n");
-+#endif
-+#if defined(CONFIG_IMQ_BEHAVIOR_AB) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+      printk(KERN_INFO "\tHooking IMQ before NAT on POSTROUTING.\n");
-+#else
-+      printk(KERN_INFO "\tHooking IMQ after NAT on POSTROUTING.\n");
-+#endif
-+
-+      return 0;
-+}
-+
-+static void __exit imq_unhook(void)
-+{
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+      nf_unregister_hook(&imq_ingress_ipv6);
-+      nf_unregister_hook(&imq_egress_ipv6);
-+#endif
-+      nf_unregister_hook(&imq_ingress_ipv4);
-+      nf_unregister_hook(&imq_egress_ipv4);
-+
-+      nf_unregister_queue_imq_handler();
-+}
-+
-+static void __exit imq_cleanup_devs(void)
-+{
-+      rtnl_link_unregister(&imq_link_ops);
-+      memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
-+}
-+
-+static void __exit imq_exit_module(void)
-+{
-+      imq_unhook();
-+      imq_cleanup_devs();
-+      printk(KERN_INFO "IMQ driver unloaded successfully.\n");
-+}
-+
-+module_init(imq_init_module);
-+module_exit(imq_exit_module);
-+
-+module_param(numdevs, int, 0);
-+MODULE_PARM_DESC(numdevs, "number of IMQ devices (how many imq* devices will "
-+                      "be created)");
-+MODULE_AUTHOR("http://www.linuximq.net");
-+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See "
-+                      "http://www.linuximq.net/ for more information.");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS_RTNL_LINK("imq");
-+
---- a/drivers/net/Kconfig
-+++ b/drivers/net/Kconfig
-@@ -124,6 +124,129 @@ config EQUALIZER
-         To compile this driver as a module, choose M here: the module
-         will be called eql.  If unsure, say N.
-+config IMQ
-+      tristate "IMQ (intermediate queueing device) support"
-+      depends on NETDEVICES && NETFILTER
-+      ---help---
-+        The IMQ device(s) is used as placeholder for QoS queueing
-+        disciplines. Every packet entering/leaving the IP stack can be
-+        directed through the IMQ device where it's enqueued/dequeued to the
-+        attached qdisc. This allows you to treat network devices as classes
-+        and distribute bandwidth among them. Iptables is used to specify
-+        through which IMQ device, if any, packets travel.
-+
-+        More information at: http://www.linuximq.net/
-+
-+        To compile this driver as a module, choose M here: the module
-+        will be called imq.  If unsure, say N.
-+
-+choice
-+      prompt "IMQ behavior (PRE/POSTROUTING)"
-+      depends on IMQ
-+      default IMQ_BEHAVIOR_AB
-+      help
-+
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              IMQ can work in any of the following ways:
-+
-+                  PREROUTING   |      POSTROUTING
-+              -----------------|-------------------
-+              #1  After NAT    |      After NAT
-+              #2  After NAT    |      Before NAT
-+              #3  Before NAT   |      After NAT
-+              #4  Before NAT   |      Before NAT
-+
-+              The default behavior is to hook before NAT on PREROUTING
-+              and after NAT on POSTROUTING (#3).
-+
-+              This settings are specially usefull when trying to use IMQ
-+              to shape NATed clients.
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_AA
-+      bool "IMQ AA"
-+      help
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              Choosing this option will make IMQ hook like this:
-+
-+              PREROUTING:   After NAT
-+              POSTROUTING:  After NAT
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_AB
-+      bool "IMQ AB"
-+      help
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              Choosing this option will make IMQ hook like this:
-+
-+              PREROUTING:   After NAT
-+              POSTROUTING:  Before NAT
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_BA
-+      bool "IMQ BA"
-+      help
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              Choosing this option will make IMQ hook like this:
-+
-+              PREROUTING:   Before NAT
-+              POSTROUTING:  After NAT
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_BB
-+      bool "IMQ BB"
-+      help
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              Choosing this option will make IMQ hook like this:
-+
-+              PREROUTING:   Before NAT
-+              POSTROUTING:  Before NAT
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+endchoice
-+
-+config IMQ_NUM_DEVS
-+
-+      int "Number of IMQ devices"
-+      range 2 16
-+      depends on IMQ
-+      default "16"
-+      help
-+
-+              This settings defines how many IMQ devices will be
-+              created.
-+
-+              The default value is 16.
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
- config TUN
-       tristate "Universal TUN/TAP device driver support"
-       select CRC32
---- a/drivers/net/Makefile
-+++ b/drivers/net/Makefile
-@@ -173,6 +173,7 @@ obj-$(CONFIG_SLHC) += slhc.o
- obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o
- obj-$(CONFIG_DUMMY) += dummy.o
-+obj-$(CONFIG_IMQ) += imq.o
- obj-$(CONFIG_IFB) += ifb.o
- obj-$(CONFIG_MACVLAN) += macvlan.o
- obj-$(CONFIG_MACVTAP) += macvtap.o
---- /dev/null
-+++ b/include/linux/imq.h
-@@ -0,0 +1,13 @@
-+#ifndef _IMQ_H
-+#define _IMQ_H
-+
-+/* IFMASK (16 device indexes, 0 to 15) and flag(s) fit in 5 bits */
-+#define IMQ_F_BITS    5
-+
-+#define IMQ_F_IFMASK  0x0f
-+#define IMQ_F_ENQUEUE 0x10
-+
-+#define IMQ_MAX_DEVS  (IMQ_F_IFMASK + 1)
-+
-+#endif /* _IMQ_H */
-+
---- a/include/linux/netdevice.h
-+++ b/include/linux/netdevice.h
-@@ -1323,6 +1323,7 @@ extern int               dev_alloc_name(struct net_de
- extern int            dev_open(struct net_device *dev);
- extern int            dev_close(struct net_device *dev);
- extern void           dev_disable_lro(struct net_device *dev);
-+extern struct netdev_queue *dev_pick_tx(struct net_device *dev, struct sk_buff *skb);
- extern int            dev_queue_xmit(struct sk_buff *skb);
- extern int            register_netdevice(struct net_device *dev);
- extern void           unregister_netdevice_queue(struct net_device *dev,
---- /dev/null
-+++ b/include/linux/netfilter/xt_IMQ.h
-@@ -0,0 +1,9 @@
-+#ifndef _XT_IMQ_H
-+#define _XT_IMQ_H
-+
-+struct xt_imq_info {
-+      unsigned int todev;     /* target imq device */
-+};
-+
-+#endif /* _XT_IMQ_H */
-+
---- /dev/null
-+++ b/include/linux/netfilter_ipv4/ipt_IMQ.h
-@@ -0,0 +1,10 @@
-+#ifndef _IPT_IMQ_H
-+#define _IPT_IMQ_H
-+
-+/* Backwards compatibility for old userspace */
-+#include <linux/netfilter/xt_IMQ.h>
-+
-+#define ipt_imq_info xt_imq_info
-+
-+#endif /* _IPT_IMQ_H */
-+
---- /dev/null
-+++ b/include/linux/netfilter_ipv6/ip6t_IMQ.h
-@@ -0,0 +1,10 @@
-+#ifndef _IP6T_IMQ_H
-+#define _IP6T_IMQ_H
-+
-+/* Backwards compatibility for old userspace */
-+#include <linux/netfilter/xt_IMQ.h>
-+
-+#define ip6t_imq_info xt_imq_info
-+
-+#endif /* _IP6T_IMQ_H */
-+
---- a/include/linux/skbuff.h
-+++ b/include/linux/skbuff.h
-@@ -29,6 +29,9 @@
- #include <linux/rcupdate.h>
- #include <linux/dmaengine.h>
- #include <linux/hrtimer.h>
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+#include <linux/imq.h>
-+#endif
- /* Don't change this without changing skb_csum_unnecessary! */
- #define CHECKSUM_NONE 0
-@@ -328,6 +331,9 @@ struct sk_buff {
-        * first. This is owned by whoever has the skb queued ATM.
-        */
-       char                    cb[48] __aligned(8);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      void                    *cb_next;
-+#endif
-       unsigned long           _skb_refdst;
- #ifdef CONFIG_XFRM
-@@ -364,6 +370,9 @@ struct sk_buff {
-       struct nf_conntrack     *nfct;
-       struct sk_buff          *nfct_reasm;
- #endif
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      struct nf_queue_entry   *nf_queue_entry;
-+#endif
- #ifdef CONFIG_BRIDGE_NETFILTER
-       struct nf_bridge_info   *nf_bridge;
- #endif
-@@ -390,6 +399,10 @@ struct sk_buff {
-       /* 0/14 bit hole */
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      __u8                    imq_flags:IMQ_F_BITS;
-+#endif
-+
- #ifdef CONFIG_NET_DMA
-       dma_cookie_t            dma_cookie;
- #endif
-@@ -476,6 +489,12 @@ static inline struct rtable *skb_rtable(
-       return (struct rtable *)skb_dst(skb);
- }
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+extern int skb_save_cb(struct sk_buff *skb);
-+extern int skb_restore_cb(struct sk_buff *skb);
-+#endif
-+
- extern void kfree_skb(struct sk_buff *skb);
- extern void consume_skb(struct sk_buff *skb);
- extern void          __kfree_skb(struct sk_buff *skb);
-@@ -2098,6 +2117,10 @@ static inline void __nf_copy(struct sk_b
-       dst->nfct_reasm = src->nfct_reasm;
-       nf_conntrack_get_reasm(src->nfct_reasm);
- #endif
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      dst->imq_flags = src->imq_flags;
-+      dst->nf_queue_entry = src->nf_queue_entry;
-+#endif
- #ifdef CONFIG_BRIDGE_NETFILTER
-       dst->nf_bridge  = src->nf_bridge;
-       nf_bridge_get(src->nf_bridge);
---- a/include/net/netfilter/nf_queue.h
-+++ b/include/net/netfilter/nf_queue.h
-@@ -13,6 +13,12 @@ struct nf_queue_entry {
-       struct net_device       *indev;
-       struct net_device       *outdev;
-       int                     (*okfn)(struct sk_buff *);
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      int                     (*next_outfn)(struct nf_queue_entry *entry,
-+                                            unsigned int queuenum);
-+      unsigned int            next_queuenum;
-+#endif
- };
- #define nf_queue_entry_reroute(x) ((void *)x + sizeof(struct nf_queue_entry))
-@@ -30,5 +36,11 @@ extern int nf_unregister_queue_handler(u
-                                      const struct nf_queue_handler *qh);
- extern void nf_unregister_queue_handlers(const struct nf_queue_handler *qh);
- extern void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
-+extern void nf_queue_entry_release_refs(struct nf_queue_entry *entry);
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+extern void nf_register_queue_imq_handler(const struct nf_queue_handler *qh);
-+extern void nf_unregister_queue_imq_handler(void);
-+#endif
- #endif /* _NF_QUEUE_H */
---- a/net/core/dev.c
-+++ b/net/core/dev.c
-@@ -98,6 +98,9 @@
- #include <net/net_namespace.h>
- #include <net/sock.h>
- #include <linux/rtnetlink.h>
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+#include <linux/imq.h>
-+#endif
- #include <linux/proc_fs.h>
- #include <linux/seq_file.h>
- #include <linux/stat.h>
-@@ -1995,7 +1998,11 @@ int dev_hard_start_xmit(struct sk_buff *
-       int rc = NETDEV_TX_OK;
-       if (likely(!skb->next)) {
--              if (!list_empty(&ptype_all))
-+              if (!list_empty(&ptype_all)
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+                      && !(skb->imq_flags & IMQ_F_ENQUEUE)
-+#endif
-+                 )
-                       dev_queue_xmit_nit(skb, dev);
-               /*
-@@ -2119,8 +2126,7 @@ static inline u16 dev_cap_txqueue(struct
-       return queue_index;
- }
--static struct netdev_queue *dev_pick_tx(struct net_device *dev,
--                                      struct sk_buff *skb)
-+struct netdev_queue *dev_pick_tx(struct net_device *dev, struct sk_buff *skb)
- {
-       int queue_index;
-       const struct net_device_ops *ops = dev->netdev_ops;
-@@ -2149,6 +2155,7 @@ static struct netdev_queue *dev_pick_tx(
-       skb_set_queue_mapping(skb, queue_index);
-       return netdev_get_tx_queue(dev, queue_index);
- }
-+EXPORT_SYMBOL(dev_pick_tx);
- static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
-                                struct net_device *dev,
---- a/net/core/skbuff.c
-+++ b/net/core/skbuff.c
-@@ -72,6 +72,9 @@
- static struct kmem_cache *skbuff_head_cache __read_mostly;
- static struct kmem_cache *skbuff_fclone_cache __read_mostly;
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+static struct kmem_cache *skbuff_cb_store_cache __read_mostly;
-+#endif
- static void sock_pipe_buf_release(struct pipe_inode_info *pipe,
-                                 struct pipe_buffer *buf)
-@@ -91,6 +94,83 @@ static int sock_pipe_buf_steal(struct pi
-       return 1;
- }
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+/* Control buffer save/restore for IMQ devices */
-+struct skb_cb_table {
-+      void                    *cb_next;
-+      atomic_t                refcnt;
-+      char                    cb[48];
-+};
-+
-+static DEFINE_SPINLOCK(skb_cb_store_lock);
-+
-+int skb_save_cb(struct sk_buff *skb)
-+{
-+      struct skb_cb_table *next;
-+
-+      next = kmem_cache_alloc(skbuff_cb_store_cache, GFP_ATOMIC);
-+      if (!next)
-+              return -ENOMEM;
-+
-+      BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb));
-+
-+      memcpy(next->cb, skb->cb, sizeof(skb->cb));
-+      next->cb_next = skb->cb_next;
-+
-+      atomic_set(&next->refcnt, 1);
-+
-+      skb->cb_next = next;
-+      return 0;
-+}
-+EXPORT_SYMBOL(skb_save_cb);
-+
-+int skb_restore_cb(struct sk_buff *skb)
-+{
-+      struct skb_cb_table *next;
-+
-+      if (!skb->cb_next)
-+              return 0;
-+
-+      next = skb->cb_next;
-+
-+      BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb));
-+
-+      memcpy(skb->cb, next->cb, sizeof(skb->cb));
-+      skb->cb_next = next->cb_next;
-+
-+      spin_lock(&skb_cb_store_lock);
-+
-+      if (atomic_dec_and_test(&next->refcnt)) {
-+              kmem_cache_free(skbuff_cb_store_cache, next);
-+      }
-+
-+      spin_unlock(&skb_cb_store_lock);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL(skb_restore_cb);
-+
-+static void skb_copy_stored_cb(struct sk_buff *new, const struct sk_buff *__old)
-+{
-+      struct skb_cb_table *next;
-+      struct sk_buff *old;
-+
-+      if (!__old->cb_next) {
-+              new->cb_next = NULL;
-+              return;
-+      }
-+
-+      spin_lock(&skb_cb_store_lock);
-+
-+      old = (struct sk_buff *)__old;
-+
-+      next = old->cb_next;
-+      atomic_inc(&next->refcnt);
-+      new->cb_next = next;
-+
-+      spin_unlock(&skb_cb_store_lock);
-+}
-+#endif
- /* Pipe buffer operations for a socket. */
- static const struct pipe_buf_operations sock_pipe_buf_ops = {
-@@ -378,6 +458,26 @@ static void skb_release_head_state(struc
-               WARN_ON(in_irq());
-               skb->destructor(skb);
-       }
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      /* This should not happen. When it does, avoid memleak by restoring
-+      the chain of cb-backups. */
-+      while(skb->cb_next != NULL) {
-+              if (net_ratelimit())
-+                      printk(KERN_WARNING "IMQ: kfree_skb: skb->cb_next: "
-+                              "%08x\n", (unsigned int)skb->cb_next);
-+
-+              skb_restore_cb(skb);
-+      }
-+      /* This should not happen either, nf_queue_entry is nullified in
-+       * imq_dev_xmit(). If we have non-NULL nf_queue_entry then we are
-+       * leaking entry pointers, maybe memory. We don't know if this is
-+       * pointer to already freed memory, or should this be freed.
-+       * If this happens we need to add refcounting, etc for nf_queue_entry.
-+       */
-+      if (skb->nf_queue_entry && net_ratelimit())
-+              printk(KERN_WARNING
-+                              "IMQ: kfree_skb: skb->nf_queue_entry != NULL");
-+#endif
- #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
-       nf_conntrack_put(skb->nfct);
-       nf_conntrack_put_reasm(skb->nfct_reasm);
-@@ -514,6 +614,9 @@ static void __copy_skb_header(struct sk_
-       new->sp                 = secpath_get(old->sp);
- #endif
-       memcpy(new->cb, old->cb, sizeof(old->cb));
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      skb_copy_stored_cb(new, old);
-+#endif
-       new->csum               = old->csum;
-       new->local_df           = old->local_df;
-       new->pkt_type           = old->pkt_type;
-@@ -2765,6 +2868,13 @@ void __init skb_init(void)
-                                               0,
-                                               SLAB_HWCACHE_ALIGN|SLAB_PANIC,
-                                               NULL);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      skbuff_cb_store_cache = kmem_cache_create("skbuff_cb_store_cache",
-+                                                sizeof(struct skb_cb_table),
-+                                                0,
-+                                                SLAB_HWCACHE_ALIGN|SLAB_PANIC,
-+                                                NULL);
-+#endif
- }
- /**
---- a/net/netfilter/Kconfig
-+++ b/net/netfilter/Kconfig
-@@ -455,6 +455,18 @@ config NETFILTER_XT_TARGET_LED
-         For more information on the LEDs available on your system, see
-         Documentation/leds-class.txt
-+config NETFILTER_XT_TARGET_IMQ
-+        tristate '"IMQ" target support'
-+      depends on NETFILTER_XTABLES
-+      depends on IP_NF_MANGLE || IP6_NF_MANGLE
-+      select IMQ
-+      default m if NETFILTER_ADVANCED=n
-+        help
-+          This option adds a `IMQ' target which is used to specify if and
-+          to which imq device packets should get enqueued/dequeued.
-+
-+          To compile it as a module, choose M here.  If unsure, say N.
-+
- config NETFILTER_XT_TARGET_MARK
-       tristate '"MARK" target support'
-       depends on NETFILTER_ADVANCED
---- a/net/netfilter/Makefile
-+++ b/net/netfilter/Makefile
-@@ -51,6 +51,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSEC
- obj-$(CONFIG_NETFILTER_XT_TARGET_CT) += xt_CT.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o
-+obj-$(CONFIG_NETFILTER_XT_TARGET_IMQ) += xt_IMQ.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
---- a/net/netfilter/nf_queue.c
-+++ b/net/netfilter/nf_queue.c
-@@ -22,6 +22,26 @@ static const struct nf_queue_handler __r
- static DEFINE_MUTEX(queue_handler_mutex);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+static const struct nf_queue_handler *queue_imq_handler;
-+
-+void nf_register_queue_imq_handler(const struct nf_queue_handler *qh)
-+{
-+      mutex_lock(&queue_handler_mutex);
-+      rcu_assign_pointer(queue_imq_handler, qh);
-+      mutex_unlock(&queue_handler_mutex);
-+}
-+EXPORT_SYMBOL(nf_register_queue_imq_handler);
-+
-+void nf_unregister_queue_imq_handler(void)
-+{
-+      mutex_lock(&queue_handler_mutex);
-+      rcu_assign_pointer(queue_imq_handler, NULL);
-+      mutex_unlock(&queue_handler_mutex);
-+}
-+EXPORT_SYMBOL(nf_unregister_queue_imq_handler);
-+#endif
-+
- /* return EBUSY when somebody else is registered, return EEXIST if the
-  * same handler is registered, return 0 in case of success. */
- int nf_register_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh)
-@@ -82,7 +102,7 @@ void nf_unregister_queue_handlers(const
- }
- EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers);
--static void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
-+void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
- {
-       /* Release those devices we held, or Alexey will kill me. */
-       if (entry->indev)
-@@ -102,6 +122,7 @@ static void nf_queue_entry_release_refs(
-       /* Drop reference to owner of hook which queued us. */
-       module_put(entry->elem->owner);
- }
-+EXPORT_SYMBOL_GPL(nf_queue_entry_release_refs);
- /*
-  * Any packet that leaves via this function must come back
-@@ -123,12 +144,26 @@ static int __nf_queue(struct sk_buff *sk
- #endif
-       const struct nf_afinfo *afinfo;
-       const struct nf_queue_handler *qh;
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      const struct nf_queue_handler *qih = NULL;
-+#endif
-       /* QUEUE == DROP if noone is waiting, to be safe. */
-       rcu_read_lock();
-       qh = rcu_dereference(queue_handler[pf]);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+      if (pf == PF_INET || pf == PF_INET6)
-+#else
-+      if (pf == PF_INET)
-+#endif
-+              qih = rcu_dereference(queue_imq_handler);
-+
-+      if (!qh && !qih)
-+#else /* !IMQ */
-       if (!qh)
-+#endif
-               goto err_unlock;
-       afinfo = nf_get_afinfo(pf);
-@@ -147,6 +182,10 @@ static int __nf_queue(struct sk_buff *sk
-               .indev  = indev,
-               .outdev = outdev,
-               .okfn   = okfn,
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+              .next_outfn = qh ? qh->outfn : NULL,
-+              .next_queuenum = queuenum,
-+#endif
-       };
-       /* If it's going away, ignore hook. */
-@@ -173,8 +212,19 @@ static int __nf_queue(struct sk_buff *sk
- #endif
-       skb_dst_force(skb);
-       afinfo->saveroute(skb, entry);
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      if (qih) {
-+              status = qih->outfn(entry, queuenum);
-+              goto imq_skip_queue;
-+      }
-+#endif
-+
-       status = qh->outfn(entry, queuenum);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+imq_skip_queue:
-+#endif
-       rcu_read_unlock();
-       if (status < 0) {
---- /dev/null
-+++ b/net/netfilter/xt_IMQ.c
-@@ -0,0 +1,73 @@
-+/*
-+ * This target marks packets to be enqueued to an imq device
-+ */
-+#include <linux/module.h>
-+#include <linux/skbuff.h>
-+#include <linux/netfilter/x_tables.h>
-+#include <linux/netfilter/xt_IMQ.h>
-+#include <linux/imq.h>
-+
-+static unsigned int imq_target(struct sk_buff *pskb,
-+                              const struct xt_action_param *par)
-+{
-+      const struct xt_imq_info *mr = par->targinfo;
-+
-+      pskb->imq_flags = (mr->todev & IMQ_F_IFMASK) | IMQ_F_ENQUEUE;
-+
-+      return XT_CONTINUE;
-+}
-+
-+static int imq_checkentry(const struct xt_tgchk_param *par)
-+{
-+      struct xt_imq_info *mr = par->targinfo;
-+
-+      if (mr->todev > IMQ_MAX_DEVS - 1) {
-+              printk(KERN_WARNING
-+                     "IMQ: invalid device specified, highest is %u\n",
-+                     IMQ_MAX_DEVS - 1);
-+              return -EINVAL;
-+      }
-+
-+      return 0;
-+}
-+
-+static struct xt_target xt_imq_reg[] __read_mostly = {
-+      {
-+              .name           = "IMQ",
-+              .family         = AF_INET,
-+              .checkentry     = imq_checkentry,
-+              .target         = imq_target,
-+              .targetsize     = sizeof(struct xt_imq_info),
-+              .table          = "mangle",
-+              .me             = THIS_MODULE
-+      },
-+      {
-+              .name           = "IMQ",
-+              .family         = AF_INET6,
-+              .checkentry     = imq_checkentry,
-+              .target         = imq_target,
-+              .targetsize     = sizeof(struct xt_imq_info),
-+              .table          = "mangle",
-+              .me             = THIS_MODULE
-+      },
-+};
-+
-+static int __init imq_init(void)
-+{
-+      return xt_register_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg));
-+}
-+
-+static void __exit imq_fini(void)
-+{
-+      xt_unregister_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg));
-+}
-+
-+module_init(imq_init);
-+module_exit(imq_fini);
-+
-+MODULE_AUTHOR("http://www.linuximq.net");
-+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information.");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS("ipt_IMQ");
-+MODULE_ALIAS("ip6t_IMQ");
-+
index 22bf51c3a9006bad65c663942182d7a7830985db..d270e9020bf575526eb0104b9d19d57407c75e22 100644 (file)
@@ -8,7 +8,7 @@
        depends on NETFILTER_ADVANCED
        help
          H.323 is a VoIP signalling protocol from ITU-T. As one of the most
-@@ -570,7 +569,6 @@ config NETFILTER_XT_TARGET_SECMARK
+@@ -558,7 +557,6 @@ config NETFILTER_XT_TARGET_SECMARK
  
  config NETFILTER_XT_TARGET_TCPMSS
        tristate '"TCPMSS" target support'
index e4324717b4459ce1f1009053e6317c930b01b6e4..6ea9ba51ee0d24cf3a3ac657278109d9b11de859 100644 (file)
@@ -1,6 +1,6 @@
 --- a/arch/mips/include/asm/string.h
 +++ b/arch/mips/include/asm/string.h
-@@ -133,11 +133,44 @@ strncmp(__const__ char *__cs, __const__
+@@ -133,11 +133,44 @@ strncmp(__const__ char *__cs, __const__ 
  
  #define __HAVE_ARCH_MEMSET
  extern void *memset(void *__s, int __c, size_t __count);
index fe8cecfc771ed7a1cd16d22361475b2151e8bb98..83fd6c309928d78bdbdc7db87abdd7b06383d9cd 100644 (file)
@@ -1,6 +1,6 @@
 --- a/include/linux/slab.h
 +++ b/include/linux/slab.h
-@@ -130,8 +130,8 @@ int kmem_ptr_validate(struct kmem_cache
+@@ -130,8 +130,8 @@ int kmem_ptr_validate(struct kmem_cache 
   * to do various tricks to work around compiler limitations in order to
   * ensure proper constant folding.
   */
index d021ec1b309347e8ece84b6885d6f2ac97f22ed9..826eb44dff3e214d78027bef349ff5ae7f4e2db1 100644 (file)
@@ -61,7 +61,7 @@
  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
  extern int mini_fo_create(inode_t *dir, dentry_t *dentry, int mode, struct nameidata *nd);
  
-@@ -501,6 +505,29 @@ static inline void double_unlock(struct
+@@ -501,6 +505,29 @@ static inline void double_unlock(struct 
  #endif  /* if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) */
  #endif /* __KERNEL__ */
  
  #endif /* defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) */
 --- a/fs/mini_fo/aux.c
 +++ b/fs/mini_fo/aux.c
-@@ -164,11 +164,11 @@ dentry_t *bpath_walk(super_block_t *sb,
+@@ -164,11 +164,11 @@ dentry_t *bpath_walk(super_block_t *sb, 
        err = vfs_path_lookup(mnt->mnt_root, mnt, bpath+1, 0, &nd);
  
        /* validate */
index d2a843c82ee77b1c57f51b935313443eabc290de..37503710c83afd8e41705eaf8397e6740273b33a 100644 (file)
@@ -1,6 +1,6 @@
 --- a/fs/mini_fo/super.c
 +++ b/fs/mini_fo/super.c
-@@ -84,6 +84,7 @@ mini_fo_write_inode(inode_t *inode, int
+@@ -84,6 +84,7 @@ mini_fo_write_inode(inode_t *inode, int 
  #endif /* defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) */
  
  
index 7b36ab61155852435502d646418fe1ff151b1081..b3e4b6e7c75b08e80bb482f2d3e49d7027c8547f 100644 (file)
@@ -20,7 +20,7 @@
  #else
  static inline int kobject_uevent(struct kobject *kobj,
                                 enum kobject_action action)
-@@ -231,6 +237,16 @@ static inline int add_uevent_var(struct
+@@ -231,6 +237,16 @@ static inline int add_uevent_var(struct 
  static inline int kobject_action_type(const char *buf, size_t count,
                                      enum kobject_action *type)
  { return -EINVAL; }
index 013c116c4a22147b9ba902f9e1fdf2cbbad07cc6..33429cb43087f7ba4eeaa8e400ecc7bebd04fe3d 100644 (file)
 +module_exit(connmark_cleanup_module);
 --- a/net/sched/Kconfig
 +++ b/net/sched/Kconfig
-@@ -559,6 +559,18 @@
+@@ -559,6 +559,18 @@ config NET_ACT_CSUM
          To compile this code as a module, choose M here: the
          module will be called act_csum.
  
        depends on NET_CLS_U32 || NET_CLS_FW
 --- a/net/sched/Makefile
 +++ b/net/sched/Makefile
-@@ -16,6 +16,7 @@
+@@ -16,6 +16,7 @@ obj-$(CONFIG_NET_ACT_PEDIT)  += act_pedit
  obj-$(CONFIG_NET_ACT_SIMP)    += act_simple.o
  obj-$(CONFIG_NET_ACT_SKBEDIT) += act_skbedit.o
  obj-$(CONFIG_NET_ACT_CSUM)    += act_csum.o
index 8d901845564cc440a65994f6f8970b37fbdd3e2c..62a90a4591698bb871982438fc9871c6cbd97efb 100644 (file)
@@ -11,7 +11,7 @@
  endif # NEW_LEDS
 --- a/drivers/leds/Makefile
 +++ b/drivers/leds/Makefile
-@@ -52,3 +52,4 @@ obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) +=
+@@ -52,3 +52,4 @@ obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += 
  obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT)  += ledtrig-backlight.o
  obj-$(CONFIG_LEDS_TRIGGER_GPIO)               += ledtrig-gpio.o
  obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
index 6406adac2a03d1c606b2129ffb3fbda2f355a9c8..5354aa187bab0c24efe9f1cadfa98a56f18a3b31 100644 (file)
@@ -14,7 +14,7 @@
  endif # NEW_LEDS
 --- a/drivers/leds/Makefile
 +++ b/drivers/leds/Makefile
-@@ -53,3 +53,4 @@ obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) +=
+@@ -53,3 +53,4 @@ obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) += 
  obj-$(CONFIG_LEDS_TRIGGER_GPIO)               += ledtrig-gpio.o
  obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
  obj-$(CONFIG_LEDS_TRIGGER_MORSE)      += ledtrig-morse.o
index 3b7063223ecda6601e050f7f19b8719af17b00dc..6609a1670af5e5d3297b09bbc6baf6cc0c67880b 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/char/gpio_dev.c
 +++ b/drivers/char/gpio_dev.c
-@@ -114,7 +114,7 @@ gpio_close(struct inode * inode, struct
+@@ -114,7 +114,7 @@ gpio_close(struct inode * inode, struct 
  }
  
  struct file_operations gpio_fops = {
index c334b17d0872a877f52cd9c0e4234ad118df7d09..5c70e79a058d050e90224ac0ef80dcb1180235ab 100644 (file)
                        dev->checkpointBlockList[i] = -1;
        }
  
-@@ -191,18 +185,17 @@ int yaffs_GetCheckpointSum(yaffs_Device
+@@ -191,18 +185,17 @@ int yaffs_GetCheckpointSum(yaffs_Device 
  
  static int yaffs_CheckpointFlushBuffer(yaffs_Device *dev)
  {
  {
        unsigned char cDelta;   /* column parity delta */
        unsigned lDelta;        /* line parity delta */
-@@ -294,8 +292,7 @@ int yaffs_ECCCorrectOther(unsigned char
+@@ -294,8 +292,7 @@ int yaffs_ECCCorrectOther(unsigned char 
                return 0; /* no error */
  
        if (lDelta == ~lDeltaPrime &&
                /* Single bit (recoverable) error in data */
  
                bit = 0;
-@@ -307,7 +304,7 @@ int yaffs_ECCCorrectOther(unsigned char
+@@ -307,7 +304,7 @@ int yaffs_ECCCorrectOther(unsigned char 
                if (cDelta & 0x02)
                        bit |= 0x01;
  
                        return -1;
  
                data[lDelta] ^= (1 << bit);
-@@ -316,7 +313,7 @@ int yaffs_ECCCorrectOther(unsigned char
+@@ -316,7 +313,7 @@ int yaffs_ECCCorrectOther(unsigned char 
        }
  
        if ((yaffs_CountBits32(lDelta) + yaffs_CountBits32(lDeltaPrime) +
                /* Reccoverable error in ecc */
  
                *read_ecc = *test_ecc;
-@@ -326,6 +323,4 @@ int yaffs_ECCCorrectOther(unsigned char
+@@ -326,6 +323,4 @@ int yaffs_ECCCorrectOther(unsigned char 
        /* Unrecoverable error */
  
        return -1;
  {
        unsigned char *alias;
        int ret;
-@@ -329,7 +395,7 @@ static int yaffs_readlink(struct dentry
+@@ -329,7 +395,7 @@ static int yaffs_readlink(struct dentry 
        return ret;
  }
  
  static int yaffs_file_flush(struct file *file, fl_owner_t id)
  #else
  static int yaffs_file_flush(struct file *file)
-@@ -513,8 +579,8 @@ static int yaffs_file_flush(struct file
+@@ -513,8 +579,8 @@ static int yaffs_file_flush(struct file 
        yaffs_Device *dev = obj->myDev;
  
        T(YAFFS_TRACE_OS,
  
        yaffs_GrossLock(dev);
  
-@@ -535,15 +601,15 @@ static int yaffs_readpage_nolock(struct
+@@ -535,15 +601,15 @@ static int yaffs_readpage_nolock(struct 
  
        yaffs_Device *dev;
  
        BUG_ON(!PageLocked(pg));
  #else
        if (!PageLocked(pg))
-@@ -555,9 +621,9 @@ static int yaffs_readpage_nolock(struct
+@@ -555,9 +621,9 @@ static int yaffs_readpage_nolock(struct 
  
        yaffs_GrossLock(dev);
  
  
        yaffs_GrossUnlock(dev);
  
-@@ -575,7 +641,7 @@ static int yaffs_readpage_nolock(struct
+@@ -575,7 +641,7 @@ static int yaffs_readpage_nolock(struct 
        flush_dcache_page(pg);
        kunmap(pg);
  
                if (n < step) {
                        n++;
                        continue;
-@@ -2119,7 +2356,7 @@ static int yaffs_proc_write(struct file
+@@ -2119,7 +2356,7 @@ static int yaffs_proc_write(struct file 
        char *end;
        char *mask_name;
        const char *x;
        int i;
        int done = 0;
        int add, len = 0;
-@@ -2129,9 +2366,8 @@ static int yaffs_proc_write(struct file
+@@ -2129,9 +2366,8 @@ static int yaffs_proc_write(struct file 
  
        while (!done && (pos < count)) {
                done = 1;
  
                switch (buf[pos]) {
                case '+':
-@@ -2148,20 +2384,21 @@ static int yaffs_proc_write(struct file
+@@ -2148,20 +2384,21 @@ static int yaffs_proc_write(struct file 
                mask_name = NULL;
  
                mask_bitfield = simple_strtoul(buf + pos, &end, 0);
                                        mask_name = mask_flags[i].mask_name;
                                        mask_bitfield = mask_flags[i].mask_bitfield;
                                        done = 0;
-@@ -2172,7 +2409,7 @@ static int yaffs_proc_write(struct file
+@@ -2172,7 +2409,7 @@ static int yaffs_proc_write(struct file 
  
                if (mask_name != NULL) {
                        done = 0;
                        case '-':
                                rg &= ~mask_bitfield;
                                break;
-@@ -2191,13 +2428,13 @@ static int yaffs_proc_write(struct file
+@@ -2191,13 +2428,13 @@ static int yaffs_proc_write(struct file 
  
        yaffs_traceMask = rg | YAFFS_TRACE_ALWAYS;
  
  {
        /* Get the real object in case we were fed a hard link as an equivalent object */
        equivalentObject = yaffs_GetEquivalentObject(equivalentObject);
-@@ -2363,33 +2396,31 @@ yaffs_Object *yaffs_Link(yaffs_Object *
+@@ -2363,33 +2396,31 @@ yaffs_Object *yaffs_Link(yaffs_Object * 
  
  }
  
        int nToCopy;
        int n = nBytes;
        int nDone = 0;
-@@ -4600,27 +4665,26 @@ int yaffs_ReadDataFromFile(yaffs_Object
+@@ -4600,27 +4665,26 @@ int yaffs_ReadDataFromFile(yaffs_Object 
        dev = in->myDev;
  
        while (n > 0) {
                        if (dev->nShortOpCaches > 0) {
  
                                /* If we can't find the data in the cache, then load it up. */
-@@ -4641,14 +4705,9 @@ int yaffs_ReadDataFromFile(yaffs_Object
+@@ -4641,14 +4705,9 @@ int yaffs_ReadDataFromFile(yaffs_Object 
  
                                cache->locked = 1;
  
                                cache->locked = 0;
                        } else {
                                /* Read into the local buffer then copy..*/
-@@ -4657,41 +4716,19 @@ int yaffs_ReadDataFromFile(yaffs_Object
+@@ -4657,41 +4716,19 @@ int yaffs_ReadDataFromFile(yaffs_Object 
                                    yaffs_GetTempBuffer(dev, __LINE__);
                                yaffs_ReadChunkDataFromObject(in, chunk,
                                                              localBuffer);
                }
  
                n -= nToCopy;
-@@ -4704,28 +4741,37 @@ int yaffs_ReadDataFromFile(yaffs_Object
+@@ -4704,28 +4741,37 @@ int yaffs_ReadDataFromFile(yaffs_Object 
        return nDone;
  }
  
        int newFullChunks;
  
        yaffs_Device *dev = in->myDev;
-@@ -4955,13 +4981,11 @@ int yaffs_ResizeFile(yaffs_Object * in,
+@@ -4955,13 +4981,11 @@ int yaffs_ResizeFile(yaffs_Object * in, 
  
        yaffs_CheckGarbageCollection(dev);
  
  
        if (newSize < oldFileSize) {
  
-@@ -4994,21 +5018,20 @@ int yaffs_ResizeFile(yaffs_Object * in,
+@@ -4994,21 +5018,20 @@ int yaffs_ResizeFile(yaffs_Object * in, 
        }
  
  
  {
        obj = yaffs_GetEquivalentObject(obj);
  
-@@ -5024,7 +5047,7 @@ loff_t yaffs_GetFileSize(yaffs_Object *
+@@ -5024,7 +5047,7 @@ loff_t yaffs_GetFileSize(yaffs_Object * 
  
  
  
  {
        int init_failed = 0;
        unsigned x;
-@@ -7040,6 +7126,8 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7040,6 +7126,8 @@ int yaffs_GutsInitialise(yaffs_Device * 
        dev->chunkOffset = 0;
        dev->nFreeChunks = 0;
  
        if (dev->startBlock == 0) {
                dev->internalStartBlock = dev->startBlock + 1;
                dev->internalEndBlock = dev->endBlock + 1;
-@@ -7049,18 +7137,18 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7049,18 +7137,18 @@ int yaffs_GutsInitialise(yaffs_Device * 
  
        /* Check geometry parameters. */
  
                return YAFFS_FAIL;
        }
  
-@@ -7070,6 +7158,12 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7070,6 +7158,12 @@ int yaffs_GutsInitialise(yaffs_Device * 
                return YAFFS_FAIL;
        }
  
        /* Got the right mix of functions? */
        if (!yaffs_CheckDevFunctions(dev)) {
                /* Function missing */
-@@ -7097,31 +7191,18 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7097,31 +7191,18 @@ int yaffs_GutsInitialise(yaffs_Device * 
  
        dev->isMounted = 1;
  
  
        /*
         * Calculate chunkGroupBits.
-@@ -7133,16 +7214,15 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7133,16 +7214,15 @@ int yaffs_GutsInitialise(yaffs_Device * 
        bits = ShiftsGE(x);
  
        /* Set up tnode width if wide tnodes are enabled. */
                dev->tnodeWidth = 16;
  
        dev->tnodeMask = (1<<dev->tnodeWidth)-1;
-@@ -7193,7 +7273,7 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7193,7 +7273,7 @@ int yaffs_GutsInitialise(yaffs_Device * 
        dev->hasPendingPrioritisedGCs = 1; /* Assume the worst for now, will get fixed on first GC */
  
        /* Initialise temporary buffers and caches. */
                init_failed = 1;
  
        dev->srCache = NULL;
-@@ -7203,25 +7283,26 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7203,25 +7283,26 @@ int yaffs_GutsInitialise(yaffs_Device * 
        if (!init_failed &&
            dev->nShortOpCaches > 0) {
                int i;
                        init_failed = 1;
  
                dev->srLastUse = 0;
-@@ -7229,29 +7310,30 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7229,29 +7310,30 @@ int yaffs_GutsInitialise(yaffs_Device * 
  
        dev->cacheHits = 0;
  
                                T(YAFFS_TRACE_ALWAYS,
                                  (TSTR("yaffs: restored from checkpoint" TENDSTR)));
                        } else {
-@@ -7273,24 +7355,25 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7273,24 +7355,25 @@ int yaffs_GutsInitialise(yaffs_Device * 
                                dev->nBackgroundDeletions = 0;
                                dev->oldestDirtySequence = 0;
  
                /* Clean up the mess */
                T(YAFFS_TRACE_TRACING,
                  (TSTR("yaffs: yaffs_GutsInitialise() aborted.\n" TENDSTR)));
-@@ -7318,7 +7401,7 @@ int yaffs_GutsInitialise(yaffs_Device *
+@@ -7318,7 +7401,7 @@ int yaffs_GutsInitialise(yaffs_Device * 
  
  }
  
  {
        if (etags) {
                memset(etags, 0, sizeof(*etags));
-@@ -169,9 +169,9 @@ static int rettags(yaffs_ExtendedTags *
+@@ -169,9 +169,9 @@ static int rettags(yaffs_ExtendedTags * 
   * Returns YAFFS_OK or YAFFS_FAIL.
   */
  int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device *dev,
 +                      yaffs_UnpackTags2(tags, &pt);
 +              }
 +      }
-+
+-      if(tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR)
+-              tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
 +      if (localData)
 +              yaffs_ReleaseTempBuffer(dev, data, __LINE__);
  
--      if(tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR)
 +      if (tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR)
-               tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
--
++              tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
        if (retval == 0)
                return YAFFS_OK;
        else
index d03deb8427f3cd019e7d5641f754d14f75600f86..b5ceb47bc5317f30b17bc21b09924e5feee18949 100644 (file)
  chunk/page state.  This byte is zeroed when the page is discarded.
  Choose this option if you have existing on-NAND data in this format
  that you need to continue to support.  New data written also uses the
-@@ -57,7 +78,7 @@ adjusted to use the older-style format.
+@@ -57,7 +78,7 @@ adjusted to use the older-style format. 
  MTD versions in yaffs_mtdif1.c.
  */
  /* Default: Not selected */
                        yaffs_ECCOther *read_ecc,
                        const yaffs_ECCOther *test_ecc)
  {
-@@ -304,7 +301,7 @@ int yaffs_ECCCorrectOther(unsigned char
+@@ -304,7 +301,7 @@ int yaffs_ECCCorrectOther(unsigned char 
                if (cDelta & 0x02)
                        bit |= 0x01;
  
                        return -1;
  
                data[lDelta] ^= (1 << bit);
-@@ -312,8 +309,8 @@ int yaffs_ECCCorrectOther(unsigned char
+@@ -312,8 +309,8 @@ int yaffs_ECCCorrectOther(unsigned char 
                return 1; /* corrected */
        }
  
index e40053170c89c6f7569699eff156072b022a8721..ad44715411263c97fc2b187c8fffd5e1dba7adae 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/hostap/hostap_ap.c
 +++ b/drivers/net/wireless/hostap/hostap_ap.c
-@@ -2335,13 +2335,13 @@ int prism2_ap_get_sta_qual(local_info_t
+@@ -2335,13 +2335,13 @@ int prism2_ap_get_sta_qual(local_info_t 
                addr[count].sa_family = ARPHRD_ETHER;
                memcpy(addr[count].sa_data, sta->addr, ETH_ALEN);
                if (sta->last_rx_silence == 0)
index 410384c28f0dc6a42f8e8252bf03775f198e82b2..a1c088a9a8d7b102216f74c4d2e6de89aee71dfc 100644 (file)
@@ -24,7 +24,7 @@
   * All of these routines try to estimate how many bits of randomness a
   * particular randomness source.  They do this by keeping track of the
   * first and second order deltas of the event timings.
-@@ -715,6 +725,61 @@ void add_disk_randomness(struct gendisk
+@@ -715,6 +725,61 @@ void add_disk_randomness(struct gendisk 
  }
  #endif
  
index c4cc05857ddd37a232ba43917d5254c7d84b7fc4..c1a70f007ffd6cada935514f1c572d4d5982dc5b 100644 (file)
@@ -1,6 +1,6 @@
 --- a/scripts/Makefile.lib
 +++ b/scripts/Makefile.lib
-@@ -231,7 +231,7 @@ cmd_bzip2 = (cat $(filter-out FORCE,$^)
+@@ -231,7 +231,7 @@ cmd_bzip2 = (cat $(filter-out FORCE,$^) 
  
  quiet_cmd_lzma = LZMA    $@
  cmd_lzma = (cat $(filter-out FORCE,$^) | \
diff --git a/target/linux/generic/patches-2.6.38/150-netfilter_imq.patch b/target/linux/generic/patches-2.6.38/150-netfilter_imq.patch
deleted file mode 100644 (file)
index 8853e89..0000000
+++ /dev/null
@@ -1,1342 +0,0 @@
---- /dev/null
-+++ b/drivers/net/imq.c
-@@ -0,0 +1,638 @@
-+/*
-+ *             Pseudo-driver for the intermediate queue device.
-+ *
-+ *             This program is free software; you can redistribute it and/or
-+ *             modify it under the terms of the GNU General Public License
-+ *             as published by the Free Software Foundation; either version
-+ *             2 of the License, or (at your option) any later version.
-+ *
-+ * Authors:    Patrick McHardy, <kaber@trash.net>
-+ *
-+ *            The first version was written by Martin Devera, <devik@cdi.cz>
-+ *
-+ * Credits:    Jan Rafaj <imq2t@cedric.vabo.cz>
-+ *              - Update patch to 2.4.21
-+ *             Sebastian Strollo <sstrollo@nortelnetworks.com>
-+ *              - Fix "Dead-loop on netdevice imq"-issue
-+ *             Marcel Sebek <sebek64@post.cz>
-+ *              - Update to 2.6.2-rc1
-+ *
-+ *           After some time of inactivity there is a group taking care
-+ *           of IMQ again: http://www.linuximq.net
-+ *
-+ *
-+ *           2004/06/30 - New version of IMQ patch to kernels <=2.6.7
-+ *             including the following changes:
-+ *
-+ *           - Correction of ipv6 support "+"s issue (Hasso Tepper)
-+ *           - Correction of imq_init_devs() issue that resulted in
-+ *           kernel OOPS unloading IMQ as module (Norbert Buchmuller)
-+ *           - Addition of functionality to choose number of IMQ devices
-+ *           during kernel config (Andre Correa)
-+ *           - Addition of functionality to choose how IMQ hooks on
-+ *           PRE and POSTROUTING (after or before NAT) (Andre Correa)
-+ *           - Cosmetic corrections (Norbert Buchmuller) (Andre Correa)
-+ *
-+ *
-+ *             2005/12/16 - IMQ versions between 2.6.7 and 2.6.13 were
-+ *             released with almost no problems. 2.6.14-x was released
-+ *             with some important changes: nfcache was removed; After
-+ *             some weeks of trouble we figured out that some IMQ fields
-+ *             in skb were missing in skbuff.c - skb_clone and copy_skb_header.
-+ *             These functions are correctly patched by this new patch version.
-+ *
-+ *             Thanks for all who helped to figure out all the problems with
-+ *             2.6.14.x: Patrick McHardy, Rune Kock, VeNoMouS, Max CtRiX,
-+ *             Kevin Shanahan, Richard Lucassen, Valery Dachev (hopefully
-+ *             I didn't forget anybody). I apologize again for my lack of time.
-+ *
-+ *
-+ *             2008/06/17 - 2.6.25 - Changed imq.c to use qdisc_run() instead 
-+ *             of qdisc_restart() and moved qdisc_run() to tasklet to avoid
-+ *             recursive locking. New initialization routines to fix 'rmmod' not
-+ *             working anymore. Used code from ifb.c. (Jussi Kivilinna)
-+ *
-+ *             2008/08/06 - 2.6.26 - (JK)
-+ *              - Replaced tasklet with 'netif_schedule()'.
-+ *              - Cleaned up and added comments for imq_nf_queue().
-+ *
-+ *             2009/04/12
-+ *              - Add skb_save_cb/skb_restore_cb helper functions for backuping
-+ *                control buffer. This is needed because qdisc-layer on kernels
-+ *                2.6.27 and newer overwrite control buffer. (Jussi Kivilinna)
-+ *              - Add better locking for IMQ device. Hopefully this will solve
-+ *                SMP issues. (Jussi Kivilinna)
-+ *              - Port to 2.6.27
-+ *              - Port to 2.6.28
-+ *              - Port to 2.6.29 + fix rmmod not working
-+ *
-+ *             2009/04/20 - (Jussi Kivilinna)
-+ *              - Use netdevice feature flags to avoid extra packet handling
-+ *                by core networking layer and possibly increase performance.
-+ *
-+ *             2009/09/26 - (Jussi Kivilinna)
-+ *              - Add imq_nf_reinject_lockless to fix deadlock with
-+ *                imq_nf_queue/imq_nf_reinject.
-+ *
-+ *             2009/12/08 - (Jussi Kivilinna)
-+ *              - Port to 2.6.32
-+ *              - Add check for skb->nf_queue_entry==NULL in imq_dev_xmit()
-+ *              - Also add better error checking for skb->nf_queue_entry usage
-+ *
-+ *             2010/02/25 - (Jussi Kivilinna)
-+ *              - Port to 2.6.33
-+ *
-+ *             2010/08/12 - (Jussi Kivilinna)
-+ *              - Port to 2.6.35
-+ *
-+ *           Also, many thanks to pablo Sebastian Greco for making the initial
-+ *           patch and to those who helped the testing.
-+ *
-+ *             More info at: http://www.linuximq.net/ (Andre Correa)
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/moduleparam.h>
-+#include <linux/list.h>
-+#include <linux/skbuff.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/rtnetlink.h>
-+#include <linux/if_arp.h>
-+#include <linux/netfilter.h>
-+#include <linux/netfilter_ipv4.h>
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+      #include <linux/netfilter_ipv6.h>
-+#endif
-+#include <linux/imq.h>
-+#include <net/pkt_sched.h>
-+#include <net/netfilter/nf_queue.h>
-+
-+static nf_hookfn imq_nf_hook;
-+
-+static struct nf_hook_ops imq_ingress_ipv4 = {
-+      .hook           = imq_nf_hook,
-+      .owner          = THIS_MODULE,
-+      .pf             = PF_INET,
-+      .hooknum        = NF_INET_PRE_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+      .priority       = NF_IP_PRI_MANGLE + 1
-+#else
-+      .priority       = NF_IP_PRI_NAT_DST + 1
-+#endif
-+};
-+
-+static struct nf_hook_ops imq_egress_ipv4 = {
-+      .hook           = imq_nf_hook,
-+      .owner          = THIS_MODULE,
-+      .pf             = PF_INET,
-+      .hooknum        = NF_INET_POST_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
-+      .priority       = NF_IP_PRI_LAST
-+#else
-+      .priority       = NF_IP_PRI_NAT_SRC - 1
-+#endif
-+};
-+
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+static struct nf_hook_ops imq_ingress_ipv6 = {
-+      .hook           = imq_nf_hook,
-+      .owner          = THIS_MODULE,
-+      .pf             = PF_INET6,
-+      .hooknum        = NF_INET_PRE_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+      .priority       = NF_IP6_PRI_MANGLE + 1
-+#else
-+      .priority       = NF_IP6_PRI_NAT_DST + 1
-+#endif
-+};
-+
-+static struct nf_hook_ops imq_egress_ipv6 = {
-+      .hook           = imq_nf_hook,
-+      .owner          = THIS_MODULE,
-+      .pf             = PF_INET6,
-+      .hooknum        = NF_INET_POST_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
-+      .priority       = NF_IP6_PRI_LAST
-+#else
-+      .priority       = NF_IP6_PRI_NAT_SRC - 1
-+#endif
-+};
-+#endif
-+
-+#if defined(CONFIG_IMQ_NUM_DEVS)
-+static unsigned int numdevs = CONFIG_IMQ_NUM_DEVS;
-+#else
-+static unsigned int numdevs = IMQ_MAX_DEVS;
-+#endif
-+
-+static DEFINE_SPINLOCK(imq_nf_queue_lock);
-+
-+static struct net_device *imq_devs_cache[IMQ_MAX_DEVS];
-+
-+
-+static struct net_device_stats *imq_get_stats(struct net_device *dev)
-+{
-+      return &dev->stats;
-+}
-+
-+/* called for packets kfree'd in qdiscs at places other than enqueue */
-+static void imq_skb_destructor(struct sk_buff *skb)
-+{
-+      struct nf_queue_entry *entry = skb->nf_queue_entry;
-+
-+      skb->nf_queue_entry = NULL;
-+
-+      if (entry) {
-+              nf_queue_entry_release_refs(entry);
-+              kfree(entry);
-+      }
-+
-+      skb_restore_cb(skb); /* kfree backup */
-+}
-+
-+/* locking not needed when called from imq_nf_queue */
-+static void imq_nf_reinject_lockless(struct nf_queue_entry *entry,
-+                                              unsigned int verdict)
-+{
-+      int status;
-+
-+      if (!entry->next_outfn) {
-+              nf_reinject(entry, verdict);
-+              return;
-+      }
-+
-+      status = entry->next_outfn(entry, entry->next_queuenum);
-+      if (status < 0) {
-+              nf_queue_entry_release_refs(entry);
-+              kfree_skb(entry->skb);
-+              kfree(entry);
-+      }
-+}
-+
-+static void imq_nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
-+{
-+      int status;
-+
-+      if (!entry->next_outfn) {
-+              spin_lock_bh(&imq_nf_queue_lock);
-+              nf_reinject(entry, verdict);
-+              spin_unlock_bh(&imq_nf_queue_lock);
-+              return;
-+      }
-+
-+      rcu_read_lock();
-+      local_bh_disable();
-+      status = entry->next_outfn(entry, entry->next_queuenum);
-+      local_bh_enable();
-+      if (status < 0) {
-+              nf_queue_entry_release_refs(entry);
-+              kfree_skb(entry->skb);
-+              kfree(entry);
-+      }
-+
-+      rcu_read_unlock();
-+}
-+
-+static netdev_tx_t imq_dev_xmit(struct sk_buff *skb, struct net_device *dev)
-+{
-+      struct nf_queue_entry *entry = skb->nf_queue_entry;
-+
-+      skb->nf_queue_entry = NULL;
-+      dev->trans_start = jiffies;
-+
-+      dev->stats.tx_bytes += skb->len;
-+      dev->stats.tx_packets++;
-+
-+      if (entry == NULL) {
-+              /* We don't know what is going on here.. packet is queued for
-+               * imq device, but (probably) not by us.
-+               *
-+               * If this packet was not send here by imq_nf_queue(), then
-+               * skb_save_cb() was not used and skb_free() should not show:
-+               *   WARNING: IMQ: kfree_skb: skb->cb_next:..
-+               * and/or
-+               *   WARNING: IMQ: kfree_skb: skb->nf_queue_entry...
-+               *
-+               * However if this message is shown, then IMQ is somehow broken
-+               * and you should report this to linuximq.net.
-+               */
-+
-+              /* imq_dev_xmit is black hole that eats all packets, report that
-+               * we eat this packet happily and increase dropped counters.
-+               */
-+
-+              dev->stats.tx_dropped++;
-+              dev_kfree_skb(skb);
-+
-+              return NETDEV_TX_OK;
-+      }
-+
-+      skb_restore_cb(skb); /* restore skb->cb */
-+
-+      skb->imq_flags = 0;
-+      skb->destructor = NULL;
-+
-+      imq_nf_reinject(entry, NF_ACCEPT);
-+
-+      return NETDEV_TX_OK;
-+}
-+
-+static int imq_nf_queue(struct nf_queue_entry *entry, unsigned queue_num)
-+{
-+      struct net_device *dev;
-+      struct sk_buff *skb_orig, *skb, *skb_shared;
-+      struct Qdisc *q;
-+      struct netdev_queue *txq;
-+      int users, index;
-+      int retval = -EINVAL;
-+
-+      index = entry->skb->imq_flags & IMQ_F_IFMASK;
-+      if (unlikely(index > numdevs - 1)) {
-+              if (net_ratelimit())
-+                      printk(KERN_WARNING
-+                             "IMQ: invalid device specified, highest is %u\n",
-+                             numdevs - 1);
-+              retval = -EINVAL;
-+              goto out;
-+      }
-+
-+      /* check for imq device by index from cache */
-+      dev = imq_devs_cache[index];
-+      if (unlikely(!dev)) {
-+              char buf[8];
-+
-+              /* get device by name and cache result */
-+              snprintf(buf, sizeof(buf), "imq%d", index);
-+              dev = dev_get_by_name(&init_net, buf);
-+              if (!dev) {
-+                      /* not found ?!*/
-+                      BUG();
-+                      retval = -ENODEV;
-+                      goto out;
-+              }
-+
-+              imq_devs_cache[index] = dev;
-+              dev_put(dev);
-+      }
-+
-+      if (unlikely(!(dev->flags & IFF_UP))) {
-+              entry->skb->imq_flags = 0;
-+              imq_nf_reinject_lockless(entry, NF_ACCEPT);
-+              retval = 0;
-+              goto out;
-+      }
-+      dev->last_rx = jiffies;
-+
-+      skb = entry->skb;
-+      skb_orig = NULL;
-+
-+      /* skb has owner? => make clone */
-+      if (unlikely(skb->destructor)) {
-+              skb_orig = skb;
-+              skb = skb_clone(skb, GFP_ATOMIC);
-+              if (!skb) {
-+                      retval = -ENOMEM;
-+                      goto out;
-+              }
-+              entry->skb = skb;
-+      }
-+
-+      skb->nf_queue_entry = entry;
-+
-+      dev->stats.rx_bytes += skb->len;
-+      dev->stats.rx_packets++;
-+
-+      txq = dev_pick_tx(dev, skb);
-+
-+      q = rcu_dereference(txq->qdisc);
-+      if (unlikely(!q->enqueue))
-+              goto packet_not_eaten_by_imq_dev;
-+
-+      spin_lock_bh(qdisc_lock(q));
-+
-+      users = atomic_read(&skb->users);
-+
-+      skb_shared = skb_get(skb); /* increase reference count by one */
-+      skb_save_cb(skb_shared); /* backup skb->cb, as qdisc layer will
-+                                      overwrite it */
-+      qdisc_enqueue_root(skb_shared, q); /* might kfree_skb */
-+
-+      if (likely(atomic_read(&skb_shared->users) == users + 1)) {
-+              kfree_skb(skb_shared); /* decrease reference count by one */
-+
-+              skb->destructor = &imq_skb_destructor;
-+
-+              /* cloned? */
-+              if (skb_orig)
-+                      kfree_skb(skb_orig); /* free original */
-+
-+              spin_unlock_bh(qdisc_lock(q));
-+
-+              /* schedule qdisc dequeue */
-+              __netif_schedule(q);
-+
-+              retval = 0;
-+              goto out;
-+      } else {
-+              skb_restore_cb(skb_shared); /* restore skb->cb */
-+              skb->nf_queue_entry = NULL;
-+              /* qdisc dropped packet and decreased skb reference count of
-+               * skb, so we don't really want to and try refree as that would
-+               * actually destroy the skb. */
-+              spin_unlock_bh(qdisc_lock(q));
-+              goto packet_not_eaten_by_imq_dev;
-+      }
-+
-+packet_not_eaten_by_imq_dev:
-+      /* cloned? restore original */
-+      if (skb_orig) {
-+              kfree_skb(skb);
-+              entry->skb = skb_orig;
-+      }
-+      retval = -1;
-+out:
-+      return retval;
-+}
-+
-+static struct nf_queue_handler nfqh = {
-+      .name  = "imq",
-+      .outfn = imq_nf_queue,
-+};
-+
-+static unsigned int imq_nf_hook(unsigned int hook, struct sk_buff *pskb,
-+                              const struct net_device *indev,
-+                              const struct net_device *outdev,
-+                              int (*okfn)(struct sk_buff *))
-+{
-+      if (pskb->imq_flags & IMQ_F_ENQUEUE)
-+              return NF_QUEUE;
-+
-+      return NF_ACCEPT;
-+}
-+
-+static int imq_close(struct net_device *dev)
-+{
-+      netif_stop_queue(dev);
-+      return 0;
-+}
-+
-+static int imq_open(struct net_device *dev)
-+{
-+      netif_start_queue(dev);
-+      return 0;
-+}
-+
-+static const struct net_device_ops imq_netdev_ops = {
-+      .ndo_open               = imq_open,
-+      .ndo_stop               = imq_close,
-+      .ndo_start_xmit         = imq_dev_xmit,
-+      .ndo_get_stats          = imq_get_stats,
-+};
-+
-+static void imq_setup(struct net_device *dev)
-+{
-+      dev->netdev_ops         = &imq_netdev_ops;
-+      dev->type               = ARPHRD_VOID;
-+      dev->mtu                = 16000;
-+      dev->tx_queue_len       = 11000;
-+      dev->flags              = IFF_NOARP;
-+      dev->features           = NETIF_F_SG | NETIF_F_FRAGLIST |
-+                                NETIF_F_GSO | NETIF_F_HW_CSUM |
-+                                NETIF_F_HIGHDMA;
-+      dev->priv_flags         &= ~IFF_XMIT_DST_RELEASE;
-+}
-+
-+static int imq_validate(struct nlattr *tb[], struct nlattr *data[])
-+{
-+      int ret = 0;
-+
-+      if (tb[IFLA_ADDRESS]) {
-+              if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) {
-+                      ret = -EINVAL;
-+                      goto end;
-+              }
-+              if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) {
-+                      ret = -EADDRNOTAVAIL;
-+                      goto end;
-+              }
-+      }
-+      return 0;
-+end:
-+      printk(KERN_WARNING "IMQ: imq_validate failed (%d)\n", ret);
-+      return ret;
-+}
-+
-+static struct rtnl_link_ops imq_link_ops __read_mostly = {
-+      .kind           = "imq",
-+      .priv_size      = 0,
-+      .setup          = imq_setup,
-+      .validate       = imq_validate,
-+};
-+
-+static int __init imq_init_hooks(void)
-+{
-+      int err;
-+
-+      nf_register_queue_imq_handler(&nfqh);
-+
-+      err = nf_register_hook(&imq_ingress_ipv4);
-+      if (err)
-+              goto err1;
-+
-+      err = nf_register_hook(&imq_egress_ipv4);
-+      if (err)
-+              goto err2;
-+
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+      err = nf_register_hook(&imq_ingress_ipv6);
-+      if (err)
-+              goto err3;
-+
-+      err = nf_register_hook(&imq_egress_ipv6);
-+      if (err)
-+              goto err4;
-+#endif
-+
-+      return 0;
-+
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+err4:
-+      nf_unregister_hook(&imq_ingress_ipv6);
-+err3:
-+      nf_unregister_hook(&imq_egress_ipv4);
-+#endif
-+err2:
-+      nf_unregister_hook(&imq_ingress_ipv4);
-+err1:
-+      nf_unregister_queue_imq_handler();
-+      return err;
-+}
-+
-+static int __init imq_init_one(int index)
-+{
-+      struct net_device *dev;
-+      int ret;
-+
-+      dev = alloc_netdev(0, "imq%d", imq_setup);
-+      if (!dev)
-+              return -ENOMEM;
-+
-+      ret = dev_alloc_name(dev, dev->name);
-+      if (ret < 0)
-+              goto fail;
-+
-+      dev->rtnl_link_ops = &imq_link_ops;
-+      ret = register_netdevice(dev);
-+      if (ret < 0)
-+              goto fail;
-+
-+      return 0;
-+fail:
-+      free_netdev(dev);
-+      return ret;
-+}
-+
-+static int __init imq_init_devs(void)
-+{
-+      int err, i;
-+
-+      if (numdevs < 1 || numdevs > IMQ_MAX_DEVS) {
-+              printk(KERN_ERR "IMQ: numdevs has to be betweed 1 and %u\n",
-+                     IMQ_MAX_DEVS);
-+              return -EINVAL;
-+      }
-+
-+      rtnl_lock();
-+      err = __rtnl_link_register(&imq_link_ops);
-+
-+      for (i = 0; i < numdevs && !err; i++)
-+              err = imq_init_one(i);
-+
-+      if (err) {
-+              __rtnl_link_unregister(&imq_link_ops);
-+              memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
-+      }
-+      rtnl_unlock();
-+
-+      return err;
-+}
-+
-+static int __init imq_init_module(void)
-+{
-+      int err;
-+
-+#if defined(CONFIG_IMQ_NUM_DEVS)
-+      BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS > 16);
-+      BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS < 2);
-+      BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS - 1 > IMQ_F_IFMASK);
-+#endif
-+
-+      err = imq_init_devs();
-+      if (err) {
-+              printk(KERN_ERR "IMQ: Error trying imq_init_devs(net)\n");
-+              return err;
-+      }
-+
-+      err = imq_init_hooks();
-+      if (err) {
-+              printk(KERN_ERR "IMQ: Error trying imq_init_hooks()\n");
-+              rtnl_link_unregister(&imq_link_ops);
-+              memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
-+              return err;
-+      }
-+
-+      printk(KERN_INFO "IMQ driver loaded successfully.\n");
-+
-+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+      printk(KERN_INFO "\tHooking IMQ before NAT on PREROUTING.\n");
-+#else
-+      printk(KERN_INFO "\tHooking IMQ after NAT on PREROUTING.\n");
-+#endif
-+#if defined(CONFIG_IMQ_BEHAVIOR_AB) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+      printk(KERN_INFO "\tHooking IMQ before NAT on POSTROUTING.\n");
-+#else
-+      printk(KERN_INFO "\tHooking IMQ after NAT on POSTROUTING.\n");
-+#endif
-+
-+      return 0;
-+}
-+
-+static void __exit imq_unhook(void)
-+{
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+      nf_unregister_hook(&imq_ingress_ipv6);
-+      nf_unregister_hook(&imq_egress_ipv6);
-+#endif
-+      nf_unregister_hook(&imq_ingress_ipv4);
-+      nf_unregister_hook(&imq_egress_ipv4);
-+
-+      nf_unregister_queue_imq_handler();
-+}
-+
-+static void __exit imq_cleanup_devs(void)
-+{
-+      rtnl_link_unregister(&imq_link_ops);
-+      memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
-+}
-+
-+static void __exit imq_exit_module(void)
-+{
-+      imq_unhook();
-+      imq_cleanup_devs();
-+      printk(KERN_INFO "IMQ driver unloaded successfully.\n");
-+}
-+
-+module_init(imq_init_module);
-+module_exit(imq_exit_module);
-+
-+module_param(numdevs, int, 0);
-+MODULE_PARM_DESC(numdevs, "number of IMQ devices (how many imq* devices will "
-+                      "be created)");
-+MODULE_AUTHOR("http://www.linuximq.net");
-+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See "
-+                      "http://www.linuximq.net/ for more information.");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS_RTNL_LINK("imq");
-+
---- a/drivers/net/Kconfig
-+++ b/drivers/net/Kconfig
-@@ -124,6 +124,129 @@ config EQUALIZER
-         To compile this driver as a module, choose M here: the module
-         will be called eql.  If unsure, say N.
-+config IMQ
-+      tristate "IMQ (intermediate queueing device) support"
-+      depends on NETDEVICES && NETFILTER
-+      ---help---
-+        The IMQ device(s) is used as placeholder for QoS queueing
-+        disciplines. Every packet entering/leaving the IP stack can be
-+        directed through the IMQ device where it's enqueued/dequeued to the
-+        attached qdisc. This allows you to treat network devices as classes
-+        and distribute bandwidth among them. Iptables is used to specify
-+        through which IMQ device, if any, packets travel.
-+
-+        More information at: http://www.linuximq.net/
-+
-+        To compile this driver as a module, choose M here: the module
-+        will be called imq.  If unsure, say N.
-+
-+choice
-+      prompt "IMQ behavior (PRE/POSTROUTING)"
-+      depends on IMQ
-+      default IMQ_BEHAVIOR_AB
-+      help
-+
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              IMQ can work in any of the following ways:
-+
-+                  PREROUTING   |      POSTROUTING
-+              -----------------|-------------------
-+              #1  After NAT    |      After NAT
-+              #2  After NAT    |      Before NAT
-+              #3  Before NAT   |      After NAT
-+              #4  Before NAT   |      Before NAT
-+
-+              The default behavior is to hook before NAT on PREROUTING
-+              and after NAT on POSTROUTING (#3).
-+
-+              This settings are specially usefull when trying to use IMQ
-+              to shape NATed clients.
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_AA
-+      bool "IMQ AA"
-+      help
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              Choosing this option will make IMQ hook like this:
-+
-+              PREROUTING:   After NAT
-+              POSTROUTING:  After NAT
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_AB
-+      bool "IMQ AB"
-+      help
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              Choosing this option will make IMQ hook like this:
-+
-+              PREROUTING:   After NAT
-+              POSTROUTING:  Before NAT
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_BA
-+      bool "IMQ BA"
-+      help
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              Choosing this option will make IMQ hook like this:
-+
-+              PREROUTING:   Before NAT
-+              POSTROUTING:  After NAT
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_BB
-+      bool "IMQ BB"
-+      help
-+              This settings defines how IMQ behaves in respect to its
-+              hooking in PREROUTING and POSTROUTING.
-+
-+              Choosing this option will make IMQ hook like this:
-+
-+              PREROUTING:   Before NAT
-+              POSTROUTING:  Before NAT
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
-+endchoice
-+
-+config IMQ_NUM_DEVS
-+
-+      int "Number of IMQ devices"
-+      range 2 16
-+      depends on IMQ
-+      default "16"
-+      help
-+
-+              This settings defines how many IMQ devices will be
-+              created.
-+
-+              The default value is 16.
-+
-+              More information can be found at: www.linuximq.net
-+
-+              If not sure leave the default settings alone.
-+
- config TUN
-       tristate "Universal TUN/TAP device driver support"
-       select CRC32
---- a/drivers/net/Makefile
-+++ b/drivers/net/Makefile
-@@ -173,6 +173,7 @@ obj-$(CONFIG_SLHC) += slhc.o
- obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o
- obj-$(CONFIG_DUMMY) += dummy.o
-+obj-$(CONFIG_IMQ) += imq.o
- obj-$(CONFIG_IFB) += ifb.o
- obj-$(CONFIG_MACVLAN) += macvlan.o
- obj-$(CONFIG_MACVTAP) += macvtap.o
---- /dev/null
-+++ b/include/linux/imq.h
-@@ -0,0 +1,13 @@
-+#ifndef _IMQ_H
-+#define _IMQ_H
-+
-+/* IFMASK (16 device indexes, 0 to 15) and flag(s) fit in 5 bits */
-+#define IMQ_F_BITS    5
-+
-+#define IMQ_F_IFMASK  0x0f
-+#define IMQ_F_ENQUEUE 0x10
-+
-+#define IMQ_MAX_DEVS  (IMQ_F_IFMASK + 1)
-+
-+#endif /* _IMQ_H */
-+
---- a/include/linux/netdevice.h
-+++ b/include/linux/netdevice.h
-@@ -1374,6 +1374,7 @@ extern int               dev_alloc_name(struct net_de
- extern int            dev_open(struct net_device *dev);
- extern int            dev_close(struct net_device *dev);
- extern void           dev_disable_lro(struct net_device *dev);
-+extern struct netdev_queue *dev_pick_tx(struct net_device *dev, struct sk_buff *skb);
- extern int            dev_queue_xmit(struct sk_buff *skb);
- extern int            register_netdevice(struct net_device *dev);
- extern void           unregister_netdevice_queue(struct net_device *dev,
---- /dev/null
-+++ b/include/linux/netfilter/xt_IMQ.h
-@@ -0,0 +1,9 @@
-+#ifndef _XT_IMQ_H
-+#define _XT_IMQ_H
-+
-+struct xt_imq_info {
-+      unsigned int todev;     /* target imq device */
-+};
-+
-+#endif /* _XT_IMQ_H */
-+
---- /dev/null
-+++ b/include/linux/netfilter_ipv4/ipt_IMQ.h
-@@ -0,0 +1,10 @@
-+#ifndef _IPT_IMQ_H
-+#define _IPT_IMQ_H
-+
-+/* Backwards compatibility for old userspace */
-+#include <linux/netfilter/xt_IMQ.h>
-+
-+#define ipt_imq_info xt_imq_info
-+
-+#endif /* _IPT_IMQ_H */
-+
---- /dev/null
-+++ b/include/linux/netfilter_ipv6/ip6t_IMQ.h
-@@ -0,0 +1,10 @@
-+#ifndef _IP6T_IMQ_H
-+#define _IP6T_IMQ_H
-+
-+/* Backwards compatibility for old userspace */
-+#include <linux/netfilter/xt_IMQ.h>
-+
-+#define ip6t_imq_info xt_imq_info
-+
-+#endif /* _IP6T_IMQ_H */
-+
---- a/include/linux/skbuff.h
-+++ b/include/linux/skbuff.h
-@@ -29,6 +29,9 @@
- #include <linux/rcupdate.h>
- #include <linux/dmaengine.h>
- #include <linux/hrtimer.h>
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+#include <linux/imq.h>
-+#endif
- /* Don't change this without changing skb_csum_unnecessary! */
- #define CHECKSUM_NONE 0
-@@ -333,6 +336,9 @@ struct sk_buff {
-        * first. This is owned by whoever has the skb queued ATM.
-        */
-       char                    cb[48] __aligned(8);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      void                    *cb_next;
-+#endif
-       unsigned long           _skb_refdst;
- #ifdef CONFIG_XFRM
-@@ -371,6 +377,9 @@ struct sk_buff {
- #ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
-       struct sk_buff          *nfct_reasm;
- #endif
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      struct nf_queue_entry   *nf_queue_entry;
-+#endif
- #ifdef CONFIG_BRIDGE_NETFILTER
-       struct nf_bridge_info   *nf_bridge;
- #endif
-@@ -398,6 +407,10 @@ struct sk_buff {
-       /* 0/13 bit hole */
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      __u8                    imq_flags:IMQ_F_BITS;
-+#endif
-+
- #ifdef CONFIG_NET_DMA
-       dma_cookie_t            dma_cookie;
- #endif
-@@ -484,6 +497,12 @@ static inline struct rtable *skb_rtable(
-       return (struct rtable *)skb_dst(skb);
- }
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+extern int skb_save_cb(struct sk_buff *skb);
-+extern int skb_restore_cb(struct sk_buff *skb);
-+#endif
-+
- extern void kfree_skb(struct sk_buff *skb);
- extern void consume_skb(struct sk_buff *skb);
- extern void          __kfree_skb(struct sk_buff *skb);
-@@ -2117,6 +2136,10 @@ static inline void __nf_copy(struct sk_b
-       dst->nfct_reasm = src->nfct_reasm;
-       nf_conntrack_get_reasm(src->nfct_reasm);
- #endif
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      dst->imq_flags = src->imq_flags;
-+      dst->nf_queue_entry = src->nf_queue_entry;
-+#endif
- #ifdef CONFIG_BRIDGE_NETFILTER
-       dst->nf_bridge  = src->nf_bridge;
-       nf_bridge_get(src->nf_bridge);
---- a/include/net/netfilter/nf_queue.h
-+++ b/include/net/netfilter/nf_queue.h
-@@ -13,6 +13,12 @@ struct nf_queue_entry {
-       struct net_device       *indev;
-       struct net_device       *outdev;
-       int                     (*okfn)(struct sk_buff *);
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      int                     (*next_outfn)(struct nf_queue_entry *entry,
-+                                            unsigned int queuenum);
-+      unsigned int            next_queuenum;
-+#endif
- };
- #define nf_queue_entry_reroute(x) ((void *)x + sizeof(struct nf_queue_entry))
-@@ -30,5 +36,11 @@ extern int nf_unregister_queue_handler(u
-                                      const struct nf_queue_handler *qh);
- extern void nf_unregister_queue_handlers(const struct nf_queue_handler *qh);
- extern void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
-+extern void nf_queue_entry_release_refs(struct nf_queue_entry *entry);
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+extern void nf_register_queue_imq_handler(const struct nf_queue_handler *qh);
-+extern void nf_unregister_queue_imq_handler(void);
-+#endif
- #endif /* _NF_QUEUE_H */
---- a/net/core/dev.c
-+++ b/net/core/dev.c
-@@ -98,6 +98,9 @@
- #include <net/net_namespace.h>
- #include <net/sock.h>
- #include <linux/rtnetlink.h>
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+#include <linux/imq.h>
-+#endif
- #include <linux/proc_fs.h>
- #include <linux/seq_file.h>
- #include <linux/stat.h>
-@@ -2068,7 +2071,11 @@ int dev_hard_start_xmit(struct sk_buff *
-               if (dev->priv_flags & IFF_XMIT_DST_RELEASE)
-                       skb_dst_drop(skb);
--              if (!list_empty(&ptype_all))
-+              if (!list_empty(&ptype_all)
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+                      && !(skb->imq_flags & IMQ_F_ENQUEUE)
-+#endif
-+                 )
-                       dev_queue_xmit_nit(skb, dev);
-               skb_orphan_try(skb);
-@@ -2230,8 +2237,7 @@ static inline int get_xps_queue(struct n
- #endif
- }
--static struct netdev_queue *dev_pick_tx(struct net_device *dev,
--                                      struct sk_buff *skb)
-+struct netdev_queue *dev_pick_tx(struct net_device *dev, struct sk_buff *skb)
- {
-       int queue_index;
-       const struct net_device_ops *ops = dev->netdev_ops;
-@@ -2266,6 +2272,7 @@ static struct netdev_queue *dev_pick_tx(
-       skb_set_queue_mapping(skb, queue_index);
-       return netdev_get_tx_queue(dev, queue_index);
- }
-+EXPORT_SYMBOL(dev_pick_tx);
- static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
-                                struct net_device *dev,
---- a/net/core/skbuff.c
-+++ b/net/core/skbuff.c
-@@ -72,6 +72,9 @@
- static struct kmem_cache *skbuff_head_cache __read_mostly;
- static struct kmem_cache *skbuff_fclone_cache __read_mostly;
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+static struct kmem_cache *skbuff_cb_store_cache __read_mostly;
-+#endif
- static void sock_pipe_buf_release(struct pipe_inode_info *pipe,
-                                 struct pipe_buffer *buf)
-@@ -91,6 +94,83 @@ static int sock_pipe_buf_steal(struct pi
-       return 1;
- }
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+/* Control buffer save/restore for IMQ devices */
-+struct skb_cb_table {
-+      void                    *cb_next;
-+      atomic_t                refcnt;
-+      char                    cb[48];
-+};
-+
-+static DEFINE_SPINLOCK(skb_cb_store_lock);
-+
-+int skb_save_cb(struct sk_buff *skb)
-+{
-+      struct skb_cb_table *next;
-+
-+      next = kmem_cache_alloc(skbuff_cb_store_cache, GFP_ATOMIC);
-+      if (!next)
-+              return -ENOMEM;
-+
-+      BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb));
-+
-+      memcpy(next->cb, skb->cb, sizeof(skb->cb));
-+      next->cb_next = skb->cb_next;
-+
-+      atomic_set(&next->refcnt, 1);
-+
-+      skb->cb_next = next;
-+      return 0;
-+}
-+EXPORT_SYMBOL(skb_save_cb);
-+
-+int skb_restore_cb(struct sk_buff *skb)
-+{
-+      struct skb_cb_table *next;
-+
-+      if (!skb->cb_next)
-+              return 0;
-+
-+      next = skb->cb_next;
-+
-+      BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb));
-+
-+      memcpy(skb->cb, next->cb, sizeof(skb->cb));
-+      skb->cb_next = next->cb_next;
-+
-+      spin_lock(&skb_cb_store_lock);
-+
-+      if (atomic_dec_and_test(&next->refcnt)) {
-+              kmem_cache_free(skbuff_cb_store_cache, next);
-+      }
-+
-+      spin_unlock(&skb_cb_store_lock);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL(skb_restore_cb);
-+
-+static void skb_copy_stored_cb(struct sk_buff *new, const struct sk_buff *__old)
-+{
-+      struct skb_cb_table *next;
-+      struct sk_buff *old;
-+
-+      if (!__old->cb_next) {
-+              new->cb_next = NULL;
-+              return;
-+      }
-+
-+      spin_lock(&skb_cb_store_lock);
-+
-+      old = (struct sk_buff *)__old;
-+
-+      next = old->cb_next;
-+      atomic_inc(&next->refcnt);
-+      new->cb_next = next;
-+
-+      spin_unlock(&skb_cb_store_lock);
-+}
-+#endif
- /* Pipe buffer operations for a socket. */
- static const struct pipe_buf_operations sock_pipe_buf_ops = {
-@@ -378,6 +458,26 @@ static void skb_release_head_state(struc
-               WARN_ON(in_irq());
-               skb->destructor(skb);
-       }
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      /* This should not happen. When it does, avoid memleak by restoring
-+      the chain of cb-backups. */
-+      while(skb->cb_next != NULL) {
-+              if (net_ratelimit())
-+                      printk(KERN_WARNING "IMQ: kfree_skb: skb->cb_next: "
-+                              "%08x\n", (unsigned int)skb->cb_next);
-+
-+              skb_restore_cb(skb);
-+      }
-+      /* This should not happen either, nf_queue_entry is nullified in
-+       * imq_dev_xmit(). If we have non-NULL nf_queue_entry then we are
-+       * leaking entry pointers, maybe memory. We don't know if this is
-+       * pointer to already freed memory, or should this be freed.
-+       * If this happens we need to add refcounting, etc for nf_queue_entry.
-+       */
-+      if (skb->nf_queue_entry && net_ratelimit())
-+              printk(KERN_WARNING
-+                              "IMQ: kfree_skb: skb->nf_queue_entry != NULL");
-+#endif
- #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
-       nf_conntrack_put(skb->nfct);
- #endif
-@@ -516,6 +616,9 @@ static void __copy_skb_header(struct sk_
-       new->sp                 = secpath_get(old->sp);
- #endif
-       memcpy(new->cb, old->cb, sizeof(old->cb));
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      skb_copy_stored_cb(new, old);
-+#endif
-       new->csum               = old->csum;
-       new->local_df           = old->local_df;
-       new->pkt_type           = old->pkt_type;
-@@ -2779,6 +2882,13 @@ void __init skb_init(void)
-                                               0,
-                                               SLAB_HWCACHE_ALIGN|SLAB_PANIC,
-                                               NULL);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      skbuff_cb_store_cache = kmem_cache_create("skbuff_cb_store_cache",
-+                                                sizeof(struct skb_cb_table),
-+                                                0,
-+                                                SLAB_HWCACHE_ALIGN|SLAB_PANIC,
-+                                                NULL);
-+#endif
- }
- /**
---- a/net/netfilter/Kconfig
-+++ b/net/netfilter/Kconfig
-@@ -455,6 +455,18 @@ config NETFILTER_XT_TARGET_LED
-         For more information on the LEDs available on your system, see
-         Documentation/leds-class.txt
-+config NETFILTER_XT_TARGET_IMQ
-+        tristate '"IMQ" target support'
-+      depends on NETFILTER_XTABLES
-+      depends on IP_NF_MANGLE || IP6_NF_MANGLE
-+      select IMQ
-+      default m if NETFILTER_ADVANCED=n
-+        help
-+          This option adds a `IMQ' target which is used to specify if and
-+          to which imq device packets should get enqueued/dequeued.
-+
-+          To compile it as a module, choose M here.  If unsure, say N.
-+
- config NETFILTER_XT_TARGET_MARK
-       tristate '"MARK" target support'
-       depends on NETFILTER_ADVANCED
---- a/net/netfilter/Makefile
-+++ b/net/netfilter/Makefile
-@@ -51,6 +51,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSEC
- obj-$(CONFIG_NETFILTER_XT_TARGET_CT) += xt_CT.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o
-+obj-$(CONFIG_NETFILTER_XT_TARGET_IMQ) += xt_IMQ.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
---- a/net/netfilter/nf_queue.c
-+++ b/net/netfilter/nf_queue.c
-@@ -22,6 +22,26 @@ static const struct nf_queue_handler __r
- static DEFINE_MUTEX(queue_handler_mutex);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+static const struct nf_queue_handler *queue_imq_handler;
-+
-+void nf_register_queue_imq_handler(const struct nf_queue_handler *qh)
-+{
-+      mutex_lock(&queue_handler_mutex);
-+      rcu_assign_pointer(queue_imq_handler, qh);
-+      mutex_unlock(&queue_handler_mutex);
-+}
-+EXPORT_SYMBOL(nf_register_queue_imq_handler);
-+
-+void nf_unregister_queue_imq_handler(void)
-+{
-+      mutex_lock(&queue_handler_mutex);
-+      rcu_assign_pointer(queue_imq_handler, NULL);
-+      mutex_unlock(&queue_handler_mutex);
-+}
-+EXPORT_SYMBOL(nf_unregister_queue_imq_handler);
-+#endif
-+
- /* return EBUSY when somebody else is registered, return EEXIST if the
-  * same handler is registered, return 0 in case of success. */
- int nf_register_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh)
-@@ -82,7 +102,7 @@ void nf_unregister_queue_handlers(const
- }
- EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers);
--static void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
-+void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
- {
-       /* Release those devices we held, or Alexey will kill me. */
-       if (entry->indev)
-@@ -102,6 +122,7 @@ static void nf_queue_entry_release_refs(
-       /* Drop reference to owner of hook which queued us. */
-       module_put(entry->elem->owner);
- }
-+EXPORT_SYMBOL_GPL(nf_queue_entry_release_refs);
- /*
-  * Any packet that leaves via this function must come back
-@@ -123,12 +144,26 @@ static int __nf_queue(struct sk_buff *sk
- #endif
-       const struct nf_afinfo *afinfo;
-       const struct nf_queue_handler *qh;
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      const struct nf_queue_handler *qih = NULL;
-+#endif
-       /* QUEUE == DROP if noone is waiting, to be safe. */
-       rcu_read_lock();
-       qh = rcu_dereference(queue_handler[pf]);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+      if (pf == PF_INET || pf == PF_INET6)
-+#else
-+      if (pf == PF_INET)
-+#endif
-+              qih = rcu_dereference(queue_imq_handler);
-+
-+      if (!qh && !qih)
-+#else /* !IMQ */
-       if (!qh)
-+#endif
-               goto err_unlock;
-       afinfo = nf_get_afinfo(pf);
-@@ -147,6 +182,10 @@ static int __nf_queue(struct sk_buff *sk
-               .indev  = indev,
-               .outdev = outdev,
-               .okfn   = okfn,
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+              .next_outfn = qh ? qh->outfn : NULL,
-+              .next_queuenum = queuenum,
-+#endif
-       };
-       /* If it's going away, ignore hook. */
-@@ -173,8 +212,19 @@ static int __nf_queue(struct sk_buff *sk
- #endif
-       skb_dst_force(skb);
-       afinfo->saveroute(skb, entry);
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+      if (qih) {
-+              status = qih->outfn(entry, queuenum);
-+              goto imq_skip_queue;
-+      }
-+#endif
-+
-       status = qh->outfn(entry, queuenum);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+imq_skip_queue:
-+#endif
-       rcu_read_unlock();
-       if (status < 0) {
---- /dev/null
-+++ b/net/netfilter/xt_IMQ.c
-@@ -0,0 +1,73 @@
-+/*
-+ * This target marks packets to be enqueued to an imq device
-+ */
-+#include <linux/module.h>
-+#include <linux/skbuff.h>
-+#include <linux/netfilter/x_tables.h>
-+#include <linux/netfilter/xt_IMQ.h>
-+#include <linux/imq.h>
-+
-+static unsigned int imq_target(struct sk_buff *pskb,
-+                              const struct xt_action_param *par)
-+{
-+      const struct xt_imq_info *mr = par->targinfo;
-+
-+      pskb->imq_flags = (mr->todev & IMQ_F_IFMASK) | IMQ_F_ENQUEUE;
-+
-+      return XT_CONTINUE;
-+}
-+
-+static int imq_checkentry(const struct xt_tgchk_param *par)
-+{
-+      struct xt_imq_info *mr = par->targinfo;
-+
-+      if (mr->todev > IMQ_MAX_DEVS - 1) {
-+              printk(KERN_WARNING
-+                     "IMQ: invalid device specified, highest is %u\n",
-+                     IMQ_MAX_DEVS - 1);
-+              return -EINVAL;
-+      }
-+
-+      return 0;
-+}
-+
-+static struct xt_target xt_imq_reg[] __read_mostly = {
-+      {
-+              .name           = "IMQ",
-+              .family         = AF_INET,
-+              .checkentry     = imq_checkentry,
-+              .target         = imq_target,
-+              .targetsize     = sizeof(struct xt_imq_info),
-+              .table          = "mangle",
-+              .me             = THIS_MODULE
-+      },
-+      {
-+              .name           = "IMQ",
-+              .family         = AF_INET6,
-+              .checkentry     = imq_checkentry,
-+              .target         = imq_target,
-+              .targetsize     = sizeof(struct xt_imq_info),
-+              .table          = "mangle",
-+              .me             = THIS_MODULE
-+      },
-+};
-+
-+static int __init imq_init(void)
-+{
-+      return xt_register_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg));
-+}
-+
-+static void __exit imq_fini(void)
-+{
-+      xt_unregister_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg));
-+}
-+
-+module_init(imq_init);
-+module_exit(imq_fini);
-+
-+MODULE_AUTHOR("http://www.linuximq.net");
-+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information.");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS("ipt_IMQ");
-+MODULE_ALIAS("ip6t_IMQ");
-+