get rid of linux 2.6.29
SVN-Revision: 16883
This commit is contained in:
		| @@ -23,7 +23,7 @@ JFFS2OPTS     :=  --pad --big-endian --squash | ||||
| SQUASHFS_OPTS :=  -be | ||||
| endif | ||||
|  | ||||
| ifneq ($(CONFIG_LINUX_2_6_29)$(CONFIG_LINUX_2_6_30),) | ||||
| ifneq ($(CONFIG_LINUX_2_6_30),) | ||||
| USE_SQUASHFS4 := y | ||||
| endif | ||||
|  | ||||
|   | ||||
| @@ -25,9 +25,6 @@ endif | ||||
| ifeq ($(LINUX_VERSION),2.6.28.10) | ||||
|   LINUX_KERNEL_MD5SUM:=c4efb2c494d749cb5de274f8ae41c3fa | ||||
| endif | ||||
| ifeq ($(LINUX_VERSION),2.6.29.6) | ||||
|   LINUX_KERNEL_MD5SUM:=7cd24826fd3c7b0f83d9f662731a7865 | ||||
| endif | ||||
| ifeq ($(LINUX_VERSION),2.6.30.1) | ||||
|   LINUX_KERNEL_MD5SUM:=7da2e2e31f1c00f2673d2dc50de76b33 | ||||
| endif | ||||
|   | ||||
| @@ -45,7 +45,7 @@ endef | ||||
| define KernelPackage/hostap | ||||
| $(call KernelPackage/hostap/Default) | ||||
|   TITLE:=Host AP support for Prism2/2.5/3 | ||||
|   DEPENDS:=@PCI_SUPPORT||PCMCIA_SUPPORT +!LINUX_2_6_29&&!LINUX_2_6_30:kmod-ieee80211 +LINUX_2_6_29||LINUX_2_6_30:kmod-lib80211 +wireless-tools | ||||
|   DEPENDS:=@PCI_SUPPORT||PCMCIA_SUPPORT +!LINUX_2_6_30:kmod-ieee80211 +LINUX_2_6_30:kmod-lib80211 +wireless-tools | ||||
|   KCONFIG:=CONFIG_HOSTAP CONFIG_HOSTAP_FIRMWARE=y CONFIG_HOSTAP_FIRMWARE_NVRAM=y | ||||
|   PROVIDES:=kmod-hostap | ||||
| endef | ||||
|   | ||||
| @@ -289,7 +289,7 @@ define KernelPackage/tg3 | ||||
|   TITLE:=Broadcom Tigon3 Gigabit Ethernet | ||||
|   FILES:=$(LINUX_DIR)/drivers/net/tg3.$(LINUX_KMOD_SUFFIX) | ||||
|   KCONFIG:=CONFIG_TIGON3 | ||||
|   DEPENDS:=@LINUX_2_6 +LINUX_2_6_27||LINUX_2_6_28||LINUX_2_6_29||LINUX_2_6_30:kmod-libphy | ||||
|   DEPENDS:=@LINUX_2_6 +LINUX_2_6_27||LINUX_2_6_28||LINUX_2_6_30:kmod-libphy | ||||
|   SUBMENU:=$(NETWORK_DEVICES_MENU) | ||||
|   AUTOLOAD:=$(call AutoLoad,50,tg3) | ||||
| endef | ||||
|   | ||||
| @@ -49,7 +49,7 @@ $(eval $(call KernelPackage,ieee80211)) | ||||
| define KernelPackage/lib80211 | ||||
|   SUBMENU:=$(WIRELESS_MENU) | ||||
|   TITLE:=802.11 Networking stack | ||||
|   DEPENDS:=@LINUX_2_6_29||LINUX_2_6_30 | ||||
|   DEPENDS:=@LINUX_2_6_30 | ||||
|   KCONFIG:= \ | ||||
| 	CONFIG_LIB80211 \ | ||||
| 	CONFIG_LIB80211_CRYPT_WEP \ | ||||
| @@ -87,7 +87,7 @@ endif | ||||
| define KernelPackage/net-libipw | ||||
|   SUBMENU:=$(WIRELESS_MENU) | ||||
|   TITLE:=libipw for ipw2100 and ipw2200 | ||||
|   DEPENDS:=@PCI_SUPPORT +kmod-crypto-arc4 +kmod-crypto-aes +kmod-crypto-michael-mic +kmod-lib80211 @LINUX_2_6_29||LINUX_2_6_30 | ||||
|   DEPENDS:=@PCI_SUPPORT +kmod-crypto-arc4 +kmod-crypto-aes +kmod-crypto-michael-mic +kmod-lib80211 @LINUX_2_6_30 | ||||
|   KCONFIG:=CONFIG_LIBIPW | ||||
|   FILES:=$(LINUX_DIR)/drivers/net/wireless/$(IPW_DIR)libipw.$(LINUX_KMOD_SUFFIX) | ||||
|   AUTOLOAD:=$(call AutoLoad,49,libipw) | ||||
| @@ -103,7 +103,7 @@ $(eval $(call KernelPackage,net-libipw)) | ||||
| define KernelPackage/net-ipw2100 | ||||
|   SUBMENU:=$(WIRELESS_MENU) | ||||
|   TITLE:=Intel IPW2100 driver | ||||
|   DEPENDS:=@PCI_SUPPORT +!LINUX_2_6_29&&!LINUX_2_6_30:kmod-ieee80211 +LINUX_2_6_29||LINUX_2_6_30:kmod-net-libipw | ||||
|   DEPENDS:=@PCI_SUPPORT +!LINUX_2_6_30:kmod-ieee80211 +LINUX_2_6_30:kmod-net-libipw | ||||
|   KCONFIG:=CONFIG_IPW2100 | ||||
|   FILES:=$(LINUX_DIR)/drivers/net/wireless/$(IPW_DIR)ipw2100.$(LINUX_KMOD_SUFFIX) | ||||
|   AUTOLOAD:=$(call AutoLoad,50,ipw2100) | ||||
| @@ -121,7 +121,7 @@ $(eval $(call KernelPackage,net-ipw2100)) | ||||
| define KernelPackage/net-ipw2200 | ||||
|   SUBMENU:=$(WIRELESS_MENU) | ||||
|   TITLE:=Intel IPW2200 driver | ||||
|   DEPENDS:=@PCI_SUPPORT +!LINUX_2_6_29&&!LINUX_2_6_30:kmod-ieee80211 +LINUX_2_6_29||LINUX_2_6_30:kmod-net-libipw | ||||
|   DEPENDS:=@PCI_SUPPORT +!LINUX_2_6_30:kmod-ieee80211 +LINUX_2_6_30:kmod-net-libipw | ||||
|   KCONFIG:=CONFIG_IPW2200 | ||||
|   FILES:=$(LINUX_DIR)/drivers/net/wireless/$(IPW_DIR)ipw2200.$(LINUX_KMOD_SUFFIX) | ||||
|   AUTOLOAD:=$(call AutoLoad,50,ipw2200) | ||||
|   | ||||
| @@ -1,219 +0,0 @@ | ||||
| CONFIG_32BIT=y | ||||
| # CONFIG_64BIT is not set | ||||
| CONFIG_ADM6996_PHY=y | ||||
| CONFIG_AG71XX=y | ||||
| CONFIG_AG71XX_AR8216_SUPPORT=y | ||||
| # CONFIG_AG71XX_DEBUG is not set | ||||
| # CONFIG_AR71XX_EARLY_SERIAL is not set | ||||
| CONFIG_AR71XX_MACH_AP81=y | ||||
| CONFIG_AR71XX_MACH_AP83=y | ||||
| CONFIG_AR71XX_MACH_AW_NR580=y | ||||
| CONFIG_AR71XX_MACH_GENERIC=y | ||||
| CONFIG_AR71XX_MACH_MZK_W04NU=y | ||||
| CONFIG_AR71XX_MACH_MZK_W300NH=y | ||||
| CONFIG_AR71XX_MACH_PB42=y | ||||
| CONFIG_AR71XX_MACH_PB44=y | ||||
| CONFIG_AR71XX_MACH_RB_4XX=y | ||||
| CONFIG_AR71XX_MACH_TEW_632BRP=y | ||||
| CONFIG_AR71XX_MACH_TL_WR741ND=y | ||||
| CONFIG_AR71XX_MACH_TL_WR941ND=y | ||||
| CONFIG_AR71XX_MACH_UBNT=y | ||||
| CONFIG_AR71XX_MACH_WNR2000=y | ||||
| CONFIG_AR71XX_MACH_WP543=y | ||||
| CONFIG_AR71XX_MACH_WRT160NL=y | ||||
| CONFIG_AR71XX_MACH_WRT400N=y | ||||
| CONFIG_AR71XX_WDT=y | ||||
| # CONFIG_ARCH_HAS_ILOG2_U32 is not set | ||||
| # CONFIG_ARCH_HAS_ILOG2_U64 is not set | ||||
| CONFIG_ARCH_POPULATES_NODE_MAP=y | ||||
| CONFIG_ARCH_REQUIRE_GPIOLIB=y | ||||
| # CONFIG_ARCH_SUPPORTS_MSI is not set | ||||
| CONFIG_ARCH_SUPPORTS_OPROFILE=y | ||||
| CONFIG_ARCH_SUSPEND_POSSIBLE=y | ||||
| CONFIG_ATHEROS_AR71XX=y | ||||
| CONFIG_BASE_SMALL=0 | ||||
| # CONFIG_BCM47XX is not set | ||||
| CONFIG_BITREVERSE=y | ||||
| # CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set | ||||
| # CONFIG_CAVIUM_OCTEON_SIMULATOR is not set | ||||
| CONFIG_CEVT_R4K=y | ||||
| CONFIG_CEVT_R4K_LIB=y | ||||
| CONFIG_CMDLINE="rootfstype=squashfs,yaffs,jffs2 noinitrd console=ttyS0,115200" | ||||
| CONFIG_CPU_BIG_ENDIAN=y | ||||
| # CONFIG_CPU_CAVIUM_OCTEON is not set | ||||
| CONFIG_CPU_HAS_LLSC=y | ||||
| CONFIG_CPU_HAS_PREFETCH=y | ||||
| CONFIG_CPU_HAS_SYNC=y | ||||
| # CONFIG_CPU_LITTLE_ENDIAN is not set | ||||
| # CONFIG_CPU_LOONGSON2 is not set | ||||
| CONFIG_CPU_MIPS32=y | ||||
| # CONFIG_CPU_MIPS32_R1 is not set | ||||
| CONFIG_CPU_MIPS32_R2=y | ||||
| # CONFIG_CPU_MIPS64_R1 is not set | ||||
| # CONFIG_CPU_MIPS64_R2 is not set | ||||
| CONFIG_CPU_MIPSR2=y | ||||
| # CONFIG_CPU_NEVADA is not set | ||||
| # CONFIG_CPU_R10000 is not set | ||||
| # CONFIG_CPU_R3000 is not set | ||||
| # CONFIG_CPU_R4300 is not set | ||||
| # CONFIG_CPU_R4X00 is not set | ||||
| # CONFIG_CPU_R5000 is not set | ||||
| # CONFIG_CPU_R5432 is not set | ||||
| # CONFIG_CPU_R5500 is not set | ||||
| # CONFIG_CPU_R6000 is not set | ||||
| # CONFIG_CPU_R8000 is not set | ||||
| # CONFIG_CPU_RM7000 is not set | ||||
| # CONFIG_CPU_RM9000 is not set | ||||
| # CONFIG_CPU_SB1 is not set | ||||
| CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y | ||||
| CONFIG_CPU_SUPPORTS_HIGHMEM=y | ||||
| # CONFIG_CPU_TX39XX is not set | ||||
| # CONFIG_CPU_TX49XX is not set | ||||
| # CONFIG_CPU_VR41XX is not set | ||||
| CONFIG_CSRC_R4K=y | ||||
| CONFIG_CSRC_R4K_LIB=y | ||||
| # CONFIG_DCB is not set | ||||
| CONFIG_DEVPORT=y | ||||
| # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set | ||||
| # CONFIG_DM9000 is not set | ||||
| CONFIG_DMA_NEED_PCI_MAP_STATE=y | ||||
| CONFIG_DMA_NONCOHERENT=y | ||||
| CONFIG_EARLY_PRINTK=y | ||||
| CONFIG_GENERIC_CLOCKEVENTS=y | ||||
| CONFIG_GENERIC_CLOCKEVENTS_BUILD=y | ||||
| CONFIG_GENERIC_CMOS_UPDATE=y | ||||
| CONFIG_GENERIC_FIND_LAST_BIT=y | ||||
| CONFIG_GENERIC_FIND_NEXT_BIT=y | ||||
| CONFIG_GENERIC_GPIO=y | ||||
| # CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set | ||||
| CONFIG_GPIOLIB=y | ||||
| CONFIG_GPIO_PCF857X=y | ||||
| CONFIG_GPIO_SYSFS=y | ||||
| CONFIG_HARDWARE_WATCHPOINTS=y | ||||
| CONFIG_HAS_DMA=y | ||||
| CONFIG_HAS_IOMEM=y | ||||
| CONFIG_HAS_IOPORT=y | ||||
| CONFIG_HAVE_ARCH_KGDB=y | ||||
| # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set | ||||
| CONFIG_HAVE_IDE=y | ||||
| CONFIG_HAVE_OPROFILE=y | ||||
| CONFIG_HW_HAS_PCI=y | ||||
| # CONFIG_HW_RANDOM is not set | ||||
| CONFIG_I2C=y | ||||
| CONFIG_I2C_ALGOBIT=y | ||||
| CONFIG_I2C_BOARDINFO=y | ||||
| CONFIG_I2C_GPIO=y | ||||
| CONFIG_ICPLUS_PHY=y | ||||
| CONFIG_INITRAMFS_ROOT_GID=0 | ||||
| CONFIG_INITRAMFS_ROOT_UID=0 | ||||
| CONFIG_INITRAMFS_SOURCE="../../root" | ||||
| CONFIG_IRQ_CPU=y | ||||
| # CONFIG_ISDN is not set | ||||
| # CONFIG_LEDS_GPIO is not set | ||||
| # CONFIG_LEMOTE_FULONG is not set | ||||
| # CONFIG_LIB80211 is not set | ||||
| # CONFIG_M25PXX_USE_FAST_READ is not set | ||||
| # CONFIG_MACH_ALCHEMY is not set | ||||
| # CONFIG_MACH_DECSTATION is not set | ||||
| # CONFIG_MACH_JAZZ is not set | ||||
| # CONFIG_MACH_TX39XX is not set | ||||
| # CONFIG_MACH_TX49XX is not set | ||||
| # CONFIG_MACH_VR41XX is not set | ||||
| CONFIG_MICREL_PHY=y | ||||
| # CONFIG_MIKROTIK_RB532 is not set | ||||
| CONFIG_MIPS=y | ||||
| # CONFIG_MIPS_COBALT is not set | ||||
| # CONFIG_MIPS_FPU_EMU is not set | ||||
| CONFIG_MIPS_L1_CACHE_SHIFT=5 | ||||
| CONFIG_MIPS_MACHINE=y | ||||
| # CONFIG_MIPS_MALTA is not set | ||||
| CONFIG_MIPS_MT_DISABLED=y | ||||
| # CONFIG_MIPS_MT_SMP is not set | ||||
| # CONFIG_MIPS_MT_SMTC is not set | ||||
| # CONFIG_MIPS_SIM is not set | ||||
| CONFIG_MISC_FILESYSTEMS=y | ||||
| CONFIG_MTD_AR91XX_FLASH=y | ||||
| # CONFIG_MTD_CFI is not set | ||||
| # CONFIG_MTD_CFI_INTELEXT is not set | ||||
| CONFIG_MTD_JEDECPROBE=y | ||||
| CONFIG_MTD_M25P80=y | ||||
| CONFIG_MTD_NAND=y | ||||
| CONFIG_MTD_NAND_RB4XX=y | ||||
| CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-2 | ||||
| CONFIG_MTD_REDBOOT_PARTS=y | ||||
| CONFIG_MYLOADER=y | ||||
| # CONFIG_NATSEMI is not set | ||||
| # CONFIG_NEC_MARKEINS is not set | ||||
| CONFIG_NET_DSA=y | ||||
| CONFIG_NET_DSA_MV88E6060=y | ||||
| # CONFIG_NET_DSA_MV88E6123_61_65 is not set | ||||
| # CONFIG_NET_DSA_MV88E6131 is not set | ||||
| # CONFIG_NET_DSA_MV88E6XXX is not set | ||||
| # CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set | ||||
| # CONFIG_NET_DSA_TAG_DSA is not set | ||||
| # CONFIG_NET_DSA_TAG_EDSA is not set | ||||
| CONFIG_NET_DSA_TAG_TRAILER=y | ||||
| # CONFIG_NET_SCH_DRR is not set | ||||
| # CONFIG_NO_IOPORT is not set | ||||
| # CONFIG_NXP_STB220 is not set | ||||
| # CONFIG_NXP_STB225 is not set | ||||
| CONFIG_PAGEFLAGS_EXTENDED=y | ||||
| CONFIG_PCI=y | ||||
| CONFIG_PCI_DOMAINS=y | ||||
| # CONFIG_PCI_STUB is not set | ||||
| # CONFIG_PCSPKR_PLATFORM is not set | ||||
| CONFIG_PHYLIB=y | ||||
| # CONFIG_PMC_MSP is not set | ||||
| # CONFIG_PMC_YOSEMITE is not set | ||||
| # CONFIG_PNX8550_JBS is not set | ||||
| # CONFIG_PNX8550_STB810 is not set | ||||
| # CONFIG_PROBE_INITRD_HEADER is not set | ||||
| CONFIG_PROM_EMU=y | ||||
| CONFIG_SCHED_OMIT_FRAME_POINTER=y | ||||
| # CONFIG_SCSI_DMA is not set | ||||
| # CONFIG_SERIAL_8250_EXTENDED is not set | ||||
| CONFIG_SERIAL_8250_NR_UARTS=1 | ||||
| CONFIG_SERIAL_8250_RUNTIME_UARTS=1 | ||||
| # CONFIG_SGI_IP22 is not set | ||||
| # CONFIG_SGI_IP27 is not set | ||||
| # CONFIG_SGI_IP28 is not set | ||||
| # CONFIG_SGI_IP32 is not set | ||||
| # CONFIG_SIBYTE_BIGSUR is not set | ||||
| # CONFIG_SIBYTE_CARMEL is not set | ||||
| # CONFIG_SIBYTE_CRHINE is not set | ||||
| # CONFIG_SIBYTE_CRHONE is not set | ||||
| # CONFIG_SIBYTE_LITTLESUR is not set | ||||
| # CONFIG_SIBYTE_RHONE is not set | ||||
| # CONFIG_SIBYTE_SENTOSA is not set | ||||
| # CONFIG_SIBYTE_SWARM is not set | ||||
| # CONFIG_SLAB is not set | ||||
| CONFIG_SLUB=y | ||||
| CONFIG_SPI=y | ||||
| CONFIG_SPI_AP83=y | ||||
| CONFIG_SPI_AR71XX=y | ||||
| CONFIG_SPI_BITBANG=y | ||||
| CONFIG_SPI_GPIO=y | ||||
| CONFIG_SPI_MASTER=y | ||||
| CONFIG_SPI_PB44=y | ||||
| # CONFIG_SPI_SPIDEV is not set | ||||
| # CONFIG_SPI_VSC7385 is not set | ||||
| CONFIG_SYS_HAS_CPU_MIPS32_R1=y | ||||
| CONFIG_SYS_HAS_CPU_MIPS32_R2=y | ||||
| CONFIG_SYS_HAS_EARLY_PRINTK=y | ||||
| CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y | ||||
| CONFIG_SYS_SUPPORTS_ARBIT_HZ=y | ||||
| CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y | ||||
| # CONFIG_TC35815 is not set | ||||
| CONFIG_TICK_ONESHOT=y | ||||
| CONFIG_TRAD_SIGNALS=y | ||||
| CONFIG_USB_SUPPORT=y | ||||
| CONFIG_YAFFS_9BYTE_TAGS=y | ||||
| CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED=y | ||||
| CONFIG_YAFFS_AUTO_YAFFS2=y | ||||
| # CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set | ||||
| # CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set | ||||
| CONFIG_YAFFS_FS=y | ||||
| CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y | ||||
| CONFIG_YAFFS_YAFFS1=y | ||||
| CONFIG_YAFFS_YAFFS2=y | ||||
| CONFIG_ZONE_DMA_FLAG=0 | ||||
| @@ -1,50 +0,0 @@ | ||||
| --- a/arch/mips/Makefile | ||||
| +++ b/arch/mips/Makefile | ||||
| @@ -609,6 +609,13 @@ else | ||||
|  load-$(CONFIG_CPU_CAVIUM_OCTEON) 	+= 0xffffffff81100000 | ||||
|  endif | ||||
|   | ||||
| +# | ||||
| +# Atheros AR71xx | ||||
| +# | ||||
| +core-$(CONFIG_ATHEROS_AR71XX)	+= arch/mips/ar71xx/ | ||||
| +cflags-$(CONFIG_ATHEROS_AR71XX)	+= -I$(srctree)/arch/mips/include/asm/mach-ar71xx | ||||
| +load-$(CONFIG_ATHEROS_AR71XX)	+= 0xffffffff80060000 | ||||
| + | ||||
|  # temporary until string.h is fixed | ||||
|  cflags-y += -ffreestanding | ||||
|   | ||||
| --- a/arch/mips/Kconfig | ||||
| +++ b/arch/mips/Kconfig | ||||
| @@ -22,6 +22,23 @@ choice | ||||
|  config MACH_ALCHEMY | ||||
|  	bool "Alchemy processor based machines" | ||||
|   | ||||
| +config ATHEROS_AR71XX | ||||
| +	bool "Atheros AR71xx based boards" | ||||
| +	select CEVT_R4K | ||||
| +	select CSRC_R4K | ||||
| +	select DMA_NONCOHERENT | ||||
| +	select HW_HAS_PCI | ||||
| +	select IRQ_CPU | ||||
| +	select ARCH_REQUIRE_GPIOLIB | ||||
| +	select SYS_HAS_CPU_MIPS32_R1 | ||||
| +	select SYS_HAS_CPU_MIPS32_R2 | ||||
| +	select SYS_SUPPORTS_32BIT_KERNEL | ||||
| +	select SYS_SUPPORTS_BIG_ENDIAN | ||||
| +	select SYS_HAS_EARLY_PRINTK | ||||
| +	select MIPS_MACHINE | ||||
| +	help | ||||
| +	  Support for Atheros AR71xx based boards. | ||||
| + | ||||
|  config BASLER_EXCITE | ||||
|  	bool "Basler eXcite smart camera" | ||||
|  	select CEVT_R4K | ||||
| @@ -640,6 +657,7 @@ config CAVIUM_OCTEON_REFERENCE_BOARD | ||||
|  endchoice | ||||
|   | ||||
|  source "arch/mips/alchemy/Kconfig" | ||||
| +source "arch/mips/ar71xx/Kconfig" | ||||
|  source "arch/mips/basler/excite/Kconfig" | ||||
|  source "arch/mips/jazz/Kconfig" | ||||
|  source "arch/mips/lasat/Kconfig" | ||||
| @@ -1,10 +0,0 @@ | ||||
| --- a/arch/mips/pci/Makefile | ||||
| +++ b/arch/mips/pci/Makefile | ||||
| @@ -16,6 +16,7 @@ obj-$(CONFIG_PCI_VR41XX)	+= ops-vr41xx.o | ||||
|  obj-$(CONFIG_NEC_MARKEINS)	+= ops-emma2rh.o pci-emma2rh.o fixup-emma2rh.o | ||||
|  obj-$(CONFIG_PCI_TX4927)	+= ops-tx4927.o | ||||
|  obj-$(CONFIG_BCM47XX)		+= pci-bcm47xx.o | ||||
| +obj-$(CONFIG_ATHEROS_AR71XX)	+= pci-ar71xx.o pci-ar724x.o | ||||
|   | ||||
|  # | ||||
|  # These are still pretty much in the old state, watch, go blind. | ||||
| @@ -1,58 +0,0 @@ | ||||
| --- a/drivers/usb/host/Kconfig | ||||
| +++ b/drivers/usb/host/Kconfig | ||||
| @@ -81,6 +81,13 @@ config USB_EHCI_BIG_ENDIAN_DESC | ||||
|  	depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX) | ||||
|  	default y | ||||
|   | ||||
| +config USB_EHCI_AR71XX | ||||
| +	bool "USB EHCI support for AR71xx" | ||||
| +	depends on USB_EHCI_HCD && ATHEROS_AR71XX | ||||
| +	default y | ||||
| +	help | ||||
| +	  Support for Atheros AR71xx built-in EHCI controller | ||||
| + | ||||
|  config USB_EHCI_FSL | ||||
|  	bool "Support for Freescale on-chip EHCI USB controller" | ||||
|  	depends on USB_EHCI_HCD && FSL_SOC | ||||
| @@ -154,6 +161,13 @@ config USB_OHCI_HCD | ||||
|  	  To compile this driver as a module, choose M here: the | ||||
|  	  module will be called ohci-hcd. | ||||
|   | ||||
| +config USB_OHCI_AR71XX | ||||
| +	bool "USB OHCI support for Atheros AR71xx" | ||||
| +	depends on USB_OHCI_HCD && ATHEROS_AR71XX | ||||
| +	default y | ||||
| +	help | ||||
| +	  Support for Atheros AR71xx built-in OHCI controller | ||||
| + | ||||
|  config USB_OHCI_HCD_PPC_SOC | ||||
|  	bool "OHCI support for on-chip PPC USB controller" | ||||
|  	depends on USB_OHCI_HCD && (STB03xxx || PPC_MPC52xx) | ||||
| --- a/drivers/usb/host/ehci-hcd.c | ||||
| +++ b/drivers/usb/host/ehci-hcd.c | ||||
| @@ -1036,6 +1036,11 @@ MODULE_LICENSE ("GPL"); | ||||
|  #define	PLATFORM_DRIVER		ixp4xx_ehci_driver | ||||
|  #endif | ||||
|   | ||||
| +#ifdef CONFIG_USB_EHCI_AR71XX | ||||
| +#include "ehci-ar71xx.c" | ||||
| +#define PLATFORM_DRIVER		ehci_ar71xx_driver | ||||
| +#endif | ||||
| + | ||||
|  #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ | ||||
|      !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) | ||||
|  #error "missing bus glue for ehci-hcd" | ||||
| --- a/drivers/usb/host/ohci-hcd.c | ||||
| +++ b/drivers/usb/host/ohci-hcd.c | ||||
| @@ -1080,6 +1080,11 @@ MODULE_LICENSE ("GPL"); | ||||
|  #define TMIO_OHCI_DRIVER	ohci_hcd_tmio_driver | ||||
|  #endif | ||||
|   | ||||
| +#ifdef CONFIG_USB_OHCI_AR71XX | ||||
| +#include "ohci-ar71xx.c" | ||||
| +#define PLATFORM_DRIVER		ohci_hcd_ar71xx_driver | ||||
| +#endif | ||||
| + | ||||
|  #if	!defined(PCI_DRIVER) &&		\ | ||||
|  	!defined(PLATFORM_DRIVER) &&	\ | ||||
|  	!defined(OF_PLATFORM_DRIVER) &&	\ | ||||
| @@ -1,26 +0,0 @@ | ||||
| --- a/drivers/spi/Kconfig | ||||
| +++ b/drivers/spi/Kconfig | ||||
| @@ -53,6 +53,13 @@ if SPI_MASTER | ||||
|   | ||||
|  comment "SPI Master Controller Drivers" | ||||
|   | ||||
| +config SPI_AR71XX | ||||
| +	tristate "Atheros AR71xx SPI Controller" | ||||
| +	depends on SPI_MASTER && ATHEROS_AR71XX | ||||
| +	select SPI_BITBANG | ||||
| +	help | ||||
| +	  This is the SPI contoller driver for Atheros AR71xx. | ||||
| + | ||||
|  config SPI_ATMEL | ||||
|  	tristate "Atmel SPI Controller" | ||||
|  	depends on (ARCH_AT91 || AVR32) | ||||
| --- a/drivers/spi/Makefile | ||||
| +++ b/drivers/spi/Makefile | ||||
| @@ -11,6 +11,7 @@ endif | ||||
|  obj-$(CONFIG_SPI_MASTER)		+= spi.o | ||||
|   | ||||
|  # SPI master controller drivers (bus) | ||||
| +obj-$(CONFIG_SPI_AR71XX)		+= ar71xx_spi.o | ||||
|  obj-$(CONFIG_SPI_ATMEL)			+= atmel_spi.o | ||||
|  obj-$(CONFIG_SPI_BFIN)			+= spi_bfin5xx.o | ||||
|  obj-$(CONFIG_SPI_BITBANG)		+= spi_bitbang.o | ||||
| @@ -1,21 +0,0 @@ | ||||
| --- a/drivers/net/Kconfig | ||||
| +++ b/drivers/net/Kconfig | ||||
| @@ -2068,6 +2068,8 @@ config ACENIC_OMIT_TIGON_I | ||||
|   | ||||
|  	  The safe and default value for this is N. | ||||
|   | ||||
| +source drivers/net/ag71xx/Kconfig | ||||
| + | ||||
|  config DL2K | ||||
|  	tristate "DL2000/TC902x-based Gigabit Ethernet support" | ||||
|  	depends on PCI | ||||
| --- a/drivers/net/Makefile | ||||
| +++ b/drivers/net/Makefile | ||||
| @@ -2,6 +2,7 @@ | ||||
|  # Makefile for the Linux network (ethercard) device drivers. | ||||
|  # | ||||
|   | ||||
| +obj-$(CONFIG_AG71XX) += ag71xx/ | ||||
|  obj-$(CONFIG_E1000) += e1000/ | ||||
|  obj-$(CONFIG_E1000E) += e1000e/ | ||||
|  obj-$(CONFIG_IBM_NEW_EMAC) += ibm_newemac/ | ||||
| @@ -1,26 +0,0 @@ | ||||
| --- a/drivers/watchdog/Kconfig | ||||
| +++ b/drivers/watchdog/Kconfig | ||||
| @@ -766,6 +766,13 @@ config TXX9_WDT | ||||
|  	help | ||||
|  	  Hardware driver for the built-in watchdog timer on TXx9 MIPS SoCs. | ||||
|   | ||||
| +config AR71XX_WDT | ||||
| +	tristate "Atheros AR71xx Watchdog Timer" | ||||
| +	depends on ATHEROS_AR71XX | ||||
| +	help | ||||
| +	  Hardware driver for the built-in watchdog timer on the Atheros | ||||
| +	  AR71xx SoCs. | ||||
| + | ||||
|  # PARISC Architecture | ||||
|   | ||||
|  # POWERPC Architecture | ||||
| --- a/drivers/watchdog/Makefile | ||||
| +++ b/drivers/watchdog/Makefile | ||||
| @@ -107,6 +107,7 @@ obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o | ||||
|  obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o | ||||
|  obj-$(CONFIG_AR7_WDT) += ar7_wdt.o | ||||
|  obj-$(CONFIG_TXX9_WDT) += txx9wdt.o | ||||
| +obj-$(CONFIG_AR71XX_WDT) += ar71xx_wdt.o | ||||
|   | ||||
|  # PARISC Architecture | ||||
|   | ||||
| @@ -1,26 +0,0 @@ | ||||
| --- a/drivers/mtd/maps/Kconfig | ||||
| +++ b/drivers/mtd/maps/Kconfig | ||||
| @@ -268,6 +268,13 @@ config MTD_ALCHEMY | ||||
|  	help | ||||
|  	  Flash memory access on AMD Alchemy Pb/Db/RDK Reference Boards | ||||
|   | ||||
| +config MTD_AR91XX_FLASH | ||||
| +	tristate "Atheros AR91xx parallel flash support" | ||||
| +	depends on ATHEROS_AR71XX | ||||
| +	select MTD_COMPLEX_MAPPINGS | ||||
| +	help | ||||
| +	  Parallel flash driver for the Atheros AR91xx based boards. | ||||
| + | ||||
|  config MTD_DILNETPC | ||||
|  	tristate "CFI Flash device mapped on DIL/Net PC" | ||||
|  	depends on X86 && MTD_CONCAT && MTD_PARTITIONS && MTD_CFI_INTELEXT | ||||
| --- a/drivers/mtd/maps/Makefile | ||||
| +++ b/drivers/mtd/maps/Makefile | ||||
| @@ -42,6 +42,7 @@ obj-$(CONFIG_MTD_DBOX2)		+= dbox2-flash. | ||||
|  obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o | ||||
|  obj-$(CONFIG_MTD_PCI)		+= pci.o | ||||
|  obj-$(CONFIG_MTD_ALCHEMY)       += alchemy-flash.o | ||||
| +obj-$(CONFIG_MTD_AR91XX_FLASH)	+= ar91xx_flash.o | ||||
|  obj-$(CONFIG_MTD_AUTCPU12)	+= autcpu12-nvram.o | ||||
|  obj-$(CONFIG_MTD_EDB7312)	+= edb7312.o | ||||
|  obj-$(CONFIG_MTD_IMPA7)		+= impa7.o | ||||
| @@ -1,13 +0,0 @@ | ||||
| --- a/drivers/mtd/devices/m25p80.c | ||||
| +++ b/drivers/mtd/devices/m25p80.c | ||||
| @@ -504,6 +504,10 @@ static struct flash_info __devinitdata m | ||||
|  	{ "at26df161a", 0x1f4601, 0, 64 * 1024, 32, SECT_4K, }, | ||||
|  	{ "at26df321",  0x1f4701, 0, 64 * 1024, 64, SECT_4K, }, | ||||
|   | ||||
| +	/* PMC -- pm25x "blocks" are 32K, sectors are 4K */ | ||||
| +	{ "pm25lv512",         0, 32 * 1024, 2, SECT_4K }, | ||||
| +	{ "pm25lv010",         0, 32 * 1024, 4, SECT_4K }, | ||||
| + | ||||
|  	/* Spansion -- single (large) sector size only, at least | ||||
|  	 * for the chips listed here (without boot sectors). | ||||
|  	 */ | ||||
| @@ -1,24 +0,0 @@ | ||||
| --- a/drivers/net/phy/Kconfig | ||||
| +++ b/drivers/net/phy/Kconfig | ||||
| @@ -104,6 +104,11 @@ config AR8216_PHY | ||||
|  	tristate "Driver for Atheros AR8216 switches" | ||||
|  	select SWCONFIG | ||||
|   | ||||
| +config MICREL_PHY | ||||
| +	tristate "Drivers for Micrel/Kendin PHYs" | ||||
| +	---help--- | ||||
| +	  Currently has a driver for the KSZ8041 | ||||
| + | ||||
|  config FIXED_PHY | ||||
|  	bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs" | ||||
|  	depends on PHYLIB=y | ||||
| --- a/drivers/net/phy/Makefile | ||||
| +++ b/drivers/net/phy/Makefile | ||||
| @@ -19,6 +19,7 @@ obj-$(CONFIG_IP175C_PHY)	+= ip175c.o | ||||
|  obj-$(CONFIG_AR8216_PHY)	+= ar8216.o | ||||
|  obj-$(CONFIG_REALTEK_PHY)	+= realtek.o | ||||
|  obj-$(CONFIG_LSI_ET1011C_PHY)	+= et1011c.o | ||||
| +obj-$(CONFIG_MICREL)		+= micrel.o | ||||
|  obj-$(CONFIG_FIXED_PHY)		+= fixed.o | ||||
|  obj-$(CONFIG_MDIO_BITBANG)	+= mdio-bitbang.o | ||||
|  obj-$(CONFIG_MDIO_GPIO)		+= mdio-gpio.o | ||||
| @@ -1,22 +0,0 @@ | ||||
| --- a/drivers/mtd/devices/m25p80.c | ||||
| +++ b/drivers/mtd/devices/m25p80.c | ||||
| @@ -712,12 +712,17 @@ static int __devinit m25p_probe(struct s | ||||
|  		struct mtd_partition	*parts = NULL; | ||||
|  		int			nr_parts = 0; | ||||
|   | ||||
| +		static const char *part_probes[] = { | ||||
|  #ifdef CONFIG_MTD_CMDLINE_PARTS | ||||
| -		static const char *part_probes[] = { "cmdlinepart", NULL, }; | ||||
| +						"cmdlinepart", | ||||
| +#endif | ||||
| +#ifdef CONFIG_MTD_MYLOADER_PARTS | ||||
| +						"MyLoader", | ||||
| +#endif | ||||
| +					       	NULL, }; | ||||
|   | ||||
|  		nr_parts = parse_mtd_partitions(&flash->mtd, | ||||
|  				part_probes, &parts, 0); | ||||
| -#endif | ||||
|   | ||||
|  		if (nr_parts <= 0 && data && data->parts) { | ||||
|  			parts = data->parts; | ||||
| @@ -1,13 +0,0 @@ | ||||
| --- a/drivers/mtd/devices/m25p80.c | ||||
| +++ b/drivers/mtd/devices/m25p80.c | ||||
| @@ -504,6 +504,10 @@ static struct flash_info __devinitdata m | ||||
|  	{ "at26df161a", 0x1f4601, 0, 64 * 1024, 32, SECT_4K, }, | ||||
|  	{ "at26df321",  0x1f4701, 0, 64 * 1024, 64, SECT_4K, }, | ||||
|   | ||||
| +	/* EON -- en25pxx */ | ||||
| +	{ "en25p32", 0x1c2016, 0, 64 * 1024,  64, }, | ||||
| +	{ "en25p64", 0x1c2017, 0, 64 * 1024, 128, }, | ||||
| + | ||||
|  	/* PMC -- pm25x "blocks" are 32K, sectors are 4K */ | ||||
|  	{ "pm25lv512",         0, 32 * 1024, 2, SECT_4K }, | ||||
|  	{ "pm25lv010",         0, 32 * 1024, 4, SECT_4K }, | ||||
| @@ -1,12 +0,0 @@ | ||||
| --- a/drivers/mtd/devices/m25p80.c | ||||
| +++ b/drivers/mtd/devices/m25p80.c | ||||
| @@ -723,6 +723,9 @@ static int __devinit m25p_probe(struct s | ||||
|  #ifdef CONFIG_MTD_MYLOADER_PARTS | ||||
|  						"MyLoader", | ||||
|  #endif | ||||
| +#ifdef CONFIG_MTD_REDBOOT_PARTS | ||||
| +						"RedBoot", | ||||
| +#endif | ||||
|  					       	NULL, }; | ||||
|   | ||||
|  		nr_parts = parse_mtd_partitions(&flash->mtd, | ||||
| @@ -1,14 +0,0 @@ | ||||
| --- a/drivers/mtd/devices/m25p80.c | ||||
| +++ b/drivers/mtd/devices/m25p80.c | ||||
| @@ -508,6 +508,11 @@ static struct flash_info __devinitdata m | ||||
|  	{ "en25p32", 0x1c2016, 0, 64 * 1024,  64, }, | ||||
|  	{ "en25p64", 0x1c2017, 0, 64 * 1024, 128, }, | ||||
|   | ||||
| +	/* Macronix -- mx25lxxx */ | ||||
| +	{ "mx25l32",  0xc22016, 0, 64 * 1024,  64, }, | ||||
| +	{ "mx25l64",  0xc22017, 0, 64 * 1024, 128, }, | ||||
| +	{ "mx25l128", 0xc22018, 0, 64 * 1024, 256, }, | ||||
| + | ||||
|  	/* PMC -- pm25x "blocks" are 32K, sectors are 4K */ | ||||
|  	{ "pm25lv512",         0, 32 * 1024, 2, SECT_4K }, | ||||
|  	{ "pm25lv010",         0, 32 * 1024, 4, SECT_4K }, | ||||
| @@ -1,14 +0,0 @@ | ||||
| --- a/drivers/mtd/devices/m25p80.c | ||||
| +++ b/drivers/mtd/devices/m25p80.c | ||||
| @@ -513,6 +513,11 @@ static struct flash_info __devinitdata m | ||||
|  	{ "mx25l64",  0xc22017, 0, 64 * 1024, 128, }, | ||||
|  	{ "mx25l128", 0xc22018, 0, 64 * 1024, 256, }, | ||||
|   | ||||
| +	/* Numonyx -- xxxs33b */ | ||||
| +	{ "160s33b",  0x898911, 0, 64 * 1024,  64, }, | ||||
| +	{ "320s33b",  0x898912, 0, 64 * 1024, 128, }, | ||||
| +	{ "640s33b",  0x898913, 0, 64 * 1024, 256, }, | ||||
| + | ||||
|  	/* PMC -- pm25x "blocks" are 32K, sectors are 4K */ | ||||
|  	{ "pm25lv512",         0, 32 * 1024, 2, SECT_4K }, | ||||
|  	{ "pm25lv010",         0, 32 * 1024, 4, SECT_4K }, | ||||
| @@ -1,29 +0,0 @@ | ||||
| --- a/drivers/mtd/chips/jedec_probe.c | ||||
| +++ b/drivers/mtd/chips/jedec_probe.c | ||||
| @@ -159,6 +159,7 @@ | ||||
|  #define SST39LF800	0x2781 | ||||
|  #define SST39LF160	0x2782 | ||||
|  #define SST39VF1601	0x234b | ||||
| +#define SST39VF6401B	0x236d | ||||
|  #define SST39LF512	0x00D4 | ||||
|  #define SST39LF010	0x00D5 | ||||
|  #define SST39LF020	0x00D6 | ||||
| @@ -1502,6 +1503,18 @@ static const struct amd_flash_info jedec | ||||
|  			ERASEINFO(0x10000,64), | ||||
|  		} | ||||
|  	}, { | ||||
| +		.mfr_id         = MANUFACTURER_SST, | ||||
| +		.dev_id         = SST39VF6401B, | ||||
| +		.name           = "SST 39VF6401B", | ||||
| +		.devtypes       = CFI_DEVICETYPE_X16, | ||||
| +		.uaddr          = MTD_UADDR_0xAAAA_0x5555, | ||||
| +		.dev_size       = SIZE_8MiB, | ||||
| +		.cmd_set        = P_ID_AMD_STD, | ||||
| +		.nr_regions     = 1, | ||||
| +		.regions        = { | ||||
| +			ERASEINFO(0x10000,128) | ||||
| +		} | ||||
| +	}, { | ||||
|  		.mfr_id		= MANUFACTURER_ST, | ||||
|  		.dev_id		= M29F800AB, | ||||
|  		.name		= "ST M29F800AB", | ||||
| @@ -1,20 +0,0 @@ | ||||
| --- a/drivers/mtd/chips/cfi_cmdset_0002.c | ||||
| +++ b/drivers/mtd/chips/cfi_cmdset_0002.c | ||||
| @@ -1568,7 +1568,7 @@ static int __xipram do_erase_chip(struct | ||||
|  			chip->erase_suspended = 0; | ||||
|  		} | ||||
|   | ||||
| -		if (chip_ready(map, adr)) | ||||
| +		if (chip_good(map, adr, map_word_ff(map))) | ||||
|  			break; | ||||
|   | ||||
|  		if (time_after(jiffies, timeo)) { | ||||
| @@ -1656,7 +1656,7 @@ static int __xipram do_erase_oneblock(st | ||||
|  			chip->erase_suspended = 0; | ||||
|  		} | ||||
|   | ||||
| -		if (chip_ready(map, adr)) { | ||||
| +		if (chip_good(map, adr, map_word_ff(map))) { | ||||
|  			xip_enable(map, chip, adr); | ||||
|  			break; | ||||
|  		} | ||||
| @@ -1,22 +0,0 @@ | ||||
| --- a/drivers/usb/host/ehci-q.c | ||||
| +++ b/drivers/usb/host/ehci-q.c | ||||
| @@ -1082,6 +1082,9 @@ static void end_unlink_async (struct ehc | ||||
|  		ehci->reclaim = NULL; | ||||
|  		start_unlink_async (ehci, next); | ||||
|  	} | ||||
| + | ||||
| +	if (ehci->has_synopsys_hc_bug) | ||||
| +		writel((u32)ehci->async->qh_dma, &ehci->regs->async_next); | ||||
|  } | ||||
|   | ||||
|  /* makes sure the async qh will become idle */ | ||||
| --- a/drivers/usb/host/ehci.h | ||||
| +++ b/drivers/usb/host/ehci.h | ||||
| @@ -125,6 +125,7 @@ struct ehci_hcd {			/* one per controlle | ||||
|  	unsigned		big_endian_mmio:1; | ||||
|  	unsigned		big_endian_desc:1; | ||||
|  	unsigned		has_amcc_usb23:1; | ||||
| +	unsigned		has_synopsys_hc_bug:1; /* Synopsys HC */ | ||||
|   | ||||
|  	/* required for usb32 quirk */ | ||||
|  	#define OHCI_CTRL_HCFS          (3 << 6) | ||||
| @@ -1,54 +0,0 @@ | ||||
| --- a/drivers/mtd/redboot.c | ||||
| +++ b/drivers/mtd/redboot.c | ||||
| @@ -60,31 +60,32 @@ static int parse_redboot_partitions(stru | ||||
|  	static char nullstring[] = "unallocated"; | ||||
|  #endif | ||||
|   | ||||
| +	buf = vmalloc(master->erasesize); | ||||
| +	if (!buf) | ||||
| +		return -ENOMEM; | ||||
| + | ||||
| + restart: | ||||
|  	if ( directory < 0 ) { | ||||
|  		offset = master->size + directory * master->erasesize; | ||||
| -		while (master->block_isbad &&  | ||||
| +		while (master->block_isbad && | ||||
|  		       master->block_isbad(master, offset)) { | ||||
|  			if (!offset) { | ||||
|  			nogood: | ||||
|  				printk(KERN_NOTICE "Failed to find a non-bad block to check for RedBoot partition table\n"); | ||||
| +				vfree(buf); | ||||
|  				return -EIO; | ||||
|  			} | ||||
|  			offset -= master->erasesize; | ||||
|  		} | ||||
|  	} else { | ||||
|  		offset = directory * master->erasesize; | ||||
| -		while (master->block_isbad &&  | ||||
| +		while (master->block_isbad && | ||||
|  		       master->block_isbad(master, offset)) { | ||||
|  			offset += master->erasesize; | ||||
|  			if (offset == master->size) | ||||
|  				goto nogood; | ||||
|  		} | ||||
|  	} | ||||
| -	buf = vmalloc(master->erasesize); | ||||
| - | ||||
| -	if (!buf) | ||||
| -		return -ENOMEM; | ||||
| - | ||||
|  	printk(KERN_NOTICE "Searching for RedBoot partition table in %s at offset 0x%lx\n", | ||||
|  	       master->name, offset); | ||||
|   | ||||
| @@ -156,6 +157,11 @@ static int parse_redboot_partitions(stru | ||||
|  	} | ||||
|  	if (i == numslots) { | ||||
|  		/* Didn't find it */ | ||||
| +		if (offset + master->erasesize < master->size) { | ||||
| +			/* not at the end of the flash yet, maybe next block :) */ | ||||
| +			directory++; | ||||
| +			goto restart; | ||||
| +		} | ||||
|  		printk(KERN_NOTICE "No RedBoot partition table detected in %s\n", | ||||
|  		       master->name); | ||||
|  		ret = 0; | ||||
| @@ -1,21 +0,0 @@ | ||||
| --- a/drivers/mtd/nand/Kconfig | ||||
| +++ b/drivers/mtd/nand/Kconfig | ||||
| @@ -427,4 +427,8 @@ config MTD_NAND_SH_FLCTL | ||||
|  	  Several Renesas SuperH CPU has FLCTL. This option enables support | ||||
|  	  for NAND Flash using FLCTL. This driver support SH7723. | ||||
|   | ||||
| +config MTD_NAND_RB4XX | ||||
| +	tristate "NAND flash driver for RouterBoard 4xx series" | ||||
| +	depends on MTD_NAND && ATHEROS_AR71XX | ||||
| + | ||||
|  endif # MTD_NAND | ||||
| --- a/drivers/mtd/nand/Makefile | ||||
| +++ b/drivers/mtd/nand/Makefile | ||||
| @@ -29,6 +29,7 @@ obj-$(CONFIG_MTD_NAND_BASLER_EXCITE)	+=  | ||||
|  obj-$(CONFIG_MTD_NAND_PXA3xx)		+= pxa3xx_nand.o | ||||
|  obj-$(CONFIG_MTD_NAND_TMIO)		+= tmio_nand.o | ||||
|  obj-$(CONFIG_MTD_NAND_PLATFORM)		+= plat_nand.o | ||||
| +obj-$(CONFIG_MTD_NAND_RB4XX)		+= rb4xx_nand.o | ||||
|  obj-$(CONFIG_MTD_ALAUDA)		+= alauda.o | ||||
|  obj-$(CONFIG_MTD_NAND_PASEMI)		+= pasemi_nand.o | ||||
|  obj-$(CONFIG_MTD_NAND_ORION)		+= orion_nand.o | ||||
| @@ -1,27 +0,0 @@ | ||||
| --- a/drivers/spi/Makefile | ||||
| +++ b/drivers/spi/Makefile | ||||
| @@ -11,6 +11,7 @@ endif | ||||
|  obj-$(CONFIG_SPI_MASTER)		+= spi.o | ||||
|   | ||||
|  # SPI master controller drivers (bus) | ||||
| +obj-$(CONFIG_SPI_AP83)			+= ap83_spi.o | ||||
|  obj-$(CONFIG_SPI_AR71XX)		+= ar71xx_spi.o | ||||
|  obj-$(CONFIG_SPI_ATMEL)			+= atmel_spi.o | ||||
|  obj-$(CONFIG_SPI_BFIN)			+= spi_bfin5xx.o | ||||
| --- a/drivers/spi/Kconfig | ||||
| +++ b/drivers/spi/Kconfig | ||||
| @@ -53,6 +53,14 @@ if SPI_MASTER | ||||
|   | ||||
|  comment "SPI Master Controller Drivers" | ||||
|   | ||||
| +config SPI_AP83 | ||||
| +	tristate "Atheros AP83 specific SPI Controller" | ||||
| +	depends on SPI_MASTER && AR71XX_MACH_AP83 | ||||
| +	select SPI_BITBANG | ||||
| +	help | ||||
| +	  This is a specific SPI controller driver for the Atheros AP83 | ||||
| +	  reference board. | ||||
| + | ||||
|  config SPI_AR71XX | ||||
|  	tristate "Atheros AR71xx SPI Controller" | ||||
|  	depends on SPI_MASTER && ATHEROS_AR71XX | ||||
| @@ -1,24 +0,0 @@ | ||||
| --- a/drivers/spi/Kconfig | ||||
| +++ b/drivers/spi/Kconfig | ||||
| @@ -272,6 +272,11 @@ config SPI_TLE62X0 | ||||
|  	  sysfs interface, with each line presented as a kind of GPIO | ||||
|  	  exposing both switch control and diagnostic feedback. | ||||
|   | ||||
| +config SPI_VSC7385 | ||||
| +	tristate "Vitesse VSC7385 ethernet switch driver" | ||||
| +	help | ||||
| +	  SPI driver for the Vitesse VSC7385 ethernet switch. | ||||
| + | ||||
|  # | ||||
|  # Add new SPI protocol masters in alphabetical order above this line | ||||
|  # | ||||
| --- a/drivers/spi/Makefile | ||||
| +++ b/drivers/spi/Makefile | ||||
| @@ -37,6 +37,7 @@ obj-$(CONFIG_SPI_SH_SCI)		+= spi_sh_sci. | ||||
|   | ||||
|  # SPI protocol drivers (device/link on bus) | ||||
|  obj-$(CONFIG_SPI_SPIDEV)	+= spidev.o | ||||
| +obj-$(CONFIG_SPI_VSC7385)	+= spi_vsc7385.o | ||||
|  obj-$(CONFIG_SPI_TLE62X0)	+= tle62x0.o | ||||
|  # 	... add above this line ... | ||||
|   | ||||
| @@ -1,27 +0,0 @@ | ||||
| --- a/drivers/spi/Kconfig | ||||
| +++ b/drivers/spi/Kconfig | ||||
| @@ -68,6 +68,14 @@ config SPI_AR71XX | ||||
|  	help | ||||
|  	  This is the SPI contoller driver for Atheros AR71xx. | ||||
|   | ||||
| +config SPI_PB44 | ||||
| +	tristate "Atheros PB44 board specific SPI controller" | ||||
| +	depends on SPI_MASTER && AR71XX_MACH_PB44 | ||||
| +	select SPI_BITBANG | ||||
| +	help | ||||
| +	  This is a specific SPI controller driver for the Atheros PB44 | ||||
| +	  reference board. | ||||
| + | ||||
|  config SPI_ATMEL | ||||
|  	tristate "Atmel SPI Controller" | ||||
|  	depends on (ARCH_AT91 || AVR32) | ||||
| --- a/drivers/spi/Makefile | ||||
| +++ b/drivers/spi/Makefile | ||||
| @@ -22,6 +22,7 @@ obj-$(CONFIG_SPI_GPIO)			+= spi_gpio.o | ||||
|  obj-$(CONFIG_SPI_GPIO_OLD)		+= spi_gpio_old.o | ||||
|  obj-$(CONFIG_SPI_IMX)			+= spi_imx.o | ||||
|  obj-$(CONFIG_SPI_LM70_LLP)		+= spi_lm70llp.o | ||||
| +obj-$(CONFIG_SPI_PB44)			+= pb44_spi.o | ||||
|  obj-$(CONFIG_SPI_PXA2XX)		+= pxa2xx_spi.o | ||||
|  obj-$(CONFIG_SPI_OMAP_UWIRE)		+= omap_uwire.o | ||||
|  obj-$(CONFIG_SPI_OMAP24XX)		+= omap2_mcspi.o | ||||
| @@ -1,22 +0,0 @@ | ||||
| --- a/arch/mips/Makefile | ||||
| +++ b/arch/mips/Makefile | ||||
| @@ -171,6 +171,7 @@ endif | ||||
|  # | ||||
|  libs-$(CONFIG_ARC)		+= arch/mips/fw/arc/ | ||||
|  libs-$(CONFIG_CFE)		+= arch/mips/fw/cfe/ | ||||
| +libs-$(CONFIG_MYLOADER)		+= arch/mips/fw/myloader/ | ||||
|  libs-$(CONFIG_SNIPROM)		+= arch/mips/fw/sni/ | ||||
|  libs-y				+= arch/mips/fw/lib/ | ||||
|  libs-$(CONFIG_SIBYTE_CFE)	+= arch/mips/sibyte/cfe/ | ||||
| --- a/arch/mips/Kconfig | ||||
| +++ b/arch/mips/Kconfig | ||||
| @@ -836,6 +836,9 @@ config MIPS_NILE4 | ||||
|  config MIPS_DISABLE_OBSOLETE_IDE | ||||
|  	bool | ||||
|   | ||||
| +config MYLOADER | ||||
| +	bool | ||||
| + | ||||
|  config SYNC_R4K | ||||
|  	bool | ||||
|   | ||||
| @@ -1,10 +0,0 @@ | ||||
| --- a/arch/mips/Kconfig | ||||
| +++ b/arch/mips/Kconfig | ||||
| @@ -36,6 +36,7 @@ config ATHEROS_AR71XX | ||||
|  	select SYS_SUPPORTS_BIG_ENDIAN | ||||
|  	select SYS_HAS_EARLY_PRINTK | ||||
|  	select MIPS_MACHINE | ||||
| +	select PROM_EMU | ||||
|  	help | ||||
|  	  Support for Atheros AR71xx based boards. | ||||
|   | ||||
| @@ -1,38 +0,0 @@ | ||||
| --- a/drivers/net/ag71xx/ag71xx_main.c | ||||
| +++ b/drivers/net/ag71xx/ag71xx_main.c | ||||
| @@ -561,7 +561,7 @@ static void ag71xx_oom_timer_handler(uns | ||||
|  	struct net_device *dev = (struct net_device *) data; | ||||
|  	struct ag71xx *ag = netdev_priv(dev); | ||||
|   | ||||
| -	netif_rx_schedule(dev, &ag->napi); | ||||
| +	netif_rx_schedule(&ag->napi); | ||||
|  } | ||||
|   | ||||
|  static void ag71xx_tx_timeout(struct net_device *dev) | ||||
| @@ -717,7 +717,7 @@ static int ag71xx_poll(struct napi_struc | ||||
|  		DBG("%s: disable polling mode, done=%d, limit=%d\n", | ||||
|  			dev->name, done, limit); | ||||
|   | ||||
| -		netif_rx_complete(dev, napi); | ||||
| +		netif_rx_complete(napi); | ||||
|   | ||||
|  		/* enable interrupts */ | ||||
|  		spin_lock_irqsave(&ag->lock, flags); | ||||
| @@ -736,7 +736,7 @@ static int ag71xx_poll(struct napi_struc | ||||
|  		printk(KERN_DEBUG "%s: out of memory\n", dev->name); | ||||
|   | ||||
|  	mod_timer(&ag->oom_timer, jiffies + AG71XX_OOM_REFILL); | ||||
| -	netif_rx_complete(dev, napi); | ||||
| +	netif_rx_complete(napi); | ||||
|  	return 0; | ||||
|  } | ||||
|   | ||||
| @@ -766,7 +766,7 @@ static irqreturn_t ag71xx_interrupt(int  | ||||
|  	if (likely(status & AG71XX_INT_POLL)) { | ||||
|  		ag71xx_int_disable(ag, AG71XX_INT_POLL); | ||||
|  		DBG("%s: enable polling mode\n", dev->name); | ||||
| -		netif_rx_schedule(dev, &ag->napi); | ||||
| +		netif_rx_schedule(&ag->napi); | ||||
|  	} | ||||
|   | ||||
|  	return IRQ_HANDLED; | ||||
| @@ -1,29 +0,0 @@ | ||||
| --- a/arch/mips/kernel/traps.c | ||||
| +++ b/arch/mips/kernel/traps.c | ||||
| @@ -48,6 +48,7 @@ | ||||
|  #include <asm/types.h> | ||||
|  #include <asm/stacktrace.h> | ||||
|  #include <asm/irq.h> | ||||
| +#include <asm/time.h> | ||||
|   | ||||
|  extern void check_wait(void); | ||||
|  extern asmlinkage void r4k_wait(void); | ||||
| @@ -1541,6 +1542,8 @@ void __cpuinit per_cpu_trap_init(void) | ||||
|  	 */ | ||||
|  	if (cpu_has_mips_r2) { | ||||
|  		cp0_compare_irq = (read_c0_intctl() >> 29) & 7; | ||||
| +		if (get_c0_compare_irq) | ||||
| +			cp0_compare_irq = get_c0_compare_irq(); | ||||
|  		cp0_perfcount_irq = (read_c0_intctl() >> 26) & 7; | ||||
|  		if (cp0_perfcount_irq == cp0_compare_irq) | ||||
|  			cp0_perfcount_irq = -1; | ||||
| --- a/arch/mips/include/asm/time.h | ||||
| +++ b/arch/mips/include/asm/time.h | ||||
| @@ -52,6 +52,7 @@ extern int (*perf_irq)(void); | ||||
|   */ | ||||
|  #ifdef CONFIG_CEVT_R4K_LIB | ||||
|  extern unsigned int __weak get_c0_compare_int(void); | ||||
| +extern unsigned int __weak get_c0_compare_irq(void); | ||||
|  extern int r4k_clockevent_init(void); | ||||
|  #endif | ||||
|   | ||||
| @@ -1,56 +0,0 @@ | ||||
| --- a/arch/mips/kernel/cevt-r4k.c | ||||
| +++ b/arch/mips/kernel/cevt-r4k.c | ||||
| @@ -15,6 +15,22 @@ | ||||
|  #include <asm/cevt-r4k.h> | ||||
|   | ||||
|  /* | ||||
| + * Compare interrupt can be routed and latched outside the core, | ||||
| + * so a single execution hazard barrier may not be enough to give | ||||
| + * it time to clear as seen in the Cause register.  4 time the | ||||
| + * pipeline depth seems reasonably conservative, and empirically | ||||
| + * works better in configurations with high CPU/bus clock ratios. | ||||
| + */ | ||||
| + | ||||
| +#define compare_change_hazard() \ | ||||
| +	do { \ | ||||
| +		irq_disable_hazard(); \ | ||||
| +		irq_disable_hazard(); \ | ||||
| +		irq_disable_hazard(); \ | ||||
| +		irq_disable_hazard(); \ | ||||
| +	} while (0) | ||||
| + | ||||
| +/* | ||||
|   * The SMTC Kernel for the 34K, 1004K, et. al. replaces several | ||||
|   * of these routines with SMTC-specific variants. | ||||
|   */ | ||||
| @@ -30,6 +46,7 @@ static int mips_next_event(unsigned long | ||||
|  	cnt = read_c0_count(); | ||||
|  	cnt += delta; | ||||
|  	write_c0_compare(cnt); | ||||
| +	compare_change_hazard(); | ||||
|  	res = ((int)(read_c0_count() - cnt) > 0) ? -ETIME : 0; | ||||
|  	return res; | ||||
|  } | ||||
| @@ -99,22 +116,6 @@ static int c0_compare_int_pending(void) | ||||
|  	return (read_c0_cause() >> cp0_compare_irq) & 0x100; | ||||
|  } | ||||
|   | ||||
| -/* | ||||
| - * Compare interrupt can be routed and latched outside the core, | ||||
| - * so a single execution hazard barrier may not be enough to give | ||||
| - * it time to clear as seen in the Cause register.  4 time the | ||||
| - * pipeline depth seems reasonably conservative, and empirically | ||||
| - * works better in configurations with high CPU/bus clock ratios. | ||||
| - */ | ||||
| - | ||||
| -#define compare_change_hazard() \ | ||||
| -	do { \ | ||||
| -		irq_disable_hazard(); \ | ||||
| -		irq_disable_hazard(); \ | ||||
| -		irq_disable_hazard(); \ | ||||
| -		irq_disable_hazard(); \ | ||||
| -	} while (0) | ||||
| - | ||||
|  int c0_compare_int_usable(void) | ||||
|  { | ||||
|  	unsigned int delta; | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,201 +0,0 @@ | ||||
| /* | ||||
|  * character device wrapper for generic gpio layer | ||||
|  * | ||||
|  * 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. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA | ||||
|  * | ||||
|  * Feedback, Bugs...  blogic@openwrt.org | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #include <linux/module.h> | ||||
| #include <linux/errno.h> | ||||
| #include <linux/init.h> | ||||
| #include <asm/uaccess.h> | ||||
| #include <asm/io.h> | ||||
| #include <asm/gpio.h> | ||||
| #include <asm/atomic.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/genhd.h> | ||||
| #include <linux/device.h> | ||||
| #include <linux/platform_device.h> | ||||
| #include <linux/gpio_dev.h> | ||||
|  | ||||
| #define DRVNAME		"gpiodev" | ||||
| #define DEVNAME		"gpio" | ||||
|  | ||||
| static int dev_major; | ||||
| static unsigned int gpio_access_mask; | ||||
| static struct class *gpiodev_class; | ||||
|  | ||||
| /* Counter is 1, if the device is not opened and zero (or less) if opened. */ | ||||
| static atomic_t gpio_open_cnt = ATOMIC_INIT(1); | ||||
|  | ||||
| static int | ||||
| gpio_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) | ||||
| { | ||||
| 	int retval = 0; | ||||
|  | ||||
| 	if (((1 << arg) & gpio_access_mask) != (1 << arg)) | ||||
| 	{ | ||||
| 		retval = -EINVAL; | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	switch (cmd) | ||||
| 	{ | ||||
| 	case GPIO_GET: | ||||
| 		retval = gpio_get_value(arg); | ||||
| 		break; | ||||
|  | ||||
| 	case GPIO_SET: | ||||
| 		gpio_set_value(arg, 1); | ||||
| 		break; | ||||
|  | ||||
| 	case GPIO_CLEAR: | ||||
| 		gpio_set_value(arg, 0); | ||||
| 		break; | ||||
|  | ||||
| 	case GPIO_DIR_IN: | ||||
| 		gpio_direction_input(arg); | ||||
| 		break; | ||||
|  | ||||
| 	case GPIO_DIR_OUT: | ||||
| 		gpio_direction_output(arg, 0); | ||||
| 		break; | ||||
|  | ||||
| 	default: | ||||
| 		retval = -EINVAL; | ||||
| 		break; | ||||
| 	} | ||||
|  | ||||
| out: | ||||
| 	return retval; | ||||
| } | ||||
|  | ||||
| static int | ||||
| gpio_open(struct inode *inode, struct file *file) | ||||
| { | ||||
| 	int result = 0; | ||||
| 	unsigned int dev_minor = MINOR(inode->i_rdev); | ||||
|  | ||||
| 	if (dev_minor != 0) | ||||
| 	{ | ||||
| 		printk(KERN_ERR DRVNAME ": trying to access unknown minor device -> %d\n", dev_minor); | ||||
| 		result = -ENODEV; | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	/* FIXME: We should really allow multiple applications to open the device | ||||
| 	 *        at the same time, as long as the apps access different IO pins. | ||||
| 	 *        The generic gpio-registration functions can be used for that. | ||||
| 	 *        Two new IOCTLs have to be introduced for that. Need to check userspace | ||||
| 	 *        compatibility first. --mb */ | ||||
| 	if (!atomic_dec_and_test(&gpio_open_cnt)) { | ||||
| 		atomic_inc(&gpio_open_cnt); | ||||
| 		printk(KERN_ERR DRVNAME ": Device with minor ID %d already in use\n", dev_minor); | ||||
| 		result = -EBUSY; | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| out: | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| static int | ||||
| gpio_close(struct inode * inode, struct file * file) | ||||
| { | ||||
| 	smp_mb__before_atomic_inc(); | ||||
| 	atomic_inc(&gpio_open_cnt); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| struct file_operations gpio_fops = { | ||||
| 	ioctl:		gpio_ioctl, | ||||
| 	open:		gpio_open, | ||||
| 	release:	gpio_close | ||||
| }; | ||||
|  | ||||
| static int | ||||
| gpio_probe(struct platform_device *dev) | ||||
| { | ||||
| 	int result = 0; | ||||
|  | ||||
| 	dev_major = register_chrdev(0, DEVNAME, &gpio_fops); | ||||
| 	if (!dev_major) | ||||
| 	{ | ||||
| 		printk(KERN_ERR DRVNAME ": Error whilst opening %s \n", DEVNAME); | ||||
| 		result = -ENODEV; | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	gpiodev_class = class_create(THIS_MODULE, DRVNAME); | ||||
| 	device_create(gpiodev_class, NULL, MKDEV(dev_major, 0), dev, DEVNAME); | ||||
|  | ||||
| 	printk(KERN_INFO DRVNAME ": gpio device registered with major %d\n", dev_major); | ||||
|  | ||||
| 	if (dev->num_resources != 1) | ||||
| 	{ | ||||
| 		printk(KERN_ERR DRVNAME ": device may only have 1 resource\n"); | ||||
| 		result = -ENODEV; | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	gpio_access_mask = dev->resource[0].start; | ||||
|  | ||||
| 	printk(KERN_INFO DRVNAME ": gpio platform device registered with access mask %08X\n", gpio_access_mask); | ||||
| out: | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| static int | ||||
| gpio_remove(struct platform_device *dev) | ||||
| { | ||||
| 	unregister_chrdev(dev_major, DEVNAME); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static struct | ||||
| platform_driver gpio_driver = { | ||||
| 	.probe = gpio_probe, | ||||
| 	.remove = gpio_remove, | ||||
| 	.driver = { | ||||
| 		.name = "GPIODEV", | ||||
| 		.owner = THIS_MODULE, | ||||
| 	}, | ||||
| }; | ||||
|  | ||||
| static int __init | ||||
| gpio_mod_init(void) | ||||
| { | ||||
| 	int ret = platform_driver_register(&gpio_driver); | ||||
| 	if (ret) | ||||
| 		printk(KERN_INFO DRVNAME ": Error registering platfom driver!"); | ||||
|  | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| static void __exit | ||||
| gpio_mod_exit(void) | ||||
| { | ||||
| 	platform_driver_unregister(&gpio_driver); | ||||
| } | ||||
|  | ||||
| module_init (gpio_mod_init); | ||||
| module_exit (gpio_mod_exit); | ||||
|  | ||||
| MODULE_LICENSE("GPL"); | ||||
| MODULE_AUTHOR("John Crispin / OpenWrt"); | ||||
| MODULE_DESCRIPTION("Character device for for generic gpio api"); | ||||
| @@ -1,209 +0,0 @@ | ||||
| /* | ||||
|  *  Driver for buttons on GPIO lines not capable of generating interrupts | ||||
|  * | ||||
|  *  Copyright (C) 2007,2008 Gabor Juhos <juhosg at openwrt.org> | ||||
|  * | ||||
|  *  This file was based on: /drivers/input/misc/cobalt_btns.c | ||||
|  *	Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | ||||
|  * | ||||
|  *  also was based on: /drivers/input/keyboard/gpio_keys.c | ||||
|  *	Copyright 2005 Phil Blundell | ||||
|  * | ||||
|  *  This program is free software; you can redistribute it and/or modify | ||||
|  *  it under the terms of the GNU General Public License version 2 as | ||||
|  *  published by the Free Software Foundation. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/module.h> | ||||
| #include <linux/init.h> | ||||
|  | ||||
| #include <linux/input.h> | ||||
| #include <linux/input-polldev.h> | ||||
| #include <linux/ioport.h> | ||||
| #include <linux/platform_device.h> | ||||
|  | ||||
| #include <linux/gpio_buttons.h> | ||||
|  | ||||
| #include <asm/gpio.h> | ||||
|  | ||||
| #define DRV_NAME	"gpio-buttons" | ||||
| #define DRV_VERSION	"0.1.1" | ||||
| #define PFX		DRV_NAME ": " | ||||
|  | ||||
| struct gpio_buttons_dev { | ||||
| 	struct input_polled_dev *poll_dev; | ||||
| 	struct gpio_buttons_platform_data *pdata; | ||||
| }; | ||||
|  | ||||
| static void gpio_buttons_poll(struct input_polled_dev *dev) | ||||
| { | ||||
| 	struct gpio_buttons_dev *bdev = dev->private; | ||||
| 	struct gpio_buttons_platform_data *pdata = bdev->pdata; | ||||
| 	struct input_dev *input = dev->input; | ||||
| 	int i; | ||||
|  | ||||
| 	for (i = 0; i < bdev->pdata->nbuttons; i++) { | ||||
| 		struct gpio_button *button = &pdata->buttons[i]; | ||||
| 		unsigned int type = button->type ?: EV_KEY; | ||||
| 		int state; | ||||
|  | ||||
| 		state = gpio_get_value(button->gpio) ? 1 : 0; | ||||
| 		state ^= button->active_low; | ||||
|  | ||||
| 		if (state) { | ||||
| 			button->count++; | ||||
| 		} else { | ||||
| 			if (button->count >= button->threshold) { | ||||
| 				input_event(input, type, button->code, 1); | ||||
| 				input_sync(input); | ||||
| 			} | ||||
| 			button->count = 0; | ||||
| 		} | ||||
|  | ||||
| 		if (button->count == button->threshold) { | ||||
| 			input_event(input, type, button->code, 0); | ||||
| 			input_sync(input); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static int __devinit gpio_buttons_probe(struct platform_device *pdev) | ||||
| { | ||||
| 	struct gpio_buttons_platform_data *pdata = pdev->dev.platform_data; | ||||
| 	struct gpio_buttons_dev *bdev; | ||||
| 	struct input_polled_dev *poll_dev; | ||||
| 	struct input_dev *input; | ||||
| 	int error, i; | ||||
|  | ||||
|  | ||||
| 	if (!pdata) | ||||
| 		return -ENXIO; | ||||
|  | ||||
| 	bdev = kzalloc(sizeof(*bdev), GFP_KERNEL); | ||||
| 	if (!bdev) { | ||||
| 		printk(KERN_ERR DRV_NAME "no memory for device\n"); | ||||
| 		return -ENOMEM; | ||||
| 	} | ||||
|  | ||||
| 	poll_dev = input_allocate_polled_device(); | ||||
| 	if (!poll_dev) { | ||||
| 		printk(KERN_ERR DRV_NAME "no memory for polled device\n"); | ||||
| 		error = -ENOMEM; | ||||
| 		goto err_free_bdev; | ||||
| 	} | ||||
|  | ||||
| 	poll_dev->private = bdev; | ||||
| 	poll_dev->poll = gpio_buttons_poll; | ||||
| 	poll_dev->poll_interval = pdata->poll_interval; | ||||
|  | ||||
| 	input = poll_dev->input; | ||||
|  | ||||
| 	input->evbit[0] = BIT(EV_KEY); | ||||
| 	input->name = pdev->name; | ||||
| 	input->phys = "gpio-buttons/input0"; | ||||
| 	input->dev.parent = &pdev->dev; | ||||
|  | ||||
| 	input->id.bustype = BUS_HOST; | ||||
| 	input->id.vendor = 0x0001; | ||||
| 	input->id.product = 0x0001; | ||||
| 	input->id.version = 0x0100; | ||||
|  | ||||
| 	for (i = 0; i < pdata->nbuttons; i++) { | ||||
| 		struct gpio_button *button = &pdata->buttons[i]; | ||||
| 		unsigned int gpio = button->gpio; | ||||
| 		unsigned int type = button->type ?: EV_KEY; | ||||
|  | ||||
| 		error = gpio_request(gpio, button->desc ? | ||||
| 				button->desc : DRV_NAME); | ||||
| 		if (error) { | ||||
| 			printk(KERN_ERR PFX "unable to claim gpio %u, " | ||||
| 				"error %d\n", gpio, error); | ||||
| 			goto err_free_gpio; | ||||
| 		} | ||||
|  | ||||
| 		error = gpio_direction_input(gpio); | ||||
| 		if (error) { | ||||
| 			printk(KERN_ERR PFX "unable to set direction on " | ||||
| 				"gpio %u, error %d\n", gpio, error); | ||||
| 			goto err_free_gpio; | ||||
| 		} | ||||
|  | ||||
| 		input_set_capability(input, type, button->code); | ||||
| 		button->count = 0; | ||||
| 	} | ||||
|  | ||||
| 	bdev->poll_dev = poll_dev; | ||||
| 	bdev->pdata = pdata; | ||||
| 	platform_set_drvdata(pdev, bdev); | ||||
|  | ||||
| 	error = input_register_polled_device(poll_dev); | ||||
| 	if (error) { | ||||
| 		printk(KERN_ERR PFX "unable to register polled device, " | ||||
| 			"error %d\n", error); | ||||
| 		goto err_free_gpio; | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
|  | ||||
| err_free_gpio: | ||||
| 	for (i = i - 1; i >= 0; i--) | ||||
| 		gpio_free(pdata->buttons[i].gpio); | ||||
|  | ||||
| 	input_free_polled_device(poll_dev); | ||||
|  | ||||
| err_free_bdev: | ||||
| 	kfree(bdev); | ||||
|  | ||||
| 	platform_set_drvdata(pdev, NULL); | ||||
| 	return error; | ||||
| } | ||||
|  | ||||
| static int __devexit gpio_buttons_remove(struct platform_device *pdev) | ||||
| { | ||||
| 	struct gpio_buttons_dev *bdev = platform_get_drvdata(pdev); | ||||
| 	struct gpio_buttons_platform_data *pdata = bdev->pdata; | ||||
| 	int i; | ||||
|  | ||||
| 	input_unregister_polled_device(bdev->poll_dev); | ||||
|  | ||||
| 	for (i = 0; i < pdata->nbuttons; i++) | ||||
| 		gpio_free(pdata->buttons[i].gpio); | ||||
|  | ||||
| 	input_free_polled_device(bdev->poll_dev); | ||||
|  | ||||
| 	kfree(bdev); | ||||
| 	platform_set_drvdata(pdev, NULL); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static struct platform_driver gpio_buttons_driver = { | ||||
| 	.probe	= gpio_buttons_probe, | ||||
| 	.remove	= __devexit_p(gpio_buttons_remove), | ||||
| 	.driver	= { | ||||
| 		.name	= DRV_NAME, | ||||
| 		.owner	= THIS_MODULE, | ||||
| 	}, | ||||
| }; | ||||
|  | ||||
| static int __init gpio_buttons_init(void) | ||||
| { | ||||
| 	printk(KERN_INFO DRV_NAME " driver version " DRV_VERSION "\n"); | ||||
| 	return platform_driver_register(&gpio_buttons_driver); | ||||
| } | ||||
|  | ||||
| static void __exit gpio_buttons_exit(void) | ||||
| { | ||||
| 	platform_driver_unregister(&gpio_buttons_driver); | ||||
| } | ||||
|  | ||||
| module_init(gpio_buttons_init); | ||||
| module_exit(gpio_buttons_exit); | ||||
|  | ||||
| MODULE_LICENSE("GPL"); | ||||
| MODULE_AUTHOR("Gabor Juhos <juhosg at openwrt.org>"); | ||||
| MODULE_VERSION(DRV_VERSION); | ||||
| MODULE_DESCRIPTION("Polled buttons driver for CPU GPIOs"); | ||||
|  | ||||
| @@ -1,172 +0,0 @@ | ||||
| /* | ||||
|  * LEDs driver for PCEngines ALIX 2/3 series | ||||
|  * | ||||
|  * Copyright (C) 2007 Petr Liebman | ||||
|  * | ||||
|  * Based on leds-wrap.c | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License version 2 as | ||||
|  * published by the Free Software Foundation. | ||||
|  */ | ||||
|  | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/platform_device.h> | ||||
| #include <linux/leds.h> | ||||
| #include <linux/err.h> | ||||
| #include <asm/io.h> | ||||
|  | ||||
| #define DRVNAME "alix-led" | ||||
|  | ||||
| #define ALIX_LED1_PORT		(0x6100) | ||||
| #define ALIX_LED1_ON		(1<<22) | ||||
| #define ALIX_LED1_OFF		(1<<6) | ||||
|  | ||||
| #define ALIX_LED2_PORT		(0x6180) | ||||
| #define ALIX_LED2_ON		(1<<25) | ||||
| #define ALIX_LED2_OFF		(1<<9) | ||||
|  | ||||
| #define ALIX_LED3_PORT		(0x6180) | ||||
| #define ALIX_LED3_ON		(1<<27) | ||||
| #define ALIX_LED3_OFF		(1<<11) | ||||
|  | ||||
|  | ||||
| static struct platform_device *pdev; | ||||
|  | ||||
| static void alix_led_set_1(struct led_classdev *led_cdev, | ||||
| 		enum led_brightness value) | ||||
| { | ||||
| 	if (value) | ||||
| 		outl(ALIX_LED1_ON, ALIX_LED1_PORT); | ||||
| 	else | ||||
| 		outl(ALIX_LED1_OFF, ALIX_LED1_PORT); | ||||
| } | ||||
|  | ||||
| static void alix_led_set_2(struct led_classdev *led_cdev, | ||||
| 		enum led_brightness value) | ||||
| { | ||||
| 	if (value) | ||||
| 		outl(ALIX_LED2_ON, ALIX_LED2_PORT); | ||||
| 	else | ||||
| 		outl(ALIX_LED2_OFF, ALIX_LED2_PORT); | ||||
| } | ||||
|  | ||||
| static void alix_led_set_3(struct led_classdev *led_cdev, | ||||
| 		enum led_brightness value) | ||||
| { | ||||
| 	if (value) | ||||
| 		outl(ALIX_LED3_ON, ALIX_LED3_PORT); | ||||
| 	else | ||||
| 		outl(ALIX_LED3_OFF, ALIX_LED3_PORT); | ||||
| } | ||||
|  | ||||
| static struct led_classdev alix_led_1 = { | ||||
| 	.name		= "alix:1", | ||||
| 	.brightness_set	= alix_led_set_1, | ||||
| }; | ||||
|  | ||||
| static struct led_classdev alix_led_2 = { | ||||
| 	.name		= "alix:2", | ||||
| 	.brightness_set	= alix_led_set_2, | ||||
| }; | ||||
|  | ||||
| static struct led_classdev alix_led_3 = { | ||||
| 	.name		= "alix:3", | ||||
| 	.brightness_set	= alix_led_set_3, | ||||
| }; | ||||
|  | ||||
|  | ||||
| #ifdef CONFIG_PM | ||||
| static int alix_led_suspend(struct platform_device *dev, | ||||
| 		pm_message_t state) | ||||
| { | ||||
| 	led_classdev_suspend(&alix_led_1); | ||||
| 	led_classdev_suspend(&alix_led_2); | ||||
| 	led_classdev_suspend(&alix_led_3); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int alix_led_resume(struct platform_device *dev) | ||||
| { | ||||
| 	led_classdev_resume(&alix_led_1); | ||||
| 	led_classdev_resume(&alix_led_2); | ||||
| 	led_classdev_resume(&alix_led_3); | ||||
| 	return 0; | ||||
| } | ||||
| #else | ||||
| #define alix_led_suspend NULL | ||||
| #define alix_led_resume NULL | ||||
| #endif | ||||
|  | ||||
| static int alix_led_probe(struct platform_device *pdev) | ||||
| { | ||||
| 	int ret; | ||||
|  | ||||
| 	ret = led_classdev_register(&pdev->dev, &alix_led_1); | ||||
| 	if (ret >= 0) | ||||
| 	{ | ||||
| 		ret = led_classdev_register(&pdev->dev, &alix_led_2); | ||||
| 		if (ret >= 0) | ||||
| 		{ | ||||
| 			ret = led_classdev_register(&pdev->dev, &alix_led_3); | ||||
| 			if (ret < 0) | ||||
| 				led_classdev_unregister(&alix_led_2); | ||||
| 		} | ||||
| 		if (ret < 0) | ||||
| 			led_classdev_unregister(&alix_led_1); | ||||
| 	} | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| static int alix_led_remove(struct platform_device *pdev) | ||||
| { | ||||
| 	led_classdev_unregister(&alix_led_1); | ||||
| 	led_classdev_unregister(&alix_led_2); | ||||
| 	led_classdev_unregister(&alix_led_3); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static struct platform_driver alix_led_driver = { | ||||
| 	.probe		= alix_led_probe, | ||||
| 	.remove		= alix_led_remove, | ||||
| 	.suspend	= alix_led_suspend, | ||||
| 	.resume		= alix_led_resume, | ||||
| 	.driver		= { | ||||
| 		.name		= DRVNAME, | ||||
| 		.owner		= THIS_MODULE, | ||||
| 	}, | ||||
| }; | ||||
|  | ||||
| static int __init alix_led_init(void) | ||||
| { | ||||
| 	int ret; | ||||
|  | ||||
| 	ret = platform_driver_register(&alix_led_driver); | ||||
| 	if (ret < 0) | ||||
| 		goto out; | ||||
|  | ||||
| 	pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); | ||||
| 	if (IS_ERR(pdev)) { | ||||
| 		ret = PTR_ERR(pdev); | ||||
| 		platform_driver_unregister(&alix_led_driver); | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| out: | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| static void __exit alix_led_exit(void) | ||||
| { | ||||
| 	platform_device_unregister(pdev); | ||||
| 	platform_driver_unregister(&alix_led_driver); | ||||
| } | ||||
|  | ||||
| module_init(alix_led_init); | ||||
| module_exit(alix_led_exit); | ||||
|  | ||||
| MODULE_AUTHOR("Petr Liebman"); | ||||
| MODULE_DESCRIPTION("PCEngines ALIX LED driver"); | ||||
| MODULE_LICENSE("GPL"); | ||||
|  | ||||
| @@ -1,365 +0,0 @@ | ||||
| /* | ||||
|  *  LED Morse Trigger | ||||
|  * | ||||
|  *  Copyright (C) 2007 Gabor Juhos <juhosg at openwrt.org> | ||||
|  * | ||||
|  *  This file was based on: drivers/led/ledtrig-timer.c | ||||
|  *	Copyright 2005-2006 Openedhand Ltd. | ||||
|  *	Author: Richard Purdie <rpurdie@openedhand.com> | ||||
|  * | ||||
|  *  also based on the patch '[PATCH] 2.5.59 morse code panics' posted | ||||
|  *  in the LKML by Tomas Szepe at Thu, 30 Jan 2003 | ||||
|  *	Copyright (C) 2002 Andrew Rodland <arodland@noln.com> | ||||
|  *	Copyright (C) 2003 Tomas Szepe <szepe@pinerecords.com> | ||||
|  * | ||||
|  *  This program is free software; you can redistribute it and/or modify it | ||||
|  *  under the terms of the GNU General Public License version 2 as published | ||||
|  *  by the Free Software Foundation. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/version.h> | ||||
| #include <linux/module.h> | ||||
| #include <linux/jiffies.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/list.h> | ||||
| #include <linux/spinlock.h> | ||||
| #include <linux/device.h> | ||||
| #include <linux/sysdev.h> | ||||
| #include <linux/timer.h> | ||||
| #include <linux/ctype.h> | ||||
| #include <linux/leds.h> | ||||
|  | ||||
| #include "leds.h" | ||||
|  | ||||
| #define MORSE_DELAY_BASE	(HZ/2) | ||||
|  | ||||
| #define MORSE_STATE_BLINK_START	0 | ||||
| #define MORSE_STATE_BLINK_STOP	1 | ||||
|  | ||||
| #define MORSE_DIT_LEN	1 | ||||
| #define MORSE_DAH_LEN	3 | ||||
| #define MORSE_SPACE_LEN	7 | ||||
|  | ||||
| struct morse_trig_data { | ||||
| 	unsigned long delay; | ||||
| 	char *msg; | ||||
|  | ||||
| 	unsigned char morse; | ||||
| 	unsigned char state; | ||||
| 	char *msgpos; | ||||
| 	struct timer_list timer; | ||||
| }; | ||||
|  | ||||
| const unsigned char morsetable[] = { | ||||
| 	0122, 0, 0310, 0, 0, 0163,				/* "#$%&' */ | ||||
| 	055, 0155, 0, 0, 0163, 0141, 0152, 0051, 		/* ()*+,-./ */ | ||||
| 	077, 076, 074, 070, 060, 040, 041, 043, 047, 057,	/* 0-9 */ | ||||
| 	0107, 0125, 0, 0061, 0, 0114, 0, 			/* :;<=>?@ */ | ||||
| 	006, 021, 025, 011, 002, 024, 013, 020, 004,		/* A-I */ | ||||
| 	036, 015, 022, 007, 005, 017, 026, 033, 012,		/* J-R */ | ||||
| 	010, 003, 014, 030, 016, 031, 035, 023,			/* S-Z */ | ||||
| 	0, 0, 0, 0, 0154					/* [\]^_ */ | ||||
| }; | ||||
|  | ||||
| static inline unsigned char tomorse(char c) { | ||||
| 	if (c >= 'a' && c <= 'z') | ||||
| 		c = c - 'a' + 'A'; | ||||
| 	if (c >= '"' && c <= '_') { | ||||
| 		return morsetable[c - '"']; | ||||
| 	} else | ||||
| 		return 0; | ||||
| } | ||||
|  | ||||
| static inline unsigned long dit_len(struct morse_trig_data *morse_data) | ||||
| { | ||||
| 	return MORSE_DIT_LEN*morse_data->delay; | ||||
| } | ||||
|  | ||||
| static inline unsigned long dah_len(struct morse_trig_data *morse_data) | ||||
| { | ||||
| 	return MORSE_DAH_LEN*morse_data->delay; | ||||
| } | ||||
|  | ||||
| static inline unsigned long space_len(struct morse_trig_data *morse_data) | ||||
| { | ||||
| 	return MORSE_SPACE_LEN*morse_data->delay; | ||||
| } | ||||
|  | ||||
| static void morse_timer_function(unsigned long data) | ||||
| { | ||||
| 	struct led_classdev *led_cdev = (struct led_classdev *)data; | ||||
| 	struct morse_trig_data *morse_data = led_cdev->trigger_data; | ||||
| 	unsigned long brightness = LED_OFF; | ||||
| 	unsigned long delay = 0; | ||||
|  | ||||
| 	if (!morse_data->msg) | ||||
| 		goto set_led; | ||||
|  | ||||
| 	switch (morse_data->state) { | ||||
| 	case MORSE_STATE_BLINK_START: | ||||
| 		/* Starting a new blink.  We have a valid code in morse. */ | ||||
| 		delay = (morse_data->morse & 001) ? dah_len(morse_data): | ||||
| 			dit_len(morse_data); | ||||
| 		brightness = LED_FULL; | ||||
| 		morse_data->state = MORSE_STATE_BLINK_STOP; | ||||
| 		morse_data->morse >>= 1; | ||||
| 		break; | ||||
| 	case MORSE_STATE_BLINK_STOP: | ||||
| 		/* Coming off of a blink. */ | ||||
| 		morse_data->state = MORSE_STATE_BLINK_START; | ||||
|  | ||||
| 		if (morse_data->morse > 1) { | ||||
| 			/* Not done yet, just a one-dit pause. */ | ||||
| 			delay = dit_len(morse_data); | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 		/* Get a new char, figure out how much space. */ | ||||
| 		/* First time through */ | ||||
| 		if (!morse_data->msgpos) | ||||
| 			morse_data->msgpos = (char *)morse_data->msg; | ||||
|  | ||||
| 		if (!*morse_data->msgpos) { | ||||
| 			/* Repeating */ | ||||
| 			morse_data->msgpos = (char *)morse_data->msg; | ||||
| 			delay = space_len(morse_data); | ||||
| 		} else { | ||||
| 			/* Inter-letter space */ | ||||
| 			delay = dah_len(morse_data); | ||||
| 		} | ||||
|  | ||||
| 		if (!(morse_data->morse = tomorse(*morse_data->msgpos))) { | ||||
| 			delay = space_len(morse_data); | ||||
| 			/* And get us back here */ | ||||
| 			morse_data->state = MORSE_STATE_BLINK_STOP; | ||||
| 		} | ||||
| 		morse_data->msgpos++; | ||||
| 		break; | ||||
| 	} | ||||
|  | ||||
| 	mod_timer(&morse_data->timer, jiffies + msecs_to_jiffies(delay)); | ||||
|  | ||||
| set_led: | ||||
| 	led_set_brightness(led_cdev, brightness); | ||||
| } | ||||
|  | ||||
| static ssize_t _morse_delay_show(struct led_classdev *led_cdev, char *buf) | ||||
| { | ||||
| 	struct morse_trig_data *morse_data = led_cdev->trigger_data; | ||||
|  | ||||
| 	sprintf(buf, "%lu\n", morse_data->delay); | ||||
|  | ||||
| 	return strlen(buf) + 1; | ||||
| } | ||||
|  | ||||
| static ssize_t _morse_delay_store(struct led_classdev *led_cdev, | ||||
| 		const char *buf, size_t size) | ||||
| { | ||||
| 	struct morse_trig_data *morse_data = led_cdev->trigger_data; | ||||
| 	char *after; | ||||
| 	unsigned long state = simple_strtoul(buf, &after, 10); | ||||
| 	size_t count = after - buf; | ||||
| 	int ret = -EINVAL; | ||||
|  | ||||
| 	if (*after && isspace(*after)) | ||||
| 		count++; | ||||
|  | ||||
| 	if (count == size) { | ||||
| 		morse_data->delay = state; | ||||
| 		mod_timer(&morse_data->timer, jiffies + 1); | ||||
| 		ret = count; | ||||
| 	} | ||||
|  | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| static ssize_t _morse_msg_show(struct led_classdev *led_cdev, char *buf) | ||||
| { | ||||
| 	struct morse_trig_data *morse_data = led_cdev->trigger_data; | ||||
|  | ||||
| 	if (!morse_data->msg) | ||||
| 		sprintf(buf, "<none>\n"); | ||||
| 	else | ||||
| 		sprintf(buf, "%s\n", morse_data->msg); | ||||
|  | ||||
| 	return strlen(buf) + 1; | ||||
| } | ||||
|  | ||||
| static ssize_t _morse_msg_store(struct led_classdev *led_cdev, | ||||
| 		const char *buf, size_t size) | ||||
| { | ||||
| 	struct morse_trig_data *morse_data = led_cdev->trigger_data; | ||||
| 	char *m; | ||||
|  | ||||
| 	m = kmalloc(size, GFP_KERNEL); | ||||
| 	if (!m) | ||||
| 		return -ENOMEM; | ||||
|  | ||||
| 	memcpy(m,buf,size); | ||||
| 	m[size]='\0'; | ||||
|  | ||||
| 	if (morse_data->msg) | ||||
| 		kfree(morse_data->msg); | ||||
|  | ||||
| 	morse_data->msg = m; | ||||
| 	morse_data->msgpos = NULL; | ||||
| 	morse_data->state = MORSE_STATE_BLINK_STOP; | ||||
|  | ||||
| 	mod_timer(&morse_data->timer, jiffies + 1); | ||||
|  | ||||
| 	return size; | ||||
| } | ||||
|  | ||||
| #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) | ||||
| static ssize_t morse_delay_show(struct device *dev, | ||||
| 		struct device_attribute *attr, char *buf) | ||||
| { | ||||
| 	struct led_classdev *led_cdev = dev_get_drvdata(dev); | ||||
|  | ||||
| 	return _morse_delay_show(led_cdev, buf); | ||||
| } | ||||
|  | ||||
| static ssize_t morse_delay_store(struct device *dev, | ||||
| 		struct device_attribute *attr, const char *buf, size_t size) | ||||
| { | ||||
| 	struct led_classdev *led_cdev = dev_get_drvdata(dev); | ||||
|  | ||||
| 	return _morse_delay_store(led_cdev, buf, size); | ||||
| } | ||||
|  | ||||
| static ssize_t morse_msg_show(struct device *dev, | ||||
| 		struct device_attribute *attr, char *buf) | ||||
| { | ||||
| 	struct led_classdev *led_cdev = dev_get_drvdata(dev); | ||||
|  | ||||
| 	return _morse_msg_show(led_cdev, buf); | ||||
| } | ||||
|  | ||||
| static ssize_t morse_msg_store(struct device *dev, | ||||
| 		struct device_attribute *attr, const char *buf, size_t size) | ||||
| { | ||||
| 	struct led_classdev *led_cdev = dev_get_drvdata(dev); | ||||
|  | ||||
| 	return _morse_msg_store(led_cdev, buf, size); | ||||
| } | ||||
|  | ||||
| static DEVICE_ATTR(delay, 0644, morse_delay_show, morse_delay_store); | ||||
| static DEVICE_ATTR(message, 0644, morse_msg_show, morse_msg_store); | ||||
|  | ||||
| #define led_device_create_file(leddev, attr) \ | ||||
| 	device_create_file(leddev->dev, &dev_attr_ ## attr) | ||||
| #define led_device_remove_file(leddev, attr) \ | ||||
| 	device_remove_file(leddev->dev, &dev_attr_ ## attr) | ||||
|  | ||||
| #else | ||||
| static ssize_t morse_delay_show(struct class_device *dev, char *buf) | ||||
| { | ||||
| 	struct led_classdev *led_cdev = class_get_devdata(dev); | ||||
|  | ||||
| 	return _morse_delay_show(led_cdev, buf); | ||||
| } | ||||
|  | ||||
| static ssize_t morse_delay_store(struct class_device *dev, const char *buf, | ||||
| 		size_t size) | ||||
| { | ||||
| 	struct led_classdev *led_cdev = class_get_devdata(dev); | ||||
|  | ||||
| 	return _morse_delay_store(led_cdev, buf, size); | ||||
| } | ||||
|  | ||||
| static ssize_t morse_msg_show(struct class_device *dev, char *buf) | ||||
| { | ||||
| 	struct led_classdev *led_cdev = class_get_devdata(dev); | ||||
|  | ||||
| 	return _morse_msg_show(led_cdev, buf); | ||||
| } | ||||
|  | ||||
| static ssize_t morse_msg_store(struct class_device *dev, const char *buf, | ||||
| 				size_t size) | ||||
| { | ||||
| 	struct led_classdev *led_cdev = class_get_devdata(dev); | ||||
|  | ||||
| 	return _morse_msg_store(led_cdev, buf, size); | ||||
| } | ||||
|  | ||||
| static CLASS_DEVICE_ATTR(delay, 0644, morse_delay_show, morse_delay_store); | ||||
| static CLASS_DEVICE_ATTR(message, 0644, morse_msg_show, morse_msg_store); | ||||
|  | ||||
| #define led_device_create_file(leddev, attr) \ | ||||
| 	class_device_create_file(leddev->class_dev, &class_device_attr_ ## attr) | ||||
| #define led_device_remove_file(leddev, attr) \ | ||||
| 	class_device_remove_file(leddev->class_dev, &class_device_attr_ ## attr) | ||||
|  | ||||
| #endif | ||||
|  | ||||
| static void morse_trig_activate(struct led_classdev *led_cdev) | ||||
| { | ||||
| 	struct morse_trig_data *morse_data; | ||||
| 	int rc; | ||||
|  | ||||
| 	morse_data = kzalloc(sizeof(*morse_data), GFP_KERNEL); | ||||
| 	if (!morse_data) | ||||
| 		return; | ||||
|  | ||||
| 	morse_data->delay = MORSE_DELAY_BASE; | ||||
| 	init_timer(&morse_data->timer); | ||||
| 	morse_data->timer.function = morse_timer_function; | ||||
| 	morse_data->timer.data = (unsigned long)led_cdev; | ||||
|  | ||||
| 	rc = led_device_create_file(led_cdev, delay); | ||||
| 	if (rc) goto err; | ||||
|  | ||||
| 	rc = led_device_create_file(led_cdev, message); | ||||
| 	if (rc) goto err_delay; | ||||
|  | ||||
| 	led_cdev->trigger_data = morse_data; | ||||
|  | ||||
| 	return; | ||||
|  | ||||
| err_delay: | ||||
| 	led_device_remove_file(led_cdev, delay); | ||||
| err: | ||||
| 	kfree(morse_data); | ||||
| } | ||||
|  | ||||
| static void morse_trig_deactivate(struct led_classdev *led_cdev) | ||||
| { | ||||
| 	struct morse_trig_data *morse_data = led_cdev->trigger_data; | ||||
|  | ||||
| 	if (!morse_data) | ||||
| 		return; | ||||
|  | ||||
| 	led_device_remove_file(led_cdev, message); | ||||
| 	led_device_remove_file(led_cdev, delay); | ||||
|  | ||||
| 	del_timer_sync(&morse_data->timer); | ||||
| 	if (morse_data->msg) | ||||
| 		kfree(morse_data->msg); | ||||
|  | ||||
| 	kfree(morse_data); | ||||
| } | ||||
|  | ||||
| static struct led_trigger morse_led_trigger = { | ||||
| 	.name		= "morse", | ||||
| 	.activate	= morse_trig_activate, | ||||
| 	.deactivate	= morse_trig_deactivate, | ||||
| }; | ||||
|  | ||||
| static int __init morse_trig_init(void) | ||||
| { | ||||
| 	return led_trigger_register(&morse_led_trigger); | ||||
| } | ||||
|  | ||||
| static void __exit morse_trig_exit(void) | ||||
| { | ||||
| 	led_trigger_unregister(&morse_led_trigger); | ||||
| } | ||||
|  | ||||
| module_init(morse_trig_init); | ||||
| module_exit(morse_trig_exit); | ||||
|  | ||||
| MODULE_AUTHOR("Gabor Juhos <juhosg at openwrt.org>"); | ||||
| MODULE_DESCRIPTION("Morse LED trigger"); | ||||
| MODULE_LICENSE("GPL"); | ||||
| @@ -1,451 +0,0 @@ | ||||
| /* | ||||
|  * LED Kernel Netdev Trigger | ||||
|  * | ||||
|  * Toggles the LED to reflect the link and traffic state of a named net device | ||||
|  * | ||||
|  * Copyright 2007 Oliver Jowett <oliver@opencloud.com> | ||||
|  * | ||||
|  * Derived from ledtrig-timer.c which is: | ||||
|  *  Copyright 2005-2006 Openedhand Ltd. | ||||
|  *  Author: Richard Purdie <rpurdie@openedhand.com> | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License version 2 as | ||||
|  * published by the Free Software Foundation. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #include <linux/module.h> | ||||
| #include <linux/jiffies.h> | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/list.h> | ||||
| #include <linux/spinlock.h> | ||||
| #include <linux/device.h> | ||||
| #include <linux/sysdev.h> | ||||
| #include <linux/netdevice.h> | ||||
| #include <linux/timer.h> | ||||
| #include <linux/ctype.h> | ||||
| #include <linux/leds.h> | ||||
| #include <linux/version.h> | ||||
|  | ||||
| #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) | ||||
| #include <net/net_namespace.h> | ||||
| #endif | ||||
|  | ||||
| #include "leds.h" | ||||
|  | ||||
| /* | ||||
|  * Configurable sysfs attributes: | ||||
|  * | ||||
|  * device_name - network device name to monitor | ||||
|  * | ||||
|  * interval - duration of LED blink, in milliseconds | ||||
|  * | ||||
|  * mode - either "none" (LED is off) or a space separated list of one or more of: | ||||
|  *   link: LED's normal state reflects whether the link is up (has carrier) or not | ||||
|  *   tx:   LED blinks on transmitted data | ||||
|  *   rx:   LED blinks on receive data | ||||
|  *  | ||||
|  * Some suggestions: | ||||
|  * | ||||
|  *  Simple link status LED: | ||||
|  *  $ echo netdev >someled/trigger | ||||
|  *  $ echo eth0 >someled/device_name | ||||
|  *  $ echo link >someled/mode | ||||
|  * | ||||
|  *  Ethernet-style link/activity LED: | ||||
|  *  $ echo netdev >someled/trigger | ||||
|  *  $ echo eth0 >someled/device_name | ||||
|  *  $ echo "link tx rx" >someled/mode | ||||
|  * | ||||
|  *  Modem-style tx/rx LEDs: | ||||
|  *  $ echo netdev >led1/trigger | ||||
|  *  $ echo ppp0 >led1/device_name | ||||
|  *  $ echo tx >led1/mode | ||||
|  *  $ echo netdev >led2/trigger | ||||
|  *  $ echo ppp0 >led2/device_name | ||||
|  *  $ echo rx >led2/mode | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #define MODE_LINK 1 | ||||
| #define MODE_TX   2 | ||||
| #define MODE_RX   4 | ||||
|  | ||||
| struct led_netdev_data { | ||||
| 	rwlock_t lock; | ||||
|  | ||||
| 	struct timer_list timer; | ||||
| 	struct notifier_block notifier; | ||||
|  | ||||
| 	struct led_classdev *led_cdev; | ||||
| 	struct net_device *net_dev; | ||||
|  | ||||
| 	char device_name[IFNAMSIZ]; | ||||
| 	unsigned interval; | ||||
| 	unsigned mode; | ||||
| 	unsigned link_up; | ||||
| 	unsigned last_activity; | ||||
| }; | ||||
|  | ||||
| static void set_baseline_state(struct led_netdev_data *trigger_data) | ||||
| { | ||||
| 	if ((trigger_data->mode & MODE_LINK) != 0 && trigger_data->link_up) | ||||
| 		led_set_brightness(trigger_data->led_cdev, LED_FULL); | ||||
| 	else | ||||
| 		led_set_brightness(trigger_data->led_cdev, LED_OFF); | ||||
|  | ||||
| 	if ((trigger_data->mode & (MODE_TX | MODE_RX)) != 0 && trigger_data->link_up) | ||||
| 		mod_timer(&trigger_data->timer, jiffies + trigger_data->interval); | ||||
| 	else | ||||
| 		del_timer(&trigger_data->timer); | ||||
| } | ||||
|  | ||||
| static ssize_t led_device_name_show(struct device *dev, | ||||
| 				    struct device_attribute *attr, char *buf) | ||||
| { | ||||
| 	struct led_classdev *led_cdev = dev_get_drvdata(dev); | ||||
| 	struct led_netdev_data *trigger_data = led_cdev->trigger_data; | ||||
|  | ||||
| 	read_lock(&trigger_data->lock); | ||||
| 	sprintf(buf, "%s\n", trigger_data->device_name); | ||||
| 	read_unlock(&trigger_data->lock); | ||||
|  | ||||
| 	return strlen(buf) + 1; | ||||
| } | ||||
|  | ||||
| #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) | ||||
| extern struct net init_net; | ||||
| #endif | ||||
|  | ||||
| static ssize_t led_device_name_store(struct device *dev, | ||||
| 				     struct device_attribute *attr, const char *buf, size_t size) | ||||
| { | ||||
| 	struct led_classdev *led_cdev = dev_get_drvdata(dev); | ||||
| 	struct led_netdev_data *trigger_data = led_cdev->trigger_data; | ||||
|  | ||||
| 	if (size < 0 || size >= IFNAMSIZ) | ||||
| 		return -EINVAL; | ||||
|  | ||||
| 	write_lock(&trigger_data->lock); | ||||
|  | ||||
| 	strcpy(trigger_data->device_name, buf); | ||||
| 	if (size > 0 && trigger_data->device_name[size-1] == '\n') | ||||
| 		trigger_data->device_name[size-1] = 0; | ||||
|  | ||||
| 	if (trigger_data->device_name[0] != 0) { | ||||
| 		/* check for existing device to update from */ | ||||
| #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) | ||||
| 		trigger_data->net_dev = dev_get_by_name(&init_net, trigger_data->device_name); | ||||
| #else | ||||
| 		trigger_data->net_dev = dev_get_by_name(trigger_data->device_name); | ||||
| #endif | ||||
| 		if (trigger_data->net_dev != NULL) | ||||
| 			trigger_data->link_up = (dev_get_flags(trigger_data->net_dev) & IFF_LOWER_UP) != 0; | ||||
| 		set_baseline_state(trigger_data); /* updates LEDs, may start timers */ | ||||
| 	} | ||||
|  | ||||
| 	write_unlock(&trigger_data->lock); | ||||
| 	return size; | ||||
| } | ||||
|  | ||||
| static DEVICE_ATTR(device_name, 0644, led_device_name_show, led_device_name_store); | ||||
|  | ||||
| static ssize_t led_mode_show(struct device *dev, | ||||
| 			     struct device_attribute *attr, char *buf) | ||||
| { | ||||
| 	struct led_classdev *led_cdev = dev_get_drvdata(dev); | ||||
| 	struct led_netdev_data *trigger_data = led_cdev->trigger_data; | ||||
|  | ||||
| 	read_lock(&trigger_data->lock); | ||||
|  | ||||
| 	if (trigger_data->mode == 0) { | ||||
| 		strcpy(buf, "none\n"); | ||||
| 	} else { | ||||
| 		if (trigger_data->mode & MODE_LINK) | ||||
| 			strcat(buf, "link "); | ||||
| 		if (trigger_data->mode & MODE_TX) | ||||
| 			strcat(buf, "tx "); | ||||
| 		if (trigger_data->mode & MODE_RX) | ||||
| 			strcat(buf, "rx "); | ||||
| 		strcat(buf, "\n"); | ||||
| 	} | ||||
|  | ||||
| 	read_unlock(&trigger_data->lock); | ||||
|  | ||||
| 	return strlen(buf)+1; | ||||
| } | ||||
|  | ||||
| static ssize_t led_mode_store(struct device *dev, | ||||
| 			      struct device_attribute *attr, const char *buf, size_t size) | ||||
| { | ||||
| 	struct led_classdev *led_cdev = dev_get_drvdata(dev); | ||||
| 	struct led_netdev_data *trigger_data = led_cdev->trigger_data; | ||||
| 	char copybuf[1024]; | ||||
| 	int new_mode = -1; | ||||
| 	char *p, *token; | ||||
|  | ||||
| 	/* take a copy since we don't want to trash the inbound buffer when using strsep */ | ||||
| 	strncpy(copybuf, buf, sizeof(copybuf)); | ||||
| 	copybuf[1023] = 0; | ||||
| 	p = copybuf; | ||||
|  | ||||
| 	while ((token = strsep(&p, " \t\n")) != NULL) { | ||||
| 		if (!*token) | ||||
| 			continue; | ||||
|  | ||||
| 		if (new_mode == -1) | ||||
| 			new_mode = 0; | ||||
|  | ||||
| 		if (!strcmp(token, "none")) | ||||
| 			new_mode = 0; | ||||
| 		else if (!strcmp(token, "tx")) | ||||
| 			new_mode |= MODE_TX; | ||||
| 		else if (!strcmp(token, "rx")) | ||||
| 			new_mode |= MODE_RX; | ||||
| 		else if (!strcmp(token, "link")) | ||||
| 			new_mode |= MODE_LINK; | ||||
| 		else | ||||
| 			return -EINVAL; | ||||
| 	} | ||||
|  | ||||
| 	if (new_mode == -1) | ||||
| 		return -EINVAL; | ||||
|  | ||||
| 	write_lock(&trigger_data->lock); | ||||
| 	trigger_data->mode = new_mode; | ||||
| 	set_baseline_state(trigger_data); | ||||
| 	write_unlock(&trigger_data->lock); | ||||
|  | ||||
| 	return size; | ||||
| } | ||||
|  | ||||
| static DEVICE_ATTR(mode, 0644, led_mode_show, led_mode_store); | ||||
|  | ||||
| static ssize_t led_interval_show(struct device *dev, | ||||
| 				 struct device_attribute *attr, char *buf) | ||||
| { | ||||
| 	struct led_classdev *led_cdev = dev_get_drvdata(dev); | ||||
| 	struct led_netdev_data *trigger_data = led_cdev->trigger_data; | ||||
|  | ||||
| 	read_lock(&trigger_data->lock); | ||||
| 	sprintf(buf, "%u\n", jiffies_to_msecs(trigger_data->interval)); | ||||
| 	read_unlock(&trigger_data->lock); | ||||
|  | ||||
| 	return strlen(buf) + 1; | ||||
| } | ||||
|  | ||||
| static ssize_t led_interval_store(struct device *dev, | ||||
| 				  struct device_attribute *attr, const char *buf, size_t size) | ||||
| { | ||||
| 	struct led_classdev *led_cdev = dev_get_drvdata(dev); | ||||
| 	struct led_netdev_data *trigger_data = led_cdev->trigger_data; | ||||
| 	int ret = -EINVAL; | ||||
| 	char *after; | ||||
| 	unsigned long value = simple_strtoul(buf, &after, 10); | ||||
| 	size_t count = after - buf; | ||||
|  | ||||
| 	if (*after && isspace(*after)) | ||||
| 		count++; | ||||
|  | ||||
| 	/* impose some basic bounds on the timer interval */ | ||||
| 	if (count == size && value >= 5 && value <= 10000) { | ||||
| 		write_lock(&trigger_data->lock); | ||||
| 		trigger_data->interval = msecs_to_jiffies(value); | ||||
| 		set_baseline_state(trigger_data); // resets timer | ||||
| 		write_unlock(&trigger_data->lock); | ||||
| 		ret = count; | ||||
| 	} | ||||
|  | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| static DEVICE_ATTR(interval, 0644, led_interval_show, led_interval_store); | ||||
|  | ||||
| static int netdev_trig_notify(struct notifier_block *nb, | ||||
| 			      unsigned long evt, | ||||
| 			      void *dv) | ||||
| { | ||||
| 	struct net_device *dev = dv; | ||||
| 	struct led_netdev_data *trigger_data = container_of(nb, struct led_netdev_data, notifier); | ||||
|  | ||||
| 	if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER) | ||||
| 		return NOTIFY_DONE; | ||||
|  | ||||
| 	write_lock(&trigger_data->lock); | ||||
|  | ||||
| 	if (strcmp(dev->name, trigger_data->device_name)) | ||||
| 		goto done; | ||||
|  | ||||
| 	if (evt == NETDEV_REGISTER) { | ||||
| 		if (trigger_data->net_dev != NULL) | ||||
| 			dev_put(trigger_data->net_dev); | ||||
| 		dev_hold(dev); | ||||
| 		trigger_data->net_dev = dev; | ||||
| 		trigger_data->link_up = 0; | ||||
| 		goto done; | ||||
| 	} | ||||
|  | ||||
| 	if (evt == NETDEV_UNREGISTER && trigger_data->net_dev != NULL) { | ||||
| 		dev_put(trigger_data->net_dev); | ||||
| 		trigger_data->net_dev = NULL; | ||||
| 		goto done; | ||||
| 	} | ||||
|  | ||||
| 	/* UP / DOWN / CHANGE */ | ||||
|  | ||||
| 	trigger_data->link_up = (evt != NETDEV_DOWN && netif_carrier_ok(dev)); | ||||
| 	set_baseline_state(trigger_data); | ||||
|  | ||||
| done: | ||||
| 	write_unlock(&trigger_data->lock); | ||||
| 	return NOTIFY_DONE; | ||||
| } | ||||
|  | ||||
| /* here's the real work! */ | ||||
| static void netdev_trig_timer(unsigned long arg) | ||||
| { | ||||
| 	struct led_netdev_data *trigger_data = (struct led_netdev_data *)arg; | ||||
| 	struct net_device_stats *dev_stats; | ||||
| 	unsigned new_activity; | ||||
|  | ||||
| 	write_lock(&trigger_data->lock); | ||||
|  | ||||
| 	if (!trigger_data->link_up || !trigger_data->net_dev || (trigger_data->mode & (MODE_TX | MODE_RX)) == 0) { | ||||
| 		/* we don't need to do timer work, just reflect link state. */ | ||||
| 		led_set_brightness(trigger_data->led_cdev, ((trigger_data->mode & MODE_LINK) != 0 && trigger_data->link_up) ? LED_FULL : LED_OFF); | ||||
| 		goto no_restart; | ||||
| 	} | ||||
|  | ||||
| 	dev_stats = trigger_data->net_dev->get_stats(trigger_data->net_dev); | ||||
| 	new_activity = | ||||
| 		((trigger_data->mode & MODE_TX) ? dev_stats->tx_packets : 0) + | ||||
| 		((trigger_data->mode & MODE_RX) ? dev_stats->rx_packets : 0); | ||||
|  | ||||
| 	if (trigger_data->mode & MODE_LINK) { | ||||
| 		/* base state is ON (link present) */ | ||||
| 		/* if there's no link, we don't get this far and the LED is off */ | ||||
|  | ||||
| 		/* OFF -> ON always */ | ||||
| 		/* ON -> OFF on activity */ | ||||
| 		if (trigger_data->led_cdev->brightness == LED_OFF) { | ||||
| 			led_set_brightness(trigger_data->led_cdev, LED_FULL); | ||||
| 		} else if (trigger_data->last_activity != new_activity) { | ||||
| 			led_set_brightness(trigger_data->led_cdev, LED_OFF); | ||||
| 		} | ||||
| 	} else { | ||||
| 		/* base state is OFF */ | ||||
| 		/* ON -> OFF always */ | ||||
| 		/* OFF -> ON on activity */ | ||||
| 		if (trigger_data->led_cdev->brightness == LED_FULL) { | ||||
| 			led_set_brightness(trigger_data->led_cdev, LED_OFF); | ||||
| 		} else if (trigger_data->last_activity != new_activity) { | ||||
| 			led_set_brightness(trigger_data->led_cdev, LED_FULL); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	trigger_data->last_activity = new_activity; | ||||
| 	mod_timer(&trigger_data->timer, jiffies + trigger_data->interval); | ||||
|  | ||||
| no_restart: | ||||
| 	write_unlock(&trigger_data->lock); | ||||
| } | ||||
|  | ||||
| static void netdev_trig_activate(struct led_classdev *led_cdev) | ||||
| { | ||||
| 	struct led_netdev_data *trigger_data; | ||||
| 	int rc; | ||||
|  | ||||
| 	trigger_data = kzalloc(sizeof(struct led_netdev_data), GFP_KERNEL); | ||||
| 	if (!trigger_data) | ||||
| 		return; | ||||
|  | ||||
| 	rwlock_init(&trigger_data->lock); | ||||
|  | ||||
| 	trigger_data->notifier.notifier_call = netdev_trig_notify; | ||||
| 	trigger_data->notifier.priority = 10; | ||||
|  | ||||
| 	setup_timer(&trigger_data->timer, netdev_trig_timer, (unsigned long) trigger_data); | ||||
|  | ||||
| 	trigger_data->led_cdev = led_cdev; | ||||
| 	trigger_data->net_dev = NULL; | ||||
| 	trigger_data->device_name[0] = 0; | ||||
|  | ||||
| 	trigger_data->mode = 0; | ||||
| 	trigger_data->interval = msecs_to_jiffies(50); | ||||
| 	trigger_data->link_up = 0; | ||||
| 	trigger_data->last_activity = 0; | ||||
|  | ||||
| 	led_cdev->trigger_data = trigger_data; | ||||
|  | ||||
| 	rc = device_create_file(led_cdev->dev, &dev_attr_device_name); | ||||
| 	if (rc) | ||||
| 		goto err_out; | ||||
| 	rc = device_create_file(led_cdev->dev, &dev_attr_mode); | ||||
| 	if (rc) | ||||
| 		goto err_out_device_name; | ||||
| 	rc = device_create_file(led_cdev->dev, &dev_attr_interval); | ||||
| 	if (rc) | ||||
| 		goto err_out_mode; | ||||
|  | ||||
| 	register_netdevice_notifier(&trigger_data->notifier); | ||||
| 	return; | ||||
|  | ||||
| err_out_mode: | ||||
| 	device_remove_file(led_cdev->dev, &dev_attr_mode); | ||||
| err_out_device_name: | ||||
| 	device_remove_file(led_cdev->dev, &dev_attr_device_name); | ||||
| err_out: | ||||
| 	led_cdev->trigger_data = NULL; | ||||
| 	kfree(trigger_data); | ||||
| } | ||||
|  | ||||
| static void netdev_trig_deactivate(struct led_classdev *led_cdev) | ||||
| { | ||||
| 	struct led_netdev_data *trigger_data = led_cdev->trigger_data; | ||||
|  | ||||
| 	if (trigger_data) { | ||||
| 		unregister_netdevice_notifier(&trigger_data->notifier); | ||||
|  | ||||
| 		device_remove_file(led_cdev->dev, &dev_attr_device_name); | ||||
| 		device_remove_file(led_cdev->dev, &dev_attr_mode); | ||||
| 		device_remove_file(led_cdev->dev, &dev_attr_interval); | ||||
|  | ||||
| 		write_lock(&trigger_data->lock); | ||||
|  | ||||
| 		if (trigger_data->net_dev) { | ||||
| 			dev_put(trigger_data->net_dev); | ||||
| 			trigger_data->net_dev = NULL; | ||||
| 		} | ||||
|  | ||||
| 		write_unlock(&trigger_data->lock); | ||||
|  | ||||
| 		del_timer_sync(&trigger_data->timer); | ||||
|  | ||||
| 		kfree(trigger_data); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static struct led_trigger netdev_led_trigger = { | ||||
| 	.name     = "netdev", | ||||
| 	.activate = netdev_trig_activate, | ||||
| 	.deactivate = netdev_trig_deactivate, | ||||
| }; | ||||
|  | ||||
| static int __init netdev_trig_init(void) | ||||
| { | ||||
| 	return led_trigger_register(&netdev_led_trigger); | ||||
| } | ||||
|  | ||||
| static void __exit netdev_trig_exit(void) | ||||
| { | ||||
| 	led_trigger_unregister(&netdev_led_trigger); | ||||
| } | ||||
|  | ||||
| module_init(netdev_trig_init); | ||||
| module_exit(netdev_trig_exit); | ||||
|  | ||||
| MODULE_AUTHOR("Oliver Jowett <oliver@opencloud.com>"); | ||||
| MODULE_DESCRIPTION("Netdev LED trigger"); | ||||
| MODULE_LICENSE("GPL"); | ||||
| @@ -1,35 +0,0 @@ | ||||
| /* | ||||
|  *  Definitions for the GPIO buttons interface driver | ||||
|  * | ||||
|  *  Copyright (C) 2007,2008 Gabor Juhos <juhosg at openwrt.org> | ||||
|  * | ||||
|  *  This file was based on: /include/linux/gpio_keys.h | ||||
|  *	The original gpio_keys.h seems not to have a license. | ||||
|  * | ||||
|  *  This program is free software; you can redistribute it and/or modify | ||||
|  *  it under the terms of the GNU General Public License version 2 as | ||||
|  *  published by the Free Software Foundation. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifndef _GPIO_BUTTONS_H_ | ||||
| #define _GPIO_BUTTONS_H_ | ||||
|  | ||||
| struct gpio_button { | ||||
| 	int	gpio;		/* GPIO line number */ | ||||
| 	int	active_low; | ||||
| 	char	*desc;		/* button description */ | ||||
| 	int	type;		/* input event type (EV_KEY, EV_SW) */ | ||||
| 	int	code;		/* input event code (KEY_*, SW_*) */ | ||||
| 	int	count; | ||||
| 	int	threshold;	/* count threshold */ | ||||
| }; | ||||
|  | ||||
| struct gpio_buttons_platform_data { | ||||
| 	struct gpio_button *buttons; | ||||
| 	int	nbuttons;		/* number of buttons */ | ||||
| 	int	poll_interval;		/* polling interval */ | ||||
| }; | ||||
|  | ||||
| #endif /* _GPIO_BUTTONS_H_ */ | ||||
|  | ||||
| @@ -1,11 +0,0 @@ | ||||
| #ifndef _GPIODEV_H__ | ||||
| #define _GPIODEV_H__ | ||||
|  | ||||
| #define IOC_GPIODEV_MAGIC  'B' | ||||
| #define GPIO_GET        _IO(IOC_GPIODEV_MAGIC, 10) | ||||
| #define GPIO_SET        _IO(IOC_GPIODEV_MAGIC, 11) | ||||
| #define GPIO_CLEAR      _IO(IOC_GPIODEV_MAGIC, 12) | ||||
| #define GPIO_DIR_IN     _IO(IOC_GPIODEV_MAGIC, 13) | ||||
| #define GPIO_DIR_OUT    _IO(IOC_GPIODEV_MAGIC, 14) | ||||
|  | ||||
| #endif | ||||
| @@ -1,12 +0,0 @@ | ||||
| --- a/Makefile | ||||
| +++ b/Makefile | ||||
| @@ -560,6 +560,9 @@ endif | ||||
|  NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include) | ||||
|  CHECKFLAGS     += $(NOSTDINC_FLAGS) | ||||
|   | ||||
| +# improve gcc optimization | ||||
| +CFLAGS += $(call cc-option,-funit-at-a-time,) | ||||
| + | ||||
|  # warn about C99 declaration after statement | ||||
|  KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,) | ||||
|   | ||||
| @@ -1,11 +0,0 @@ | ||||
| --- a/arch/mips/include/asm/system.h | ||||
| +++ b/arch/mips/include/asm/system.h | ||||
| @@ -187,7 +187,7 @@ extern __u64 __xchg_u64_unsupported_on_3 | ||||
|     if something tries to do an invalid xchg().  */ | ||||
|  extern void __xchg_called_with_bad_pointer(void); | ||||
|   | ||||
| -static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size) | ||||
| +static __always_inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size) | ||||
|  { | ||||
|  	switch (size) { | ||||
|  	case 4: | ||||
| @@ -1,36 +0,0 @@ | ||||
| --- a/drivers/mtd/chips/cfi_cmdset_0002.c | ||||
| +++ b/drivers/mtd/chips/cfi_cmdset_0002.c | ||||
| @@ -51,6 +51,7 @@ | ||||
|  #define SST49LF040B	        0x0050 | ||||
|  #define SST49LF008A		0x005a | ||||
|  #define AT49BV6416		0x00d6 | ||||
| +#define MANUFACTURER_SAMSUNG	0x00ec | ||||
|   | ||||
|  static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); | ||||
|  static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); | ||||
| @@ -375,12 +376,19 @@ struct mtd_info *cfi_cmdset_0002(struct  | ||||
|   | ||||
|  		if (extp->MajorVersion != '1' || | ||||
|  		    (extp->MinorVersion < '0' || extp->MinorVersion > '4')) { | ||||
| -			printk(KERN_ERR "  Unknown Amd/Fujitsu Extended Query " | ||||
| -			       "version %c.%c.\n",  extp->MajorVersion, | ||||
| -			       extp->MinorVersion); | ||||
| -			kfree(extp); | ||||
| -			kfree(mtd); | ||||
| -			return NULL; | ||||
| +		        if (cfi->mfr == MANUFACTURER_SAMSUNG && | ||||
| +			    (extp->MajorVersion == '3' && extp->MinorVersion == '3')) { | ||||
| +			    printk(KERN_NOTICE "  Newer Samsung flash detected, " | ||||
| +			           "should be compatibile with Amd/Fujitsu.\n"); | ||||
| +		        } | ||||
| +		        else { | ||||
| +			    printk(KERN_ERR "  Unknown Amd/Fujitsu Extended Query " | ||||
| +			           "version %c.%c.\n",  extp->MajorVersion, | ||||
| +			           extp->MinorVersion); | ||||
| +			    kfree(extp); | ||||
| +			    kfree(mtd); | ||||
| +			    return NULL; | ||||
| +		        } | ||||
|  		} | ||||
|   | ||||
|  		/* Install our own private info structure */ | ||||
| @@ -1,11 +0,0 @@ | ||||
| --- a/arch/mips/kernel/head.S | ||||
| +++ b/arch/mips/kernel/head.S | ||||
| @@ -121,6 +121,8 @@ | ||||
|  #endif | ||||
|  	.endm | ||||
|   | ||||
| +	j kernel_entry | ||||
| +	nop | ||||
|  #ifndef CONFIG_NO_EXCEPT_FILL | ||||
|  	/* | ||||
|  	 * Reserved space for exception handlers. | ||||
| @@ -1,157 +0,0 @@ | ||||
| --- /dev/null | ||||
| +++ b/include/asm-mips/mips_machine.h | ||||
| @@ -0,0 +1,47 @@ | ||||
| +/* | ||||
| + *  Copyright (C) 2008 Gabor Juhos <juhosg@openwrt.org> | ||||
| + * | ||||
| + *  This program is free software; you can redistribute it and/or modify it | ||||
| + *  under the terms of the GNU General Public License version 2 as published | ||||
| + *  by the Free Software Foundation. | ||||
| + * | ||||
| + */ | ||||
| + | ||||
| +#ifndef __ASM_MIPS_MACHINE_H | ||||
| +#define __ASM_MIPS_MACHINE_H | ||||
| + | ||||
| +#include <linux/init.h> | ||||
| +#include <linux/list.h> | ||||
| + | ||||
| +#define MIPS_MACHINE_NAME_LEN	64 | ||||
| + | ||||
| +struct mips_machine { | ||||
| +	unsigned long		mach_type; | ||||
| +	void			(*mach_setup)(void); | ||||
| +	unsigned char		mach_name[MIPS_MACHINE_NAME_LEN]; | ||||
| +	struct list_head	list; | ||||
| +}; | ||||
| + | ||||
| +void mips_machine_register(struct mips_machine *) __init; | ||||
| +void mips_machine_setup(unsigned long machtype) __init; | ||||
| + | ||||
| +extern unsigned char mips_machine_name[MIPS_MACHINE_NAME_LEN]; | ||||
| + | ||||
| +#define MIPS_MACHINE(_type, _name, _setup) 			\ | ||||
| +static struct mips_machine machine_##_type __initdata =		\ | ||||
| +{								\ | ||||
| +	.mach_type	= _type,				\ | ||||
| +	.mach_name	= _name,				\ | ||||
| +	.mach_setup	= _setup,				\ | ||||
| +};								\ | ||||
| +								\ | ||||
| +static int __init register_machine_##_type(void)		\ | ||||
| +{								\ | ||||
| +	mips_machine_register(&machine_##_type);		\ | ||||
| +	return 0;						\ | ||||
| +}								\ | ||||
| +								\ | ||||
| +pure_initcall(register_machine_##_type) | ||||
| + | ||||
| +#endif /* __ASM_MIPS_MACHINE_H */ | ||||
| + | ||||
| --- /dev/null | ||||
| +++ b/arch/mips/kernel/mips_machine.c | ||||
| @@ -0,0 +1,58 @@ | ||||
| +/* | ||||
| + *  Copyright (C) 2008 Gabor Juhos <juhosg@openwrt.org> | ||||
| + * | ||||
| + *  This program is free software; you can redistribute it and/or modify it | ||||
| + *  under the terms of the GNU General Public License version 2 as published | ||||
| + *  by the Free Software Foundation. | ||||
| + * | ||||
| + */ | ||||
| + | ||||
| +#include <asm/mips_machine.h> | ||||
| +#include <asm/bootinfo.h> | ||||
| + | ||||
| +static struct list_head mips_machines __initdata = | ||||
| +		LIST_HEAD_INIT(mips_machines); | ||||
| + | ||||
| +unsigned char mips_machine_name[MIPS_MACHINE_NAME_LEN] = "Unknown"; | ||||
| + | ||||
| +static struct mips_machine * __init mips_machine_find(unsigned long machtype) | ||||
| +{ | ||||
| +	struct list_head *this; | ||||
| + | ||||
| +	list_for_each(this, &mips_machines) { | ||||
| +		struct mips_machine *mach; | ||||
| + | ||||
| +		mach = list_entry(this, struct mips_machine, list); | ||||
| +		if (mach->mach_type == machtype) | ||||
| +			return mach; | ||||
| +	} | ||||
| + | ||||
| +	return NULL; | ||||
| +} | ||||
| + | ||||
| +void __init mips_machine_register(struct mips_machine *mach) | ||||
| +{ | ||||
| +	list_add_tail(&mach->list, &mips_machines); | ||||
| +} | ||||
| + | ||||
| +void __init mips_machine_setup(unsigned long machtype) | ||||
| +{ | ||||
| +	struct mips_machine *mach; | ||||
| + | ||||
| +	mach = mips_machine_find(machtype); | ||||
| +	if (!mach) { | ||||
| +		printk(KERN_ALERT "MIPS: no machine registered for " | ||||
| +			"machtype %lu\n", machtype); | ||||
| +		return; | ||||
| +	} | ||||
| + | ||||
| +	if (mach->mach_name[0]) | ||||
| +		strncpy(mips_machine_name, mach->mach_name, | ||||
| +			MIPS_MACHINE_NAME_LEN); | ||||
| + | ||||
| +	printk(KERN_INFO "MIPS: machine is %s\n", mips_machine_name); | ||||
| + | ||||
| +	if (mach->mach_setup) | ||||
| +		mach->mach_setup(); | ||||
| +} | ||||
| + | ||||
| --- a/arch/mips/kernel/Makefile | ||||
| +++ b/arch/mips/kernel/Makefile | ||||
| @@ -85,6 +85,7 @@ obj-$(CONFIG_GPIO_TXX9)		+= gpio_txx9.o | ||||
|   | ||||
|  obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o | ||||
|  obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o | ||||
| +obj-$(CONFIG_MIPS_MACHINE)	+= mips_machine.o | ||||
|   | ||||
|  CFLAGS_cpu-bugs64.o	= $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi) | ||||
|   | ||||
| --- a/arch/mips/Kconfig | ||||
| +++ b/arch/mips/Kconfig | ||||
| @@ -810,6 +810,9 @@ config MIPS_DISABLE_OBSOLETE_IDE | ||||
|  config SYNC_R4K | ||||
|  	bool | ||||
|   | ||||
| +config MIPS_MACHINE | ||||
| +	def_bool n | ||||
| + | ||||
|  config NO_IOPORT | ||||
|  	def_bool n | ||||
|   | ||||
| --- a/arch/mips/kernel/proc.c | ||||
| +++ b/arch/mips/kernel/proc.c | ||||
| @@ -14,6 +14,7 @@ | ||||
|  #include <asm/cpu-features.h> | ||||
|  #include <asm/mipsregs.h> | ||||
|  #include <asm/processor.h> | ||||
| +#include <asm/mips_machine.h> | ||||
|   | ||||
|  unsigned int vced_count, vcei_count; | ||||
|   | ||||
| @@ -33,8 +34,12 @@ static int show_cpuinfo(struct seq_file  | ||||
|  	/* | ||||
|  	 * For the first processor also print the system type | ||||
|  	 */ | ||||
| -	if (n == 0) | ||||
| +	if (n == 0) { | ||||
|  		seq_printf(m, "system type\t\t: %s\n", get_system_type()); | ||||
| +#ifdef CONFIG_MIPS_MACHINE | ||||
| +		seq_printf(m, "machine\t\t\t: %s\n", mips_machine_name); | ||||
| +#endif | ||||
| +	} | ||||
|   | ||||
|  	seq_printf(m, "processor\t\t: %ld\n", n); | ||||
|  	sprintf(fmt, "cpu model\t\t: %%s V%%d.%%d%s\n", | ||||
| @@ -1,50 +0,0 @@ | ||||
| --- a/arch/mips/Kconfig | ||||
| +++ b/arch/mips/Kconfig | ||||
| @@ -812,6 +812,9 @@ config SYNC_R4K | ||||
|   | ||||
|  config MIPS_MACHINE | ||||
|  	def_bool n | ||||
| +	 | ||||
| +config PROM_EMU | ||||
| +	def_bool n | ||||
|   | ||||
|  config NO_IOPORT | ||||
|  	def_bool n | ||||
| --- a/arch/mips/kernel/head.S | ||||
| +++ b/arch/mips/kernel/head.S | ||||
| @@ -143,6 +143,15 @@ FEXPORT(__kernel_entry) | ||||
|  	j	kernel_entry | ||||
|  #endif | ||||
|   | ||||
| +#ifdef CONFIG_PROM_EMU | ||||
| +EXPORT(prom_emu_argv) | ||||
| +	.word	0 | ||||
| +	.word	prom_emu_cmdline | ||||
| +	.ascii	"CMDLINE:" | ||||
| +EXPORT(prom_emu_cmdline) | ||||
| +	.fill	0x400 | ||||
| +#endif | ||||
| + | ||||
|  	__REF | ||||
|   | ||||
|  NESTED(kernel_entry, 16, sp)			# kernel entry point | ||||
| @@ -183,6 +192,19 @@ NESTED(kernel_entry, 16, sp)			# kernel  | ||||
|  	LONG_S		zero, (t0) | ||||
|  	bne		t0, t1, 1b | ||||
|   | ||||
| +#ifdef CONFIG_PROM_EMU | ||||
| +	PTR_LA		t0, prom_emu_cmdline | ||||
| +	LONG_L		t1, 0(t0) | ||||
| +	beqz		t1, 1f | ||||
| + | ||||
| +	li		a0, 2 | ||||
| +	PTR_LA		a1, prom_emu_argv | ||||
| +	move		a2, zero | ||||
| +	move		a3, zero | ||||
| + | ||||
| +1: | ||||
| +#endif /* CONFIG_PROM_EMU */ | ||||
| + | ||||
|  	LONG_S		a0, fw_arg0		# firmware arguments | ||||
|  	LONG_S		a1, fw_arg1 | ||||
|  	LONG_S		a2, fw_arg2 | ||||
| @@ -1,171 +0,0 @@ | ||||
| From: Ralf Baechle <ralf@linux-mips.org> | ||||
| Date: Thu, 30 Apr 2009 16:14:56 +0000 (+0200) | ||||
| Subject: MIPS: Rewrite <asm/div64.h> to work with gcc 4.4.0. | ||||
| X-Git-Url: http://www.linux-mips.org/git?p=linux.git;a=commitdiff_plain;h=a1b68289997030df64cba8478d5767fe10e42a58 | ||||
|  | ||||
| MIPS: Rewrite <asm/div64.h> to work with gcc 4.4.0. | ||||
|  | ||||
| The inline assembler used on 32-bit kernels was using the "h" constraint | ||||
| which was considered dangerous and removed for gcc 4.4.0. | ||||
|  | ||||
| Signed-off-by: Ralf Baechle <ralf@linux-mips.org> | ||||
| --- | ||||
|  | ||||
| --- a/arch/mips/include/asm/div64.h | ||||
| +++ b/arch/mips/include/asm/div64.h | ||||
| @@ -6,105 +6,63 @@ | ||||
|   * License.  See the file "COPYING" in the main directory of this archive | ||||
|   * for more details. | ||||
|   */ | ||||
| -#ifndef _ASM_DIV64_H | ||||
| -#define _ASM_DIV64_H | ||||
| +#ifndef __ASM_DIV64_H | ||||
| +#define __ASM_DIV64_H | ||||
|   | ||||
| -#include <linux/types.h> | ||||
| +#include <asm-generic/div64.h> | ||||
|   | ||||
| -#if (_MIPS_SZLONG == 32) | ||||
| +#if BITS_PER_LONG == 64 | ||||
|   | ||||
| -#include <asm/compiler.h> | ||||
| +#include <linux/types.h> | ||||
|   | ||||
|  /* | ||||
|   * No traps on overflows for any of these... | ||||
|   */ | ||||
|   | ||||
| -#define do_div64_32(res, high, low, base) ({ \ | ||||
| -	unsigned long __quot32, __mod32; \ | ||||
| -	unsigned long __cf, __tmp, __tmp2, __i; \ | ||||
| -	\ | ||||
| -	__asm__(".set	push\n\t" \ | ||||
| -		".set	noat\n\t" \ | ||||
| -		".set	noreorder\n\t" \ | ||||
| -		"move	%2, $0\n\t" \ | ||||
| -		"move	%3, $0\n\t" \ | ||||
| -		"b	1f\n\t" \ | ||||
| -		" li	%4, 0x21\n" \ | ||||
| -		"0:\n\t" \ | ||||
| -		"sll	$1, %0, 0x1\n\t" \ | ||||
| -		"srl	%3, %0, 0x1f\n\t" \ | ||||
| -		"or	%0, $1, %5\n\t" \ | ||||
| -		"sll	%1, %1, 0x1\n\t" \ | ||||
| -		"sll	%2, %2, 0x1\n" \ | ||||
| -		"1:\n\t" \ | ||||
| -		"bnez	%3, 2f\n\t" \ | ||||
| -		" sltu	%5, %0, %z6\n\t" \ | ||||
| -		"bnez	%5, 3f\n" \ | ||||
| -		"2:\n\t" \ | ||||
| -		" addiu	%4, %4, -1\n\t" \ | ||||
| -		"subu	%0, %0, %z6\n\t" \ | ||||
| -		"addiu	%2, %2, 1\n" \ | ||||
| -		"3:\n\t" \ | ||||
| -		"bnez	%4, 0b\n\t" \ | ||||
| -		" srl	%5, %1, 0x1f\n\t" \ | ||||
| -		".set	pop" \ | ||||
| -		: "=&r" (__mod32), "=&r" (__tmp), \ | ||||
| -		  "=&r" (__quot32), "=&r" (__cf), \ | ||||
| -		  "=&r" (__i), "=&r" (__tmp2) \ | ||||
| -		: "Jr" (base), "0" (high), "1" (low)); \ | ||||
| -	\ | ||||
| -	(res) = __quot32; \ | ||||
| -	__mod32; }) | ||||
| - | ||||
| -#define do_div(n, base) ({ \ | ||||
| -	unsigned long long __quot; \ | ||||
| -	unsigned long __mod; \ | ||||
| -	unsigned long long __div; \ | ||||
| -	unsigned long __upper, __low, __high, __base; \ | ||||
| -	\ | ||||
| -	__div = (n); \ | ||||
| -	__base = (base); \ | ||||
| -	\ | ||||
| -	__high = __div >> 32; \ | ||||
| -	__low = __div; \ | ||||
| -	__upper = __high; \ | ||||
| -	\ | ||||
| -	if (__high) \ | ||||
| -		__asm__("divu	$0, %z2, %z3" \ | ||||
| -			: "=h" (__upper), "=l" (__high) \ | ||||
| -			: "Jr" (__high), "Jr" (__base) \ | ||||
| -			: GCC_REG_ACCUM); \ | ||||
| -	\ | ||||
| -	__mod = do_div64_32(__low, __upper, __low, __base); \ | ||||
| -	\ | ||||
| -	__quot = __high; \ | ||||
| -	__quot = __quot << 32 | __low; \ | ||||
| -	(n) = __quot; \ | ||||
| -	__mod; }) | ||||
| - | ||||
| -#endif /* (_MIPS_SZLONG == 32) */ | ||||
| - | ||||
| -#if (_MIPS_SZLONG == 64) | ||||
| - | ||||
| -/* | ||||
| - * Hey, we're already 64-bit, no | ||||
| - * need to play games.. | ||||
| - */ | ||||
| -#define do_div(n, base) ({ \ | ||||
| -	unsigned long __quot; \ | ||||
| -	unsigned int __mod; \ | ||||
| -	unsigned long __div; \ | ||||
| -	unsigned int __base; \ | ||||
| -	\ | ||||
| -	__div = (n); \ | ||||
| -	__base = (base); \ | ||||
| -	\ | ||||
| -	__mod = __div % __base; \ | ||||
| -	__quot = __div / __base; \ | ||||
| -	\ | ||||
| -	(n) = __quot; \ | ||||
| -	__mod; }) | ||||
| +#define __div64_32(n, base)						\ | ||||
| +({									\ | ||||
| +	unsigned long __cf, __tmp, __tmp2, __i;				\ | ||||
| +	unsigned long __quot32, __mod32;				\ | ||||
| +	unsigned long __high, __low;					\ | ||||
| +	unsigned long long __n;						\ | ||||
| +									\ | ||||
| +	__high = *__n >> 32;						\ | ||||
| +	__low = __n;							\ | ||||
| +	__asm__(							\ | ||||
| +	"	.set	push					\n"	\ | ||||
| +	"	.set	noat					\n"	\ | ||||
| +	"	.set	noreorder				\n"	\ | ||||
| +	"	move	%2, $0					\n"	\ | ||||
| +	"	move	%3, $0					\n"	\ | ||||
| +	"	b	1f					\n"	\ | ||||
| +	"	 li	%4, 0x21				\n"	\ | ||||
| +	"0:							\n"	\ | ||||
| +	"	sll	$1, %0, 0x1				\n"	\ | ||||
| +	"	srl	%3, %0, 0x1f				\n"	\ | ||||
| +	"	or	%0, $1, %5				\n"	\ | ||||
| +	"	sll	%1, %1, 0x1				\n"	\ | ||||
| +	"	sll	%2, %2, 0x1				\n"	\ | ||||
| +	"1:							\n"	\ | ||||
| +	"	bnez	%3, 2f					\n"	\ | ||||
| +	"	 sltu	%5, %0, %z6				\n"	\ | ||||
| +	"	bnez	%5, 3f					\n"	\ | ||||
| +	"2:							\n"	\ | ||||
| +	"	 addiu	%4, %4, -1				\n"	\ | ||||
| +	"	subu	%0, %0, %z6				\n"	\ | ||||
| +	"	addiu	%2, %2, 1				\n"	\ | ||||
| +	"3:							\n"	\ | ||||
| +	"	bnez	%4, 0b\n\t"					\ | ||||
| +	"	 srl	%5, %1, 0x1f\n\t"				\ | ||||
| +	"	.set	pop"						\ | ||||
| +	: "=&r" (__mod32), "=&r" (__tmp),				\ | ||||
| +	  "=&r" (__quot32), "=&r" (__cf),				\ | ||||
| +	  "=&r" (__i), "=&r" (__tmp2)					\ | ||||
| +	: "Jr" (base), "0" (__high), "1" (__low));			\ | ||||
| +									\ | ||||
| +	(__n) = __quot32;						\ | ||||
| +	__mod32;							\ | ||||
| +}) | ||||
|   | ||||
| -#endif /* (_MIPS_SZLONG == 64) */ | ||||
| +#endif /* BITS_PER_LONG == 64 */ | ||||
|   | ||||
| -#endif /* _ASM_DIV64_H */ | ||||
| +#endif /* __ASM_DIV64_H */ | ||||
| @@ -1,40 +0,0 @@ | ||||
| When init is started it is SIGNAL_UNKILLABLE.  If it were to get an | ||||
| address error, we would try to send it SIGBUS, but it would be ignored | ||||
| and the faulting instruction restarted.  This results in an endless | ||||
| loop. | ||||
|  | ||||
| We need to use force_sig() instead so it will actually die and give us | ||||
| some useful information. | ||||
|  | ||||
| Reported-by: Florian Fainelli <florian@openwrt.org> | ||||
|  | ||||
| Signed-off-by: David Daney <ddaney@caviumnetworks.com> | ||||
| --- | ||||
|  arch/mips/kernel/unaligned.c |    6 +++--- | ||||
|  1 files changed, 3 insertions(+), 3 deletions(-) | ||||
|  | ||||
| --- a/arch/mips/kernel/unaligned.c | ||||
| +++ b/arch/mips/kernel/unaligned.c | ||||
| @@ -482,19 +482,19 @@ fault: | ||||
|  		return; | ||||
|   | ||||
|  	die_if_kernel("Unhandled kernel unaligned access", regs); | ||||
| -	send_sig(SIGSEGV, current, 1); | ||||
| +	force_sig(SIGSEGV, current); | ||||
|   | ||||
|  	return; | ||||
|   | ||||
|  sigbus: | ||||
|  	die_if_kernel("Unhandled kernel unaligned access", regs); | ||||
| -	send_sig(SIGBUS, current, 1); | ||||
| +	force_sig(SIGBUS, current); | ||||
|   | ||||
|  	return; | ||||
|   | ||||
|  sigill: | ||||
|  	die_if_kernel("Unhandled kernel unaligned access or invalid instruction", regs); | ||||
| -	send_sig(SIGILL, current, 1); | ||||
| +	force_sig(SIGILL, current); | ||||
|  } | ||||
|   | ||||
|  asmlinkage void do_ade(struct pt_regs *regs) | ||||
| @@ -1,152 +0,0 @@ | ||||
| From: Wu Zhangjin <wuzj@lemote.com> | ||||
|  | ||||
| the gcc 4.4 support for MIPS mostly refer to this PATCH: | ||||
| http://www.nabble.com/-PATCH--MIPS:-Handle-removal-of-%27h%27-constraint-in-GCC-4.4-td22192768.html | ||||
| but have been tuned a little. | ||||
|  | ||||
| because only gcc 4.4 have loongson-specific support, so, we need to | ||||
| choose the suitable -march argument for gcc <= 4.3 and gcc >= 4.4, and | ||||
| we also need to consider use -march=loongson2e and -march=loongson2f for | ||||
| loongson2e and loongson2f respectively. this is handled by adding two | ||||
| new kernel options: CPU_LOONGSON2E and CPU_LOONGSON2F(thanks for the | ||||
| solutin provided by ZhangLe). | ||||
|  | ||||
| I have tested it on FuLoong(2f) in 32bit and 64bit with gcc-4.4 and | ||||
| gcc-4.3. so, basically, it works. | ||||
|  | ||||
| Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com> | ||||
| --- | ||||
|  arch/mips/Makefile               |    9 +++++- | ||||
|  arch/mips/include/asm/compiler.h |   10 ++++++ | ||||
|  arch/mips/include/asm/delay.h    |   58 +++++++++++++++++++++++++------------ | ||||
|  3 files changed, 57 insertions(+), 20 deletions(-) | ||||
|  | ||||
| --- a/arch/mips/Makefile | ||||
| +++ b/arch/mips/Makefile | ||||
| @@ -119,7 +119,14 @@ cflags-$(CONFIG_CPU_R4300)	+= -march=r43 | ||||
|  cflags-$(CONFIG_CPU_VR41XX)	+= -march=r4100 -Wa,--trap | ||||
|  cflags-$(CONFIG_CPU_R4X00)	+= -march=r4600 -Wa,--trap | ||||
|  cflags-$(CONFIG_CPU_TX49XX)	+= -march=r4600 -Wa,--trap | ||||
| -cflags-$(CONFIG_CPU_LOONGSON2)	+= -march=r4600 -Wa,--trap | ||||
| + | ||||
| +# only gcc >= 4.4 have the loongson-specific support | ||||
| +cflags-$(CONFIG_CPU_LOONGSON2)	+= -Wa,--trap | ||||
| +cflags-$(CONFIG_CPU_LOONGSON2E)	+= $(shell if [ $(call cc-version) -lt 0440 ] ; then \ | ||||
| +	echo $(call cc-option,-march=r4600); else echo $(call cc-option,-march=loongson2e); fi ;) | ||||
| +cflags-$(CONFIG_CPU_LOONGSON2F)	+= $(shell if [ $(call cc-version) -lt 0440 ] ; then \ | ||||
| +	echo $(call cc-option,-march=r4600); else echo $(call cc-option,-march=loongson2f); fi ;) | ||||
| + | ||||
|  cflags-$(CONFIG_CPU_MIPS32_R1)	+= $(call cc-option,-march=mips32,-mips32 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \ | ||||
|  			-Wa,-mips32 -Wa,--trap | ||||
|  cflags-$(CONFIG_CPU_MIPS32_R2)	+= $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \ | ||||
| --- a/arch/mips/include/asm/compiler.h | ||||
| +++ b/arch/mips/include/asm/compiler.h | ||||
| @@ -1,5 +1,6 @@ | ||||
|  /* | ||||
|   * Copyright (C) 2004, 2007  Maciej W. Rozycki | ||||
| + * Copyright (C) 2009  Wu Zhangjin, wuzj@lemote.com | ||||
|   * | ||||
|   * This file is subject to the terms and conditions of the GNU General Public | ||||
|   * License.  See the file "COPYING" in the main directory of this archive | ||||
| @@ -16,4 +17,13 @@ | ||||
|  #define GCC_REG_ACCUM "accum" | ||||
|  #endif | ||||
|   | ||||
| +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) | ||||
| +#define GCC_NO_H_CONSTRAINT | ||||
| +#ifdef CONFIG_64BIT | ||||
| +typedef unsigned int uintx_t __attribute__((mode(TI))); | ||||
| +#else | ||||
| +typedef u64 uintx_t; | ||||
| +#endif | ||||
| +#endif | ||||
| + | ||||
|  #endif /* _ASM_COMPILER_H */ | ||||
| --- a/arch/mips/include/asm/delay.h | ||||
| +++ b/arch/mips/include/asm/delay.h | ||||
| @@ -7,6 +7,7 @@ | ||||
|   * Copyright (C) 1995 - 2000, 01, 03 by Ralf Baechle | ||||
|   * Copyright (C) 1999, 2000 Silicon Graphics, Inc. | ||||
|   * Copyright (C) 2007  Maciej W. Rozycki | ||||
| + * Copyright (C) 2009  Wu Zhangjin, wuzj@lemote.com | ||||
|   */ | ||||
|  #ifndef _ASM_DELAY_H | ||||
|  #define _ASM_DELAY_H | ||||
| @@ -48,6 +49,43 @@ static inline void __delay(unsigned long | ||||
|  		: "0" (loops), "r" (1)); | ||||
|  } | ||||
|   | ||||
| +/* | ||||
| + * convert usecs to loops | ||||
| + * | ||||
| + * handle removal of 'h' constraint in GCC 4.4 | ||||
| + */ | ||||
| + | ||||
| +#ifndef GCC_NO_H_CONSTRAINT	/* gcc <= 4.3 */ | ||||
| +static inline unsigned long __usecs_to_loops(unsigned long usecs, | ||||
| +		unsigned long lpj) | ||||
| +{ | ||||
| +	unsigned long hi, lo; | ||||
| + | ||||
| +	if (sizeof(long) == 4) | ||||
| +		__asm__("multu\t%2, %3" | ||||
| +		: "=h" (usecs), "=l" (lo) | ||||
| +		: "r" (usecs), "r" (lpj) | ||||
| +		: GCC_REG_ACCUM); | ||||
| +	else if (sizeof(long) == 8 && !R4000_WAR) | ||||
| +		__asm__("dmultu\t%2, %3" | ||||
| +		: "=h" (usecs), "=l" (lo) | ||||
| +		: "r" (usecs), "r" (lpj) | ||||
| +		: GCC_REG_ACCUM); | ||||
| +	else if (sizeof(long) == 8 && R4000_WAR) | ||||
| +		__asm__("dmultu\t%3, %4\n\tmfhi\t%0" | ||||
| +		: "=r" (usecs), "=h" (hi), "=l" (lo) | ||||
| +		: "r" (usecs), "r" (lpj) | ||||
| +		: GCC_REG_ACCUM); | ||||
| + | ||||
| +	return usecs; | ||||
| +} | ||||
| +#else	/* GCC_NO_H_CONSTRAINT, gcc >= 4.4 */ | ||||
| +static inline unsigned long __usecs_to_loops(unsigned long usecs, | ||||
| +		unsigned long lpj) | ||||
| +{ | ||||
| +	return ((uintx_t)usecs * lpj) >> BITS_PER_LONG; | ||||
| +} | ||||
| +#endif | ||||
|   | ||||
|  /* | ||||
|   * Division by multiplication: you don't have to worry about | ||||
| @@ -62,8 +100,6 @@ static inline void __delay(unsigned long | ||||
|   | ||||
|  static inline void __udelay(unsigned long usecs, unsigned long lpj) | ||||
|  { | ||||
| -	unsigned long hi, lo; | ||||
| - | ||||
|  	/* | ||||
|  	 * The rates of 128 is rounded wrongly by the catchall case | ||||
|  	 * for 64-bit.  Excessive precission?  Probably ... | ||||
| @@ -77,23 +113,7 @@ static inline void __udelay(unsigned lon | ||||
|  	                           0x80000000ULL) >> 32); | ||||
|  #endif | ||||
|   | ||||
| -	if (sizeof(long) == 4) | ||||
| -		__asm__("multu\t%2, %3" | ||||
| -		: "=h" (usecs), "=l" (lo) | ||||
| -		: "r" (usecs), "r" (lpj) | ||||
| -		: GCC_REG_ACCUM); | ||||
| -	else if (sizeof(long) == 8 && !R4000_WAR) | ||||
| -		__asm__("dmultu\t%2, %3" | ||||
| -		: "=h" (usecs), "=l" (lo) | ||||
| -		: "r" (usecs), "r" (lpj) | ||||
| -		: GCC_REG_ACCUM); | ||||
| -	else if (sizeof(long) == 8 && R4000_WAR) | ||||
| -		__asm__("dmultu\t%3, %4\n\tmfhi\t%0" | ||||
| -		: "=r" (usecs), "=h" (hi), "=l" (lo) | ||||
| -		: "r" (usecs), "r" (lpj) | ||||
| -		: GCC_REG_ACCUM); | ||||
| - | ||||
| -	__delay(usecs); | ||||
| +	__delay(__usecs_to_loops(usecs, lpj)); | ||||
|  } | ||||
|   | ||||
|  #define __udelay_val cpu_data[raw_smp_processor_id()].udelay_val | ||||
| @@ -1,153 +0,0 @@ | ||||
| MIPS: allow disabling the kernel FPU emulator | ||||
|  | ||||
| This patch allows turning off the in-kernel Algorithmics | ||||
| FPU emulator support, which allows one to save a couple of | ||||
| precious blocks on an embedded system. | ||||
|  | ||||
| Signed-off-by: Florian Fainelli <florian@openwrt.org> | ||||
| -- | ||||
| --- a/arch/mips/Kconfig | ||||
| +++ b/arch/mips/Kconfig | ||||
| @@ -798,6 +798,17 @@ config I8259 | ||||
|  config MIPS_BONITO64 | ||||
|  	bool | ||||
|   | ||||
| +config MIPS_FPU_EMU | ||||
| +	bool | ||||
| +	default n | ||||
| +	help | ||||
| +	   This option allows building a kernel with or without the Algorithmics | ||||
| +	   FPU emulator enabled. Turning off this option results in a kernel which | ||||
| +	   does not catch floating operations exceptions. Make sure that your toolchain | ||||
| +	   is configured to enable software floating point emulation in that case. | ||||
| +		 | ||||
| +	   If unsure say Y here. | ||||
| + | ||||
|  config MIPS_MSC | ||||
|  	bool | ||||
|   | ||||
| --- a/arch/mips/math-emu/Makefile | ||||
| +++ b/arch/mips/math-emu/Makefile | ||||
| @@ -2,12 +2,14 @@ | ||||
|  # Makefile for the Linux/MIPS kernel FPU emulation. | ||||
|  # | ||||
|   | ||||
| -obj-y	:= cp1emu.o ieee754m.o ieee754d.o ieee754dp.o ieee754sp.o ieee754.o \ | ||||
| +obj-y	:=	kernel_linkage.o dsemul.o cp1emu.o | ||||
| + | ||||
| +obj-$(CONFIG_MIPS_FPU_EMU)	+= ieee754m.o ieee754d.o ieee754dp.o ieee754sp.o ieee754.o \ | ||||
|  	   ieee754xcpt.o dp_frexp.o dp_modf.o dp_div.o dp_mul.o dp_sub.o \ | ||||
|  	   dp_add.o dp_fsp.o dp_cmp.o dp_logb.o dp_scalb.o dp_simple.o \ | ||||
|  	   dp_tint.o dp_fint.o dp_tlong.o dp_flong.o sp_frexp.o sp_modf.o \ | ||||
|  	   sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o sp_cmp.o sp_logb.o \ | ||||
|  	   sp_scalb.o sp_simple.o sp_tint.o sp_fint.o sp_tlong.o sp_flong.o \ | ||||
| -	   dp_sqrt.o sp_sqrt.o kernel_linkage.o dsemul.o | ||||
| +	   dp_sqrt.o sp_sqrt.o | ||||
|   | ||||
|  EXTRA_CFLAGS += -Werror | ||||
| --- a/arch/mips/math-emu/cp1emu.c | ||||
| +++ b/arch/mips/math-emu/cp1emu.c | ||||
| @@ -56,6 +56,12 @@ | ||||
|  #endif | ||||
|  #define __mips 4 | ||||
|   | ||||
| +/* Further private data for which no space exists in mips_fpu_struct */ | ||||
| + | ||||
| +struct mips_fpu_emulator_stats fpuemustats; | ||||
| + | ||||
| +#ifdef CONFIG_MIPS_FPU_EMU | ||||
| + | ||||
|  /* Function which emulates a floating point instruction. */ | ||||
|   | ||||
|  static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *, | ||||
| @@ -66,10 +72,6 @@ static int fpux_emu(struct pt_regs *, | ||||
|  	struct mips_fpu_struct *, mips_instruction); | ||||
|  #endif | ||||
|   | ||||
| -/* Further private data for which no space exists in mips_fpu_struct */ | ||||
| - | ||||
| -struct mips_fpu_emulator_stats fpuemustats; | ||||
| - | ||||
|  /* Control registers */ | ||||
|   | ||||
|  #define FPCREG_RID	0	/* $0  = revision id */ | ||||
| @@ -1273,6 +1275,13 @@ int fpu_emulator_cop1Handler(struct pt_r | ||||
|   | ||||
|  	return sig; | ||||
|  } | ||||
| +#else | ||||
| +int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, | ||||
| +        int has_fpu) | ||||
| +{ | ||||
| +	return 0; | ||||
| +} | ||||
| +#endif /* CONFIG_MIPS_FPU_EMU */ | ||||
|   | ||||
|  #ifdef CONFIG_DEBUG_FS | ||||
|  extern struct dentry *mips_debugfs_dir; | ||||
| --- a/arch/mips/math-emu/dsemul.c | ||||
| +++ b/arch/mips/math-emu/dsemul.c | ||||
| @@ -109,6 +109,7 @@ int mips_dsemul(struct pt_regs *regs, mi | ||||
|  	return SIGILL;		/* force out of emulation loop */ | ||||
|  } | ||||
|   | ||||
| +#ifdef CONFIG_MIPS_FPU_EMU | ||||
|  int do_dsemulret(struct pt_regs *xcp) | ||||
|  { | ||||
|  	struct emuframe __user *fr; | ||||
| @@ -165,3 +166,9 @@ int do_dsemulret(struct pt_regs *xcp) | ||||
|   | ||||
|  	return 1; | ||||
|  } | ||||
| +#else | ||||
| +int do_dsemulret(struct pt_regs *xcp) | ||||
| +{ | ||||
| +	return 0; | ||||
| +} | ||||
| +#endif /* CONFIG_MIPS_FPU_EMU */ | ||||
| --- a/arch/mips/math-emu/kernel_linkage.c | ||||
| +++ b/arch/mips/math-emu/kernel_linkage.c | ||||
| @@ -29,6 +29,7 @@ | ||||
|   | ||||
|  #define SIGNALLING_NAN 0x7ff800007ff80000LL | ||||
|   | ||||
| +#ifdef CONFIG_MIPS_FPU_EMU | ||||
|  void fpu_emulator_init_fpu(void) | ||||
|  { | ||||
|  	static int first = 1; | ||||
| @@ -112,4 +113,34 @@ int fpu_emulator_restore_context32(struc | ||||
|   | ||||
|  	return err; | ||||
|  } | ||||
| -#endif | ||||
| +#endif	/* CONFIG_64BIT */ | ||||
| +#else | ||||
| + | ||||
| +void fpu_emulator_init_fpu(void) | ||||
| +{ | ||||
| +	return; | ||||
| +} | ||||
| + | ||||
| +int fpu_emulator_save_context(struct sigcontext __user *sc) | ||||
| +{ | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +int fpu_emulator_restore_context(struct sigcontext __user *sc) | ||||
| +{ | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +int fpu_emulator_save_context32(struct sigcontext32 __user *sc) | ||||
| +{ | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +int fpu_emulator_restore_context32(struct sigcontext32 __user *sc) | ||||
| +{ | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +#ifdef CONFIG_64BIT | ||||
| +#endif	/* CONFIG_64BIT */ | ||||
| +#endif /* CONFIG_MIPS_FPU_EMU */ | ||||
| @@ -1,42 +0,0 @@ | ||||
| From 819b4bda18d62b52d04789c4a8d4fc3fbf9ce242 Mon Sep 17 00:00:00 2001 | ||||
| From: Gabor Juhos <juhosg@openwrt.org> | ||||
| Date: Mon, 13 Jul 2009 10:46:49 +0200 | ||||
| Subject: [PATCH] MIPS: fix loading of modules with unresolved weak symbols | ||||
|  | ||||
| Loading of modules with unresolved weak symbols fails on MIPS | ||||
| since '88173507e4fc1e7ecd111b0565e8cba0cb7dae6d'. | ||||
|  | ||||
| Modules: handle symbols that have a zero value | ||||
|  | ||||
| The module subsystem cannot handle symbols that are zero.  If symbols | ||||
| are present that have a zero value then the module resolver prints out a | ||||
| message that these symbols are unresolved. | ||||
|  | ||||
| We have to use IS_ERR_VALUE() to check that a symbol has been resolved | ||||
| or not. | ||||
|  | ||||
| Signed-off-by: Gabor Juhos <juhosg@openwrt.org> | ||||
| --- | ||||
|  arch/mips/kernel/module.c |    4 ++-- | ||||
|  1 files changed, 2 insertions(+), 2 deletions(-) | ||||
|  | ||||
| --- a/arch/mips/kernel/module.c | ||||
| +++ b/arch/mips/kernel/module.c | ||||
| @@ -303,7 +303,7 @@ int apply_relocate(Elf_Shdr *sechdrs, co | ||||
|  		/* This is the symbol it is referring to */ | ||||
|  		sym = (Elf_Sym *)sechdrs[symindex].sh_addr | ||||
|  			+ ELF_MIPS_R_SYM(rel[i]); | ||||
| -		if (!sym->st_value) { | ||||
| +		if (IS_ERR_VALUE(sym->st_value)) { | ||||
|  			/* Ignore unresolved weak symbol */ | ||||
|  			if (ELF_ST_BIND(sym->st_info) == STB_WEAK) | ||||
|  				continue; | ||||
| @@ -343,7 +343,7 @@ int apply_relocate_add(Elf_Shdr *sechdrs | ||||
|  		/* This is the symbol it is referring to */ | ||||
|  		sym = (Elf_Sym *)sechdrs[symindex].sh_addr | ||||
|  			+ ELF_MIPS_R_SYM(rel[i]); | ||||
| -		if (!sym->st_value) { | ||||
| +		if (IS_ERR_VALUE(sym->st_value)) { | ||||
|  			/* Ignore unresolved weak symbol */ | ||||
|  			if (ELF_ST_BIND(sym->st_info) == STB_WEAK) | ||||
|  				continue; | ||||
| @@ -1,110 +0,0 @@ | ||||
| --- a/drivers/mtd/devices/block2mtd.c | ||||
| +++ b/drivers/mtd/devices/block2mtd.c | ||||
| @@ -14,6 +14,7 @@ | ||||
|  #include <linux/list.h> | ||||
|  #include <linux/init.h> | ||||
|  #include <linux/mtd/mtd.h> | ||||
| +#include <linux/mtd/partitions.h> | ||||
|  #include <linux/buffer_head.h> | ||||
|  #include <linux/mutex.h> | ||||
|  #include <linux/mount.h> | ||||
| @@ -232,10 +233,11 @@ static void block2mtd_free_device(struct | ||||
|   | ||||
|   | ||||
|  /* FIXME: ensure that mtd->size % erase_size == 0 */ | ||||
| -static struct block2mtd_dev *add_device(char *devname, int erase_size) | ||||
| +static struct block2mtd_dev *add_device(char *devname, int erase_size, const char *mtdname) | ||||
|  { | ||||
|  	struct block_device *bdev; | ||||
|  	struct block2mtd_dev *dev; | ||||
| +	struct mtd_partition *part; | ||||
|  	char *name; | ||||
|   | ||||
|  	if (!devname) | ||||
| @@ -273,17 +275,17 @@ static struct block2mtd_dev *add_device( | ||||
|   | ||||
|  	mutex_init(&dev->write_mutex); | ||||
|   | ||||
| -	/* Setup the MTD structure */ | ||||
| -	/* make the name contain the block device in */ | ||||
| -	name = kmalloc(sizeof("block2mtd: ") + strlen(devname) + 1, | ||||
| -			GFP_KERNEL); | ||||
| +	if (!mtdname) | ||||
| +		mtdname = devname; | ||||
| + | ||||
| +	name = kmalloc(strlen(mtdname) + 1, GFP_KERNEL); | ||||
|  	if (!name) | ||||
|  		goto devinit_err; | ||||
|   | ||||
| -	sprintf(name, "block2mtd: %s", devname); | ||||
| +	strcpy(name, mtdname); | ||||
|  	dev->mtd.name = name; | ||||
|   | ||||
| -	dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK; | ||||
| +	dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK & ~(erase_size - 1); | ||||
|  	dev->mtd.erasesize = erase_size; | ||||
|  	dev->mtd.writesize = 1; | ||||
|  	dev->mtd.type = MTD_RAM; | ||||
| @@ -296,14 +298,17 @@ static struct block2mtd_dev *add_device( | ||||
|  	dev->mtd.priv = dev; | ||||
|  	dev->mtd.owner = THIS_MODULE; | ||||
|   | ||||
| -	if (add_mtd_device(&dev->mtd)) { | ||||
| +	part = kzalloc(sizeof(struct mtd_partition), GFP_KERNEL); | ||||
| +	part->name = dev->mtd.name; | ||||
| +	part->offset = 0; | ||||
| +	part->size = dev->mtd.size; | ||||
| +	if (add_mtd_partitions(&dev->mtd, part, 1)) { | ||||
|  		/* Device didnt get added, so free the entry */ | ||||
|  		goto devinit_err; | ||||
|  	} | ||||
|  	list_add(&dev->list, &blkmtd_device_list); | ||||
|  	INFO("mtd%d: [%s] erase_size = %dKiB [%d]", dev->mtd.index, | ||||
| -			dev->mtd.name + strlen("block2mtd: "), | ||||
| -			dev->mtd.erasesize >> 10, dev->mtd.erasesize); | ||||
| +			mtdname, dev->mtd.erasesize >> 10, dev->mtd.erasesize); | ||||
|  	return dev; | ||||
|   | ||||
|  devinit_err: | ||||
| @@ -376,9 +381,9 @@ static char block2mtd_paramline[80 + 12] | ||||
|   | ||||
|  static int block2mtd_setup2(const char *val) | ||||
|  { | ||||
| -	char buf[80 + 12]; /* 80 for device, 12 for erase size */ | ||||
| +	char buf[80 + 12 + 80]; /* 80 for device, 12 for erase size, 80 for name */ | ||||
|  	char *str = buf; | ||||
| -	char *token[2]; | ||||
| +	char *token[3]; | ||||
|  	char *name; | ||||
|  	size_t erase_size = PAGE_SIZE; | ||||
|  	int i, ret; | ||||
| @@ -389,7 +394,7 @@ static int block2mtd_setup2(const char * | ||||
|  	strcpy(str, val); | ||||
|  	kill_final_newline(str); | ||||
|   | ||||
| -	for (i = 0; i < 2; i++) | ||||
| +	for (i = 0; i < 3; i++) | ||||
|  		token[i] = strsep(&str, ","); | ||||
|   | ||||
|  	if (str) | ||||
| @@ -408,8 +413,10 @@ static int block2mtd_setup2(const char * | ||||
|  			parse_err("illegal erase size"); | ||||
|  		} | ||||
|  	} | ||||
| +	if (token[2] && (strlen(token[2]) + 1 > 80)) | ||||
| +		parse_err("mtd device name too long"); | ||||
|   | ||||
| -	add_device(name, erase_size); | ||||
| +	add_device(name, erase_size, token[2]); | ||||
|   | ||||
|  	return 0; | ||||
|  } | ||||
| @@ -443,7 +450,7 @@ static int block2mtd_setup(const char *v | ||||
|   | ||||
|   | ||||
|  module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200); | ||||
| -MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>]\""); | ||||
| +MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>[,<name>]]\""); | ||||
|   | ||||
|  static int __init block2mtd_init(void) | ||||
|  { | ||||
| @@ -1,633 +0,0 @@ | ||||
| --- a/drivers/mtd/Kconfig | ||||
| +++ b/drivers/mtd/Kconfig | ||||
| @@ -53,6 +53,16 @@ config MTD_TESTS | ||||
|  	  should normally be compiled as kernel modules. The modules perform | ||||
|  	  various checks and verifications when loaded. | ||||
|   | ||||
| +config MTD_ROOTFS_ROOT_DEV | ||||
| +	bool "Automatically set 'rootfs' partition to be root filesystem" | ||||
| +	depends on MTD_PARTITIONS | ||||
| +	default y | ||||
| + | ||||
| +config MTD_ROOTFS_SPLIT | ||||
| +	bool "Automatically split 'rootfs' partition for squashfs" | ||||
| +	depends on MTD_PARTITIONS | ||||
| +	default y | ||||
| + | ||||
|  config MTD_REDBOOT_PARTS | ||||
|  	tristate "RedBoot partition table parsing" | ||||
|  	depends on MTD_PARTITIONS | ||||
| --- a/drivers/mtd/mtdpart.c | ||||
| +++ b/drivers/mtd/mtdpart.c | ||||
| @@ -18,6 +18,8 @@ | ||||
|  #include <linux/mtd/mtd.h> | ||||
|  #include <linux/mtd/partitions.h> | ||||
|  #include <linux/mtd/compatmac.h> | ||||
| +#include <linux/root_dev.h> | ||||
| +#include <linux/magic.h> | ||||
|   | ||||
|  /* Our partition linked list */ | ||||
|  static LIST_HEAD(mtd_partitions); | ||||
| @@ -37,7 +39,7 @@ struct mtd_part { | ||||
|   * the pointer to that structure with this macro. | ||||
|   */ | ||||
|  #define PART(x)  ((struct mtd_part *)(x)) | ||||
| - | ||||
| +#define IS_PART(mtd) (mtd->read == part_read) | ||||
|   | ||||
|  /* | ||||
|   * MTD methods which simply translate the effective address and pass through | ||||
| @@ -489,6 +491,156 @@ out_register: | ||||
|  	return slave; | ||||
|  } | ||||
|   | ||||
| +#ifdef CONFIG_MTD_ROOTFS_SPLIT | ||||
| +#define ROOTFS_SPLIT_NAME "rootfs_data" | ||||
| +#define ROOTFS_REMOVED_NAME "<removed>" | ||||
| + | ||||
| +struct squashfs_super_block { | ||||
| +	__le32 s_magic; | ||||
| +	__le32 pad0[9]; | ||||
| +	__le64 bytes_used; | ||||
| +}; | ||||
| + | ||||
| + | ||||
| +static int split_squashfs(struct mtd_info *master, int offset, int *split_offset) | ||||
| +{ | ||||
| +	char buf[512]; | ||||
| +	struct squashfs_super_block *sb = (struct squashfs_super_block *) buf; | ||||
| +	int len, ret; | ||||
| + | ||||
| +	ret = master->read(master, offset, sizeof(*sb), &len, buf); | ||||
| +	if (ret || (len != sizeof(*sb))) { | ||||
| +		printk(KERN_ALERT "split_squashfs: error occured while reading " | ||||
| +			"from \"%s\"\n", master->name); | ||||
| +		return -EINVAL; | ||||
| +	} | ||||
| + | ||||
| +	if (*((u32 *) buf) != SQUASHFS_MAGIC) { | ||||
| +		printk(KERN_ALERT "split_squashfs: no squashfs found in \"%s\"\n", | ||||
| +			master->name); | ||||
| +		*split_offset = 0; | ||||
| +		return 0; | ||||
| +	} | ||||
| + | ||||
| +	if (sb->bytes_used <= 0) { | ||||
| +		printk(KERN_ALERT "split_squashfs: squashfs is empty in \"%s\"\n", | ||||
| +			master->name); | ||||
| +		*split_offset = 0; | ||||
| +		return 0; | ||||
| +	} | ||||
| + | ||||
| +	len = (u32) sb->bytes_used; | ||||
| +	len += (offset & 0x000fffff); | ||||
| +	len +=  (master->erasesize - 1); | ||||
| +	len &= ~(master->erasesize - 1); | ||||
| +	len -= (offset & 0x000fffff); | ||||
| +	*split_offset = offset + len; | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static int split_rootfs_data(struct mtd_info *master, struct mtd_info *rpart, const struct mtd_partition *part, | ||||
| +		int index) | ||||
| +{ | ||||
| +	struct mtd_partition *dpart; | ||||
| +	struct mtd_part *slave = NULL; | ||||
| +	int split_offset = 0; | ||||
| +	int ret; | ||||
| + | ||||
| +	ret = split_squashfs(master, part->offset, &split_offset); | ||||
| +	if (ret) | ||||
| +		return ret; | ||||
| + | ||||
| +	if (split_offset <= 0) | ||||
| +		return 0; | ||||
| + | ||||
| +	dpart = kmalloc(sizeof(*part)+sizeof(ROOTFS_SPLIT_NAME)+1, GFP_KERNEL); | ||||
| +	if (dpart == NULL) { | ||||
| +		printk(KERN_INFO "split_squashfs: no memory for partition \"%s\"\n", | ||||
| +			ROOTFS_SPLIT_NAME); | ||||
| +		return -ENOMEM; | ||||
| +	} | ||||
| + | ||||
| +	memcpy(dpart, part, sizeof(*part)); | ||||
| +	dpart->name = (unsigned char *)&dpart[1]; | ||||
| +	strcpy(dpart->name, ROOTFS_SPLIT_NAME); | ||||
| + | ||||
| +	dpart->size -= split_offset - dpart->offset; | ||||
| +	dpart->offset = split_offset; | ||||
| + | ||||
| +	if (dpart == NULL) | ||||
| +		return 1; | ||||
| + | ||||
| +	printk(KERN_INFO "mtd: partition \"%s\" created automatically, ofs=%llX, len=%llX \n", | ||||
| +		ROOTFS_SPLIT_NAME, dpart->offset, dpart->size); | ||||
| + | ||||
| +	slave = add_one_partition(master, dpart, index, split_offset); | ||||
| +	if (!slave) { | ||||
| +		kfree(dpart); | ||||
| +		return -ENOMEM; | ||||
| +	} | ||||
| +	rpart->split = &slave->mtd; | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static int refresh_rootfs_split(struct mtd_info *mtd) | ||||
| +{ | ||||
| +	struct mtd_partition tpart; | ||||
| +	struct mtd_part *part; | ||||
| +	char *name; | ||||
| +	int index = 0; | ||||
| +	int offset, size; | ||||
| +	int ret; | ||||
| + | ||||
| +	part = PART(mtd); | ||||
| + | ||||
| +	/* check for the new squashfs offset first */ | ||||
| +	ret = split_squashfs(part->master, part->offset, &offset); | ||||
| +	if (ret) | ||||
| +		return ret; | ||||
| + | ||||
| +	if ((offset > 0) && !mtd->split) { | ||||
| +		printk(KERN_INFO "%s: creating new split partition for \"%s\"\n", __func__, mtd->name); | ||||
| +		/* if we don't have a rootfs split partition, create a new one */ | ||||
| +		tpart.name = (char *) mtd->name; | ||||
| +		tpart.size = mtd->size; | ||||
| +		tpart.offset = part->offset; | ||||
| + | ||||
| +		/* find the index of the last partition */ | ||||
| +		if (!list_empty(&mtd_partitions)) | ||||
| +			index = list_first_entry(&mtd_partitions, struct mtd_part, list)->index + 1; | ||||
| + | ||||
| +		return split_rootfs_data(part->master, &part->mtd, &tpart, index); | ||||
| +	} else if ((offset > 0) && mtd->split) { | ||||
| +		/* update the offsets of the existing partition */ | ||||
| +		size = mtd->size + part->offset - offset; | ||||
| + | ||||
| +		part = PART(mtd->split); | ||||
| +		part->offset = offset; | ||||
| +		part->mtd.size = size; | ||||
| +		printk(KERN_INFO "%s: %s partition \"" ROOTFS_SPLIT_NAME "\", offset: 0x%06x (0x%06x)\n", | ||||
| +			__func__, (!strcmp(part->mtd.name, ROOTFS_SPLIT_NAME) ? "updating" : "creating"), | ||||
| +			(u32) part->offset, (u32) part->mtd.size); | ||||
| +		name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL); | ||||
| +		strcpy(name, ROOTFS_SPLIT_NAME); | ||||
| +		part->mtd.name = name; | ||||
| +	} else if ((offset <= 0) && mtd->split) { | ||||
| +		printk(KERN_INFO "%s: removing partition \"%s\"\n", __func__, mtd->split->name); | ||||
| + | ||||
| +		/* mark existing partition as removed */ | ||||
| +		part = PART(mtd->split); | ||||
| +		name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL); | ||||
| +		strcpy(name, ROOTFS_REMOVED_NAME); | ||||
| +		part->mtd.name = name; | ||||
| +		part->offset = 0; | ||||
| +		part->mtd.size = 0; | ||||
| +	} | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| +#endif /* CONFIG_MTD_ROOTFS_SPLIT */ | ||||
| + | ||||
|  /* | ||||
|   * This function, given a master MTD object and a partition table, creates | ||||
|   * and registers slave MTD objects which are bound to the master according to | ||||
| @@ -502,14 +654,29 @@ int add_mtd_partitions(struct mtd_info * | ||||
|  { | ||||
|  	struct mtd_part *slave; | ||||
|  	uint64_t cur_offset = 0; | ||||
| -	int i; | ||||
| +	int i, j, ret; | ||||
|   | ||||
|  	printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name); | ||||
|   | ||||
| -	for (i = 0; i < nbparts; i++) { | ||||
| -		slave = add_one_partition(master, parts + i, i, cur_offset); | ||||
| +	for (i = 0, j = 0; i < nbparts; i++) { | ||||
| +		slave = add_one_partition(master, parts + i, j++, cur_offset); | ||||
|  		if (!slave) | ||||
|  			return -ENOMEM; | ||||
| + | ||||
| +		if (!strcmp(parts[i].name, "rootfs") && slave->registered) { | ||||
| +#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV | ||||
| +			if (ROOT_DEV == 0) { | ||||
| +				printk(KERN_NOTICE "mtd: partition \"rootfs\" " | ||||
| +					"set to be root filesystem\n"); | ||||
| +				ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, slave->mtd.index); | ||||
| +			} | ||||
| +#endif | ||||
| +#ifdef CONFIG_MTD_ROOTFS_SPLIT | ||||
| +			ret = split_rootfs_data(master, &slave->mtd, &parts[i], j); | ||||
| +			if (ret == 0) | ||||
| +				j++; | ||||
| +#endif | ||||
| +		} | ||||
|  		cur_offset = slave->offset + slave->mtd.size; | ||||
|  	} | ||||
|   | ||||
| @@ -517,6 +684,32 @@ int add_mtd_partitions(struct mtd_info * | ||||
|  } | ||||
|  EXPORT_SYMBOL(add_mtd_partitions); | ||||
|   | ||||
| +int refresh_mtd_partitions(struct mtd_info *mtd) | ||||
| +{ | ||||
| +	int ret = 0; | ||||
| + | ||||
| +	if (IS_PART(mtd)) { | ||||
| +		struct mtd_part *part; | ||||
| +		struct mtd_info *master; | ||||
| + | ||||
| +		part = PART(mtd); | ||||
| +		master = part->master; | ||||
| +		if (master->refresh_device) | ||||
| +			ret = master->refresh_device(master); | ||||
| +	} | ||||
| + | ||||
| +	if (!ret && mtd->refresh_device) | ||||
| +		ret = mtd->refresh_device(mtd); | ||||
| + | ||||
| +#ifdef CONFIG_MTD_ROOTFS_SPLIT | ||||
| +	if (!ret && IS_PART(mtd) && !strcmp(mtd->name, "rootfs")) | ||||
| +		refresh_rootfs_split(mtd); | ||||
| +#endif | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| +EXPORT_SYMBOL_GPL(refresh_mtd_partitions); | ||||
| + | ||||
|  static DEFINE_SPINLOCK(part_parser_lock); | ||||
|  static LIST_HEAD(part_parsers); | ||||
|   | ||||
| --- a/drivers/mtd/devices/block2mtd.c | ||||
| +++ b/drivers/mtd/devices/block2mtd.c | ||||
| @@ -29,6 +29,8 @@ struct block2mtd_dev { | ||||
|  	struct block_device *blkdev; | ||||
|  	struct mtd_info mtd; | ||||
|  	struct mutex write_mutex; | ||||
| +	rwlock_t bdev_mutex; | ||||
| +	char devname[0]; | ||||
|  }; | ||||
|   | ||||
|   | ||||
| @@ -81,6 +83,12 @@ static int block2mtd_erase(struct mtd_in | ||||
|  	size_t len = instr->len; | ||||
|  	int err; | ||||
|   | ||||
| +	read_lock(&dev->bdev_mutex); | ||||
| +	if (!dev->blkdev) { | ||||
| +		err = -EINVAL; | ||||
| +		goto done; | ||||
| +	} | ||||
| + | ||||
|  	instr->state = MTD_ERASING; | ||||
|  	mutex_lock(&dev->write_mutex); | ||||
|  	err = _block2mtd_erase(dev, from, len); | ||||
| @@ -93,6 +101,10 @@ static int block2mtd_erase(struct mtd_in | ||||
|   | ||||
|  	instr->state = MTD_ERASE_DONE; | ||||
|  	mtd_erase_callback(instr); | ||||
| + | ||||
| +done: | ||||
| +	read_unlock(&dev->bdev_mutex); | ||||
| + | ||||
|  	return err; | ||||
|  } | ||||
|   | ||||
| @@ -104,10 +116,14 @@ static int block2mtd_read(struct mtd_inf | ||||
|  	struct page *page; | ||||
|  	int index = from >> PAGE_SHIFT; | ||||
|  	int offset = from & (PAGE_SIZE-1); | ||||
| -	int cpylen; | ||||
| +	int cpylen, err = 0; | ||||
| + | ||||
| +	read_lock(&dev->bdev_mutex); | ||||
| +	if (!dev->blkdev || (from > mtd->size)) { | ||||
| +		err = -EINVAL; | ||||
| +		goto done; | ||||
| +	} | ||||
|   | ||||
| -	if (from > mtd->size) | ||||
| -		return -EINVAL; | ||||
|  	if (from + len > mtd->size) | ||||
|  		len = mtd->size - from; | ||||
|   | ||||
| @@ -122,10 +138,14 @@ static int block2mtd_read(struct mtd_inf | ||||
|  		len = len - cpylen; | ||||
|   | ||||
|  		page = page_read(dev->blkdev->bd_inode->i_mapping, index); | ||||
| -		if (!page) | ||||
| -			return -ENOMEM; | ||||
| -		if (IS_ERR(page)) | ||||
| -			return PTR_ERR(page); | ||||
| +		if (!page) { | ||||
| +			err = -ENOMEM; | ||||
| +			goto done; | ||||
| +		} | ||||
| +		if (IS_ERR(page)) { | ||||
| +			err = PTR_ERR(page); | ||||
| +			goto done; | ||||
| +		} | ||||
|   | ||||
|  		memcpy(buf, page_address(page) + offset, cpylen); | ||||
|  		page_cache_release(page); | ||||
| @@ -136,7 +156,10 @@ static int block2mtd_read(struct mtd_inf | ||||
|  		offset = 0; | ||||
|  		index++; | ||||
|  	} | ||||
| -	return 0; | ||||
| + | ||||
| +done: | ||||
| +	read_unlock(&dev->bdev_mutex); | ||||
| +	return err; | ||||
|  } | ||||
|   | ||||
|   | ||||
| @@ -188,12 +211,22 @@ static int block2mtd_write(struct mtd_in | ||||
|  		size_t *retlen, const u_char *buf) | ||||
|  { | ||||
|  	struct block2mtd_dev *dev = mtd->priv; | ||||
| -	int err; | ||||
| +	int err = 0; | ||||
| + | ||||
| +	read_lock(&dev->bdev_mutex); | ||||
| +	if (!dev->blkdev) { | ||||
| +		err = -EINVAL; | ||||
| +		goto done; | ||||
| +	} | ||||
|   | ||||
|  	if (!len) | ||||
| -		return 0; | ||||
| -	if (to >= mtd->size) | ||||
| -		return -ENOSPC; | ||||
| +		goto done; | ||||
| + | ||||
| +	if (to >= mtd->size) { | ||||
| +		err = -ENOSPC; | ||||
| +		goto done; | ||||
| +	} | ||||
| + | ||||
|  	if (to + len > mtd->size) | ||||
|  		len = mtd->size - to; | ||||
|   | ||||
| @@ -202,6 +235,9 @@ static int block2mtd_write(struct mtd_in | ||||
|  	mutex_unlock(&dev->write_mutex); | ||||
|  	if (err > 0) | ||||
|  		err = 0; | ||||
| + | ||||
| +done: | ||||
| +	read_unlock(&dev->bdev_mutex); | ||||
|  	return err; | ||||
|  } | ||||
|   | ||||
| @@ -210,52 +246,29 @@ static int block2mtd_write(struct mtd_in | ||||
|  static void block2mtd_sync(struct mtd_info *mtd) | ||||
|  { | ||||
|  	struct block2mtd_dev *dev = mtd->priv; | ||||
| -	sync_blockdev(dev->blkdev); | ||||
| -	return; | ||||
| -} | ||||
| - | ||||
| - | ||||
| -static void block2mtd_free_device(struct block2mtd_dev *dev) | ||||
| -{ | ||||
| -	if (!dev) | ||||
| -		return; | ||||
| - | ||||
| -	kfree(dev->mtd.name); | ||||
|   | ||||
| -	if (dev->blkdev) { | ||||
| -		invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping, | ||||
| -					0, -1); | ||||
| -		close_bdev_exclusive(dev->blkdev, FMODE_READ|FMODE_WRITE); | ||||
| -	} | ||||
| +	read_lock(&dev->bdev_mutex); | ||||
| +	if (dev->blkdev) | ||||
| +		sync_blockdev(dev->blkdev); | ||||
| +	read_unlock(&dev->bdev_mutex); | ||||
|   | ||||
| -	kfree(dev); | ||||
| +	return; | ||||
|  } | ||||
|   | ||||
|   | ||||
| -/* FIXME: ensure that mtd->size % erase_size == 0 */ | ||||
| -static struct block2mtd_dev *add_device(char *devname, int erase_size, const char *mtdname) | ||||
| +static int _open_bdev(struct block2mtd_dev *dev) | ||||
|  { | ||||
|  	struct block_device *bdev; | ||||
| -	struct block2mtd_dev *dev; | ||||
| -	struct mtd_partition *part; | ||||
| -	char *name; | ||||
| - | ||||
| -	if (!devname) | ||||
| -		return NULL; | ||||
| - | ||||
| -	dev = kzalloc(sizeof(struct block2mtd_dev), GFP_KERNEL); | ||||
| -	if (!dev) | ||||
| -		return NULL; | ||||
|   | ||||
|  	/* Get a handle on the device */ | ||||
| -	bdev = open_bdev_exclusive(devname, FMODE_READ|FMODE_WRITE, NULL); | ||||
| +	bdev = open_bdev_exclusive(dev->devname, FMODE_READ|FMODE_WRITE, NULL); | ||||
|  #ifndef MODULE | ||||
|  	if (IS_ERR(bdev)) { | ||||
|   | ||||
|  		/* We might not have rootfs mounted at this point. Try | ||||
|  		   to resolve the device name by other means. */ | ||||
|   | ||||
| -		dev_t devt = name_to_dev_t(devname); | ||||
| +		dev_t devt = name_to_dev_t(dev->devname); | ||||
|  		if (devt) { | ||||
|  			bdev = open_by_devnum(devt, FMODE_WRITE | FMODE_READ); | ||||
|  		} | ||||
| @@ -263,17 +276,97 @@ static struct block2mtd_dev *add_device( | ||||
|  #endif | ||||
|   | ||||
|  	if (IS_ERR(bdev)) { | ||||
| -		ERROR("error: cannot open device %s", devname); | ||||
| -		goto devinit_err; | ||||
| +		ERROR("error: cannot open device %s", dev->devname); | ||||
| +		return 1; | ||||
|  	} | ||||
|  	dev->blkdev = bdev; | ||||
|   | ||||
|  	if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) { | ||||
|  		ERROR("attempting to use an MTD device as a block device"); | ||||
| -		goto devinit_err; | ||||
| +		return 1; | ||||
|  	} | ||||
|   | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static void _close_bdev(struct block2mtd_dev *dev) | ||||
| +{ | ||||
| +	struct block_device *bdev; | ||||
| + | ||||
| +	if (!dev->blkdev) | ||||
| +		return; | ||||
| + | ||||
| +	bdev = dev->blkdev; | ||||
| +	invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping, 0, -1); | ||||
| +	close_bdev_exclusive(dev->blkdev, FMODE_READ|FMODE_WRITE); | ||||
| +	dev->blkdev = NULL; | ||||
| +} | ||||
| + | ||||
| +static void block2mtd_free_device(struct block2mtd_dev *dev) | ||||
| +{ | ||||
| +	if (!dev) | ||||
| +		return; | ||||
| + | ||||
| +	kfree(dev->mtd.name); | ||||
| +	_close_bdev(dev); | ||||
| +	kfree(dev); | ||||
| +} | ||||
| + | ||||
| + | ||||
| +static int block2mtd_refresh(struct mtd_info *mtd) | ||||
| +{ | ||||
| +	struct block2mtd_dev *dev = mtd->priv; | ||||
| +	struct block_device *bdev; | ||||
| +	dev_t devt; | ||||
| +	int err = 0; | ||||
| + | ||||
| +	/* no other mtd function can run at this point */ | ||||
| +	write_lock(&dev->bdev_mutex); | ||||
| + | ||||
| +	/* get the device number for the whole disk */ | ||||
| +	devt = MKDEV(MAJOR(dev->blkdev->bd_dev), 0); | ||||
| + | ||||
| +	/* close the old block device */ | ||||
| +	_close_bdev(dev); | ||||
| + | ||||
| +	/* open the whole disk, issue a partition rescan, then */ | ||||
| +	bdev = open_by_devnum(devt, FMODE_WRITE | FMODE_READ); | ||||
| +	if (!bdev || !bdev->bd_disk) | ||||
| +		err = -EINVAL; | ||||
| +	else { | ||||
| +		err = rescan_partitions(bdev->bd_disk, bdev); | ||||
| +	} | ||||
| +	if (bdev) | ||||
| +		close_bdev_exclusive(bdev, FMODE_READ|FMODE_WRITE); | ||||
| + | ||||
| +	/* try to open the partition block device again */ | ||||
| +	_open_bdev(dev); | ||||
| +	write_unlock(&dev->bdev_mutex); | ||||
| + | ||||
| +	return err; | ||||
| +} | ||||
| + | ||||
| +/* FIXME: ensure that mtd->size % erase_size == 0 */ | ||||
| +static struct block2mtd_dev *add_device(char *devname, int erase_size, char *mtdname) | ||||
| +{ | ||||
| +	struct block2mtd_dev *dev; | ||||
| +	struct mtd_partition *part; | ||||
| +	char *name; | ||||
| + | ||||
| +	if (!devname) | ||||
| +		return NULL; | ||||
| + | ||||
| +	dev = kzalloc(sizeof(struct block2mtd_dev) + strlen(devname) + 1, GFP_KERNEL); | ||||
| +	if (!dev) | ||||
| +		return NULL; | ||||
| + | ||||
| +	strcpy(dev->devname, devname); | ||||
| + | ||||
| +	if (_open_bdev(dev)) | ||||
| +		goto devinit_err; | ||||
| + | ||||
|  	mutex_init(&dev->write_mutex); | ||||
| +	rwlock_init(&dev->bdev_mutex); | ||||
|   | ||||
|  	if (!mtdname) | ||||
|  		mtdname = devname; | ||||
| @@ -297,6 +390,7 @@ static struct block2mtd_dev *add_device( | ||||
|  	dev->mtd.read = block2mtd_read; | ||||
|  	dev->mtd.priv = dev; | ||||
|  	dev->mtd.owner = THIS_MODULE; | ||||
| +	dev->mtd.refresh_device = block2mtd_refresh; | ||||
|   | ||||
|  	part = kzalloc(sizeof(struct mtd_partition), GFP_KERNEL); | ||||
|  	part->name = dev->mtd.name; | ||||
| --- a/drivers/mtd/mtdchar.c | ||||
| +++ b/drivers/mtd/mtdchar.c | ||||
| @@ -16,6 +16,7 @@ | ||||
|   | ||||
|  #include <linux/mtd/mtd.h> | ||||
|  #include <linux/mtd/compatmac.h> | ||||
| +#include <linux/mtd/partitions.h> | ||||
|   | ||||
|  #include <asm/uaccess.h> | ||||
|   | ||||
| @@ -773,6 +774,13 @@ static int mtd_ioctl(struct inode *inode | ||||
|  		file->f_pos = 0; | ||||
|  		break; | ||||
|  	} | ||||
| +#ifdef CONFIG_MTD_PARTITIONS | ||||
| +	case MTDREFRESH: | ||||
| +	{ | ||||
| +		ret = refresh_mtd_partitions(mtd); | ||||
| +		break; | ||||
| +	} | ||||
| +#endif | ||||
|   | ||||
|  	default: | ||||
|  		ret = -ENOTTY; | ||||
| --- a/include/linux/mtd/mtd.h | ||||
| +++ b/include/linux/mtd/mtd.h | ||||
| @@ -100,6 +100,7 @@ struct mtd_oob_ops { | ||||
|  	uint8_t		*oobbuf; | ||||
|  }; | ||||
|   | ||||
| +struct mtd_info; | ||||
|  struct mtd_info { | ||||
|  	u_char type; | ||||
|  	uint32_t flags; | ||||
| @@ -225,6 +226,9 @@ struct mtd_info { | ||||
|  	struct module *owner; | ||||
|  	int usecount; | ||||
|   | ||||
| +	int (*refresh_device)(struct mtd_info *mtd); | ||||
| +	struct mtd_info *split; | ||||
| + | ||||
|  	/* If the driver is something smart, like UBI, it may need to maintain | ||||
|  	 * its own reference counting. The below functions are only for driver. | ||||
|  	 * The driver may register its callbacks. These callbacks are not | ||||
| --- a/include/linux/mtd/partitions.h | ||||
| +++ b/include/linux/mtd/partitions.h | ||||
| @@ -34,6 +34,7 @@ | ||||
|   * erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK). | ||||
|   */ | ||||
|   | ||||
| +struct mtd_partition; | ||||
|  struct mtd_partition { | ||||
|  	char *name;			/* identifier string */ | ||||
|  	uint64_t size;			/* partition size */ | ||||
| @@ -41,6 +42,7 @@ struct mtd_partition { | ||||
|  	uint32_t mask_flags;		/* master MTD flags to mask out for this partition */ | ||||
|  	struct nand_ecclayout *ecclayout;	/* out of band layout for this partition (NAND only)*/ | ||||
|  	struct mtd_info **mtdp;		/* pointer to store the MTD object */ | ||||
| +	int (*refresh_partition)(struct mtd_info *); | ||||
|  }; | ||||
|   | ||||
|  #define MTDPART_OFS_NXTBLK	(-2) | ||||
| @@ -50,6 +52,7 @@ struct mtd_partition { | ||||
|   | ||||
|  int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int); | ||||
|  int del_mtd_partitions(struct mtd_info *); | ||||
| +int refresh_mtd_partitions(struct mtd_info *); | ||||
|   | ||||
|  /* | ||||
|   * Functions dealing with the various ways of partitioning the space | ||||
| --- a/include/mtd/mtd-abi.h | ||||
| +++ b/include/mtd/mtd-abi.h | ||||
| @@ -93,6 +93,7 @@ struct otp_info { | ||||
|  #define ECCGETLAYOUT		_IOR('M', 17, struct nand_ecclayout) | ||||
|  #define ECCGETSTATS		_IOR('M', 18, struct mtd_ecc_stats) | ||||
|  #define MTDFILEMODE		_IO('M', 19) | ||||
| +#define MTDREFRESH		_IO('M', 23) | ||||
|   | ||||
|  /* | ||||
|   * Obsolete legacy interface. Keep it in order not to break userspace | ||||
| @@ -1,27 +0,0 @@ | ||||
| --- a/drivers/mtd/mtdpart.c | ||||
| +++ b/drivers/mtd/mtdpart.c | ||||
| @@ -515,21 +515,21 @@ static int split_squashfs(struct mtd_inf | ||||
|  		return -EINVAL; | ||||
|  	} | ||||
|   | ||||
| -	if (*((u32 *) buf) != SQUASHFS_MAGIC) { | ||||
| +	if (SQUASHFS_MAGIC != le32_to_cpu(sb->s_magic) ) { | ||||
|  		printk(KERN_ALERT "split_squashfs: no squashfs found in \"%s\"\n", | ||||
|  			master->name); | ||||
|  		*split_offset = 0; | ||||
|  		return 0; | ||||
|  	} | ||||
|   | ||||
| -	if (sb->bytes_used <= 0) { | ||||
| +	if (le64_to_cpu((sb->bytes_used)) <= 0) { | ||||
|  		printk(KERN_ALERT "split_squashfs: squashfs is empty in \"%s\"\n", | ||||
|  			master->name); | ||||
|  		*split_offset = 0; | ||||
|  		return 0; | ||||
|  	} | ||||
|   | ||||
| -	len = (u32) sb->bytes_used; | ||||
| +	len = (u32) le64_to_cpu(sb->bytes_used); | ||||
|  	len += (offset & 0x000fffff); | ||||
|  	len +=  (master->erasesize - 1); | ||||
|  	len &= ~(master->erasesize - 1); | ||||
| @@ -1,30 +0,0 @@ | ||||
| --- a/drivers/mtd/redboot.c | ||||
| +++ b/drivers/mtd/redboot.c | ||||
| @@ -249,14 +249,21 @@ static int parse_redboot_partitions(stru | ||||
|  #endif | ||||
|  		names += strlen(names)+1; | ||||
|   | ||||
| -#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED | ||||
|  		if(fl->next && fl->img->flash_base + fl->img->size + master->erasesize <= fl->next->img->flash_base) { | ||||
| -			i++; | ||||
| -			parts[i].offset = parts[i-1].size + parts[i-1].offset; | ||||
| -			parts[i].size = fl->next->img->flash_base - parts[i].offset; | ||||
| -			parts[i].name = nullname; | ||||
| -		} | ||||
| +			if (!strcmp(parts[i].name, "rootfs")) { | ||||
| +				parts[i].size = fl->next->img->flash_base; | ||||
| +				parts[i].size &= ~(master->erasesize - 1); | ||||
| +				parts[i].size -= parts[i].offset; | ||||
| +#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED | ||||
| +				nrparts--; | ||||
| +			} else { | ||||
| +				i++; | ||||
| +				parts[i].offset = parts[i-1].size + parts[i-1].offset; | ||||
| +				parts[i].size = fl->next->img->flash_base - parts[i].offset; | ||||
| +				parts[i].name = nullname; | ||||
|  #endif | ||||
| +			} | ||||
| +		} | ||||
|  		tmp_fl = fl; | ||||
|  		fl = fl->next; | ||||
|  		kfree(tmp_fl); | ||||
| @@ -1,60 +0,0 @@ | ||||
| --- a/drivers/mtd/redboot.c | ||||
| +++ b/drivers/mtd/redboot.c | ||||
| @@ -11,6 +11,8 @@ | ||||
|  #include <linux/mtd/mtd.h> | ||||
|  #include <linux/mtd/partitions.h> | ||||
|   | ||||
| +#define BOARD_CONFIG_PART		"boardconfig" | ||||
| + | ||||
|  struct fis_image_desc { | ||||
|      unsigned char name[16];      // Null terminated name | ||||
|      uint32_t	  flash_base;    // Address within FLASH of image | ||||
| @@ -41,6 +43,7 @@ static int parse_redboot_partitions(stru | ||||
|                               struct mtd_partition **pparts, | ||||
|                               unsigned long fis_origin) | ||||
|  { | ||||
| +	unsigned long max_offset = 0; | ||||
|  	int nrparts = 0; | ||||
|  	struct fis_image_desc *buf; | ||||
|  	struct mtd_partition *parts; | ||||
| @@ -209,14 +212,14 @@ static int parse_redboot_partitions(stru | ||||
|  		} | ||||
|  	} | ||||
|  #endif | ||||
| -	parts = kzalloc(sizeof(*parts)*nrparts + nulllen + namelen, GFP_KERNEL); | ||||
| +	parts = kzalloc(sizeof(*parts) * (nrparts + 1) + nulllen + namelen + sizeof(BOARD_CONFIG_PART), GFP_KERNEL); | ||||
|   | ||||
|  	if (!parts) { | ||||
|  		ret = -ENOMEM; | ||||
|  		goto out; | ||||
|  	} | ||||
|   | ||||
| -	nullname = (char *)&parts[nrparts]; | ||||
| +	nullname = (char *)&parts[nrparts + 1]; | ||||
|  #ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED | ||||
|  	if (nulllen > 0) { | ||||
|  		strcpy(nullname, nullstring); | ||||
| @@ -235,6 +238,8 @@ static int parse_redboot_partitions(stru | ||||
|  	} | ||||
|  #endif | ||||
|  	for ( ; i<nrparts; i++) { | ||||
| +		if(max_offset < buf[i].flash_base + buf[i].size) | ||||
| +			max_offset = buf[i].flash_base + buf[i].size; | ||||
|  		parts[i].size = fl->img->size; | ||||
|  		parts[i].offset = fl->img->flash_base; | ||||
|  		parts[i].name = names; | ||||
| @@ -268,6 +273,14 @@ static int parse_redboot_partitions(stru | ||||
|  		fl = fl->next; | ||||
|  		kfree(tmp_fl); | ||||
|  	} | ||||
| +	if(master->size - max_offset >= master->erasesize) | ||||
| +	{ | ||||
| +		parts[nrparts].size = master->size - max_offset; | ||||
| +		parts[nrparts].offset = max_offset; | ||||
| +		parts[nrparts].name = names; | ||||
| +		strcpy(names, BOARD_CONFIG_PART); | ||||
| +		nrparts++; | ||||
| +	} | ||||
|  	ret = nrparts; | ||||
|  	*pparts = parts; | ||||
|   out: | ||||
| @@ -1,32 +0,0 @@ | ||||
| --- a/include/linux/mtd/nand.h | ||||
| +++ b/include/linux/mtd/nand.h | ||||
| @@ -574,6 +574,7 @@ struct platform_nand_chip { | ||||
|  	int			chip_delay; | ||||
|  	unsigned int		options; | ||||
|  	const char		**part_probe_types; | ||||
| +	int			(*chip_fixup)(struct mtd_info *mtd); | ||||
|  	void			*priv; | ||||
|  }; | ||||
|   | ||||
| --- a/drivers/mtd/nand/plat_nand.c | ||||
| +++ b/drivers/mtd/nand/plat_nand.c | ||||
| @@ -71,7 +71,18 @@ static int __init plat_nand_probe(struct | ||||
|  	platform_set_drvdata(pdev, data); | ||||
|   | ||||
|  	/* Scan to find existance of the device */ | ||||
| -	if (nand_scan(&data->mtd, 1)) { | ||||
| +	if (nand_scan_ident(&data->mtd, 1)) { | ||||
| +		res = -ENXIO; | ||||
| +		goto out; | ||||
| +	} | ||||
| + | ||||
| +	if (pdata->chip.chip_fixup) { | ||||
| +		res = pdata->chip.chip_fixup(&data->mtd); | ||||
| +		if (res) | ||||
| +			goto out; | ||||
| +	} | ||||
| + | ||||
| +	if (nand_scan_tail(&data->mtd)) { | ||||
|  		res = -ENXIO; | ||||
|  		goto out; | ||||
|  	} | ||||
| @@ -1,35 +0,0 @@ | ||||
| --- a/drivers/mtd/Kconfig | ||||
| +++ b/drivers/mtd/Kconfig | ||||
| @@ -180,6 +180,22 @@ config MTD_AR7_PARTS | ||||
|  	---help--- | ||||
|  	  TI AR7 partitioning support | ||||
|   | ||||
| +config MTD_MYLOADER_PARTS | ||||
| +	tristate "MyLoader partition parsing" | ||||
| +	depends on MTD_PARTITIONS && (ADM5120 || ATHEROS || ATHEROS_AR71XX) | ||||
| +	---help--- | ||||
| +	  MyLoader is a bootloader which allows the user to define partitions | ||||
| +	  in flash devices, by putting a table in the second erase block | ||||
| +	  on the device, similar to a partition table. This table gives the  | ||||
| +	  offsets and lengths of the user defined partitions. | ||||
| + | ||||
| +	  If you need code which can detect and parse these tables, and | ||||
| +	  register MTD 'partitions' corresponding to each image detected, | ||||
| +	  enable this option. | ||||
| + | ||||
| +	  You will still need the parsing functions to be called by the driver | ||||
| +	  for your particular device. It won't happen automatically. | ||||
| + | ||||
|  comment "User Modules And Translation Layers" | ||||
|   | ||||
|  config MTD_CHAR | ||||
| --- a/drivers/mtd/Makefile | ||||
| +++ b/drivers/mtd/Makefile | ||||
| @@ -13,6 +13,7 @@ obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdli | ||||
|  obj-$(CONFIG_MTD_AFS_PARTS)	+= afs.o | ||||
|  obj-$(CONFIG_MTD_AR7_PARTS)	+= ar7part.o | ||||
|  obj-$(CONFIG_MTD_OF_PARTS)      += ofpart.o | ||||
| +obj-$(CONFIG_MTD_MYLOADER_PARTS) += myloader.o | ||||
|   | ||||
|  # 'Users' - code which presents functionality to userspace. | ||||
|  obj-$(CONFIG_MTD_CHAR)		+= mtdchar.o | ||||
| @@ -1,11 +0,0 @@ | ||||
| --- a/drivers/mtd/myloader.c | ||||
| +++ b/drivers/mtd/myloader.c | ||||
| @@ -19,7 +19,7 @@ | ||||
|  #include <linux/vmalloc.h> | ||||
|  #include <linux/mtd/mtd.h> | ||||
|  #include <linux/mtd/partitions.h> | ||||
| -#include <linux/byteorder/generic.h> | ||||
| +#include <linux/byteorder.h> | ||||
|  #include <linux/myloader.h> | ||||
|   | ||||
|  #define BLOCK_LEN_MIN		0x10000 | ||||
| @@ -1,12 +0,0 @@ | ||||
| --- a/drivers/mtd/nand/nand_ecc.c | ||||
| +++ b/drivers/mtd/nand/nand_ecc.c | ||||
| @@ -492,8 +492,7 @@ int nand_correct_data(struct mtd_info *m | ||||
|  	if ((bitsperbyte[b0] + bitsperbyte[b1] + bitsperbyte[b2]) == 1) | ||||
|  		return 1;	/* error in ecc data; no action needed */ | ||||
|   | ||||
| -	printk(KERN_ERR "uncorrectable error : "); | ||||
| -	return -1; | ||||
| +	return -EBADMSG; | ||||
|  } | ||||
|  EXPORT_SYMBOL(nand_correct_data); | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,108 +0,0 @@ | ||||
| --- a/include/linux/netfilter/xt_layer7.h | ||||
| +++ b/include/linux/netfilter/xt_layer7.h | ||||
| @@ -8,6 +8,7 @@ struct xt_layer7_info { | ||||
|      char protocol[MAX_PROTOCOL_LEN]; | ||||
|      char pattern[MAX_PATTERN_LEN]; | ||||
|      u_int8_t invert; | ||||
| +    u_int8_t pkt; | ||||
|  }; | ||||
|   | ||||
|  #endif /* _XT_LAYER7_H */ | ||||
| --- a/net/netfilter/xt_layer7.c | ||||
| +++ b/net/netfilter/xt_layer7.c | ||||
| @@ -314,33 +314,35 @@ static int match_no_append(struct nf_con | ||||
|  } | ||||
|   | ||||
|  /* add the new app data to the conntrack.  Return number of bytes added. */ | ||||
| -static int add_data(struct nf_conn * master_conntrack, | ||||
| -                    char * app_data, int appdatalen) | ||||
| +static int add_datastr(char *target, int offset, char *app_data, int len) | ||||
|  { | ||||
|  	int length = 0, i; | ||||
| -	int oldlength = master_conntrack->layer7.app_data_len; | ||||
| - | ||||
| -	/* This is a fix for a race condition by Deti Fliegl. However, I'm not  | ||||
| -	   clear on whether the race condition exists or whether this really  | ||||
| -	   fixes it.  I might just be being dense... Anyway, if it's not really  | ||||
| -	   a fix, all it does is waste a very small amount of time. */ | ||||
| -	if(!master_conntrack->layer7.app_data) return 0; | ||||
| +	if (!target) return 0; | ||||
|   | ||||
|  	/* Strip nulls. Make everything lower case (our regex lib doesn't | ||||
|  	do case insensitivity).  Add it to the end of the current data. */ | ||||
| -	for(i = 0; i < maxdatalen-oldlength-1 && | ||||
| -		   i < appdatalen; i++) { | ||||
| + 	for(i = 0; i < maxdatalen-offset-1 && i < len; i++) { | ||||
|  		if(app_data[i] != '\0') { | ||||
|  			/* the kernel version of tolower mungs 'upper ascii' */ | ||||
| -			master_conntrack->layer7.app_data[length+oldlength] = | ||||
| +			target[length+offset] = | ||||
|  				isascii(app_data[i])?  | ||||
|  					tolower(app_data[i]) : app_data[i]; | ||||
|  			length++; | ||||
|  		} | ||||
|  	} | ||||
| +	target[length+offset] = '\0'; | ||||
| + | ||||
| +	return length; | ||||
| +} | ||||
| + | ||||
| +/* add the new app data to the conntrack.  Return number of bytes added. */ | ||||
| +static int add_data(struct nf_conn * master_conntrack, | ||||
| +                    char * app_data, int appdatalen) | ||||
| +{ | ||||
| +	int length; | ||||
|   | ||||
| -	master_conntrack->layer7.app_data[length+oldlength] = '\0'; | ||||
| -	master_conntrack->layer7.app_data_len = length + oldlength; | ||||
| +	length = add_datastr(master_conntrack->layer7.app_data, master_conntrack->layer7.app_data_len, app_data, appdatalen); | ||||
| +	master_conntrack->layer7.app_data_len += length; | ||||
|   | ||||
|  	return length; | ||||
|  } | ||||
| @@ -438,7 +440,7 @@ match(const struct sk_buff *skbin, | ||||
|   | ||||
|  	enum ip_conntrack_info master_ctinfo, ctinfo; | ||||
|  	struct nf_conn *master_conntrack, *conntrack; | ||||
| -	unsigned char * app_data; | ||||
| +	unsigned char *app_data, *tmp_data; | ||||
|  	unsigned int pattern_result, appdatalen; | ||||
|  	regexp * comppattern; | ||||
|   | ||||
| @@ -466,8 +468,8 @@ match(const struct sk_buff *skbin, | ||||
|  		master_conntrack = master_ct(master_conntrack); | ||||
|   | ||||
|  	/* if we've classified it or seen too many packets */ | ||||
| -	if(total_acct_packets(master_conntrack) > num_packets || | ||||
| -	   master_conntrack->layer7.app_proto) { | ||||
| +	if(!info->pkt && (total_acct_packets(master_conntrack) > num_packets || | ||||
| +	   master_conntrack->layer7.app_proto)) { | ||||
|   | ||||
|  		pattern_result = match_no_append(conntrack, master_conntrack,  | ||||
|  						 ctinfo, master_ctinfo, info); | ||||
| @@ -500,6 +502,25 @@ match(const struct sk_buff *skbin, | ||||
|  	/* the return value gets checked later, when we're ready to use it */ | ||||
|  	comppattern = compile_and_cache(info->pattern, info->protocol); | ||||
|   | ||||
| +	if (info->pkt) { | ||||
| +		tmp_data = kmalloc(maxdatalen, GFP_ATOMIC); | ||||
| +		if(!tmp_data){ | ||||
| +			if (net_ratelimit()) | ||||
| +				printk(KERN_ERR "layer7: out of memory in match, bailing.\n"); | ||||
| +			return info->invert; | ||||
| +		} | ||||
| + | ||||
| +		tmp_data[0] = '\0'; | ||||
| +		add_datastr(tmp_data, 0, app_data, appdatalen); | ||||
| +		pattern_result = ((comppattern && regexec(comppattern, tmp_data)) ? 1 : 0); | ||||
| + | ||||
| +		kfree(tmp_data); | ||||
| +		tmp_data = NULL; | ||||
| +		spin_unlock_bh(&l7_lock); | ||||
| + | ||||
| +		return (pattern_result ^ info->invert); | ||||
| +	} | ||||
| + | ||||
|  	/* On the first packet of a connection, allocate space for app data */ | ||||
|  	if(total_acct_packets(master_conntrack) == 1 && !skb->cb[0] &&  | ||||
|  	   !master_conntrack->layer7.app_data){ | ||||
| @@ -1,119 +0,0 @@ | ||||
| --- a/include/linux/netfilter_ipv4/ip_tables.h | ||||
| +++ b/include/linux/netfilter_ipv4/ip_tables.h | ||||
| @@ -62,6 +62,7 @@ struct ipt_ip { | ||||
|  #define IPT_F_FRAG		0x01	/* Set if rule is a fragment rule */ | ||||
|  #define IPT_F_GOTO		0x02	/* Set if jump is a goto */ | ||||
|  #define IPT_F_MASK		0x03	/* All possible flag bits mask. */ | ||||
| +#define IPT_F_NO_DEF_MATCH	0x80	/* Internal: no default match rules present */ | ||||
|   | ||||
|  /* Values for "inv" field in struct ipt_ip. */ | ||||
|  #define IPT_INV_VIA_IN		0x01	/* Invert the sense of IN IFACE. */ | ||||
| --- a/net/ipv4/netfilter/ip_tables.c | ||||
| +++ b/net/ipv4/netfilter/ip_tables.c | ||||
| @@ -88,6 +88,9 @@ ip_packet_match(const struct iphdr *ip, | ||||
|   | ||||
|  #define FWINV(bool, invflg) ((bool) ^ !!(ipinfo->invflags & (invflg))) | ||||
|   | ||||
| +	if (ipinfo->flags & IPT_F_NO_DEF_MATCH) | ||||
| +		return true; | ||||
| + | ||||
|  	if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr, | ||||
|  		  IPT_INV_SRCIP) | ||||
|  	    || FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr, | ||||
| @@ -147,13 +150,35 @@ ip_packet_match(const struct iphdr *ip, | ||||
|  		return false; | ||||
|  	} | ||||
|   | ||||
| +#undef FWINV | ||||
|  	return true; | ||||
|  } | ||||
|   | ||||
|  static bool | ||||
| -ip_checkentry(const struct ipt_ip *ip) | ||||
| +ip_checkentry(struct ipt_ip *ip) | ||||
|  { | ||||
| -	if (ip->flags & ~IPT_F_MASK) { | ||||
| +#define FWINV(bool, invflg) ((bool) || (ip->invflags & (invflg))) | ||||
| + | ||||
| +	if (FWINV(ip->smsk.s_addr, IPT_INV_SRCIP) || | ||||
| +		FWINV(ip->dmsk.s_addr, IPT_INV_DSTIP)) | ||||
| +		goto has_match_rules; | ||||
| + | ||||
| +	if (FWINV(!!((const unsigned long *)ip->iniface_mask)[0], | ||||
| +		IPT_INV_VIA_IN) || | ||||
| +	    FWINV(!!((const unsigned long *)ip->outiface_mask)[0], | ||||
| +		IPT_INV_VIA_OUT)) | ||||
| +		goto has_match_rules; | ||||
| + | ||||
| +	if (FWINV(ip->proto, IPT_INV_PROTO)) | ||||
| +		goto has_match_rules; | ||||
| + | ||||
| +	if (FWINV(ip->flags&IPT_F_FRAG, IPT_INV_FRAG)) | ||||
| +		goto has_match_rules; | ||||
| + | ||||
| +	ip->flags |= IPT_F_NO_DEF_MATCH; | ||||
| + | ||||
| +has_match_rules: | ||||
| +	if (ip->flags & ~(IPT_F_MASK|IPT_F_NO_DEF_MATCH)) { | ||||
|  		duprintf("Unknown flag bits set: %08X\n", | ||||
|  			 ip->flags & ~IPT_F_MASK); | ||||
|  		return false; | ||||
| @@ -163,6 +188,8 @@ ip_checkentry(const struct ipt_ip *ip) | ||||
|  			 ip->invflags & ~IPT_INV_MASK); | ||||
|  		return false; | ||||
|  	} | ||||
| + | ||||
| +#undef FWINV | ||||
|  	return true; | ||||
|  } | ||||
|   | ||||
| @@ -210,7 +237,6 @@ unconditional(const struct ipt_ip *ip) | ||||
|  			return 0; | ||||
|   | ||||
|  	return 1; | ||||
| -#undef FWINV | ||||
|  } | ||||
|   | ||||
|  #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | ||||
| @@ -328,8 +354,27 @@ ipt_do_table(struct sk_buff *skb, | ||||
|  	struct xt_match_param mtpar; | ||||
|  	struct xt_target_param tgpar; | ||||
|   | ||||
| -	/* Initialization */ | ||||
|  	ip = ip_hdr(skb); | ||||
| + | ||||
| +	read_lock_bh(&table->lock); | ||||
| +	IP_NF_ASSERT(table->valid_hooks & (1 << hook)); | ||||
| +	private = table->private; | ||||
| +	table_base = (void *)private->entries[smp_processor_id()]; | ||||
| +	e = get_entry(table_base, private->hook_entry[hook]); | ||||
| +	if (e->target_offset <= sizeof(struct ipt_entry) && | ||||
| +		(e->ip.flags & IPT_F_NO_DEF_MATCH)) { | ||||
| +			struct ipt_entry_target *t = ipt_get_target(e); | ||||
| +			if (!t->u.kernel.target->target) { | ||||
| +				int v = ((struct ipt_standard_target *)t)->verdict; | ||||
| +				if ((v < 0) && (v != IPT_RETURN)) { | ||||
| +					ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1); | ||||
| +					read_unlock_bh(&table->lock); | ||||
| +					return (unsigned)(-v) - 1; | ||||
| +				} | ||||
| +			} | ||||
| +	} | ||||
| + | ||||
| +	/* Initialization */ | ||||
|  	datalen = skb->len - ip->ihl * 4; | ||||
|  	indev = in ? in->name : nulldevname; | ||||
|  	outdev = out ? out->name : nulldevname; | ||||
| @@ -347,12 +392,6 @@ ipt_do_table(struct sk_buff *skb, | ||||
|  	mtpar.family  = tgpar.family = NFPROTO_IPV4; | ||||
|  	tgpar.hooknum = hook; | ||||
|   | ||||
| -	read_lock_bh(&table->lock); | ||||
| -	IP_NF_ASSERT(table->valid_hooks & (1 << hook)); | ||||
| -	private = table->private; | ||||
| -	table_base = (void *)private->entries[smp_processor_id()]; | ||||
| -	e = get_entry(table_base, private->hook_entry[hook]); | ||||
| - | ||||
|  	/* For return from builtin chain */ | ||||
|  	back = get_entry(table_base, private->underflow[hook]); | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,18 +0,0 @@ | ||||
| --- a/net/netfilter/Kconfig | ||||
| +++ b/net/netfilter/Kconfig | ||||
| @@ -160,7 +160,6 @@ config NF_CONNTRACK_FTP | ||||
|   | ||||
|  config NF_CONNTRACK_H323 | ||||
|  	tristate "H.323 protocol support" | ||||
| -	depends on (IPV6 || IPV6=n) | ||||
|  	depends on NETFILTER_ADVANCED | ||||
|  	help | ||||
|  	  H.323 is a VoIP signalling protocol from ITU-T. As one of the most | ||||
| @@ -466,7 +465,6 @@ config NETFILTER_XT_TARGET_SECMARK | ||||
|   | ||||
|  config NETFILTER_XT_TARGET_TCPMSS | ||||
|  	tristate '"TCPMSS" target support' | ||||
| -	depends on (IPV6 || IPV6=n) | ||||
|  	default m if NETFILTER_ADVANCED=n | ||||
|  	---help--- | ||||
|  	  This option adds a `TCPMSS' target, which allows you to alter the | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,793 +0,0 @@ | ||||
| --- a/include/linux/pkt_sched.h | ||||
| +++ b/include/linux/pkt_sched.h | ||||
| @@ -182,8 +182,37 @@ struct tc_sfq_xstats | ||||
|   * | ||||
|   *	The only reason for this is efficiency, it is possible | ||||
|   *	to change these parameters in compile time. | ||||
| + * | ||||
| + *	If you need to play with these values, use esfq instead. | ||||
|   */ | ||||
|   | ||||
| +/* ESFQ section */ | ||||
| + | ||||
| +enum | ||||
| +{ | ||||
| +        /* traditional */ | ||||
| +	TCA_SFQ_HASH_CLASSIC, | ||||
| +	TCA_SFQ_HASH_DST, | ||||
| +	TCA_SFQ_HASH_SRC, | ||||
| +	TCA_SFQ_HASH_FWMARK, | ||||
| +	/* conntrack */ | ||||
| +	TCA_SFQ_HASH_CTORIGDST, | ||||
| +	TCA_SFQ_HASH_CTORIGSRC, | ||||
| +	TCA_SFQ_HASH_CTREPLDST, | ||||
| +	TCA_SFQ_HASH_CTREPLSRC, | ||||
| +	TCA_SFQ_HASH_CTNATCHG, | ||||
| +}; | ||||
| + | ||||
| +struct tc_esfq_qopt | ||||
| +{ | ||||
| +	unsigned	quantum;	/* Bytes per round allocated to flow */ | ||||
| +	int		perturb_period;	/* Period of hash perturbation */ | ||||
| +	__u32		limit;		/* Maximal packets in queue */ | ||||
| +	unsigned	divisor;	/* Hash divisor  */ | ||||
| +	unsigned	flows;		/* Maximal number of flows  */ | ||||
| +	unsigned	hash_kind;	/* Hash function to use for flow identification */ | ||||
| +}; | ||||
| + | ||||
|  /* RED section */ | ||||
|   | ||||
|  enum | ||||
| --- a/net/sched/Kconfig | ||||
| +++ b/net/sched/Kconfig | ||||
| @@ -137,6 +137,37 @@ config NET_SCH_SFQ | ||||
|  	  To compile this code as a module, choose M here: the | ||||
|  	  module will be called sch_sfq. | ||||
|   | ||||
| +config NET_SCH_ESFQ | ||||
| +	tristate "Enhanced Stochastic Fairness Queueing (ESFQ)" | ||||
| +	---help--- | ||||
| +	  Say Y here if you want to use the Enhanced Stochastic Fairness | ||||
| +	  Queueing (ESFQ) packet scheduling algorithm for some of your network | ||||
| +	  devices or as a leaf discipline for a classful qdisc such as HTB or | ||||
| +	  CBQ (see the top of <file:net/sched/sch_esfq.c> for details and | ||||
| +	  references to the SFQ algorithm). | ||||
| + | ||||
| +	  This is an enchanced SFQ version which allows you to control some | ||||
| +	  hardcoded values in the SFQ scheduler. | ||||
| + | ||||
| +	  ESFQ also adds control of the hash function used to identify packet | ||||
| +	  flows. The original SFQ discipline hashes by connection; ESFQ add | ||||
| +	  several other hashing methods, such as by src IP or by dst IP, which | ||||
| +	  can be more fair to users in some networking situations. | ||||
| + | ||||
| +	  To compile this code as a module, choose M here: the | ||||
| +	  module will be called sch_esfq. | ||||
| + | ||||
| +config NET_SCH_ESFQ_NFCT | ||||
| +	bool "Connection Tracking Hash Types" | ||||
| +	depends on NET_SCH_ESFQ && NF_CONNTRACK | ||||
| +	---help--- | ||||
| +	  Say Y here to enable support for hashing based on netfilter connection | ||||
| +	  tracking information. This is useful for a router that is also using | ||||
| +	  NAT to connect privately-addressed hosts to the Internet. If you want | ||||
| +	  to provide fair distribution of upstream bandwidth, ESFQ must use | ||||
| +	  connection tracking information, since all outgoing packets will share | ||||
| +	  the same source address. | ||||
| + | ||||
|  config NET_SCH_TEQL | ||||
|  	tristate "True Link Equalizer (TEQL)" | ||||
|  	---help--- | ||||
| --- a/net/sched/Makefile | ||||
| +++ b/net/sched/Makefile | ||||
| @@ -24,6 +24,7 @@ obj-$(CONFIG_NET_SCH_GRED)	+= sch_gred.o | ||||
|  obj-$(CONFIG_NET_SCH_INGRESS)	+= sch_ingress.o  | ||||
|  obj-$(CONFIG_NET_SCH_DSMARK)	+= sch_dsmark.o | ||||
|  obj-$(CONFIG_NET_SCH_SFQ)	+= sch_sfq.o | ||||
| +obj-$(CONFIG_NET_SCH_ESFQ)	+= sch_esfq.o | ||||
|  obj-$(CONFIG_NET_SCH_TBF)	+= sch_tbf.o | ||||
|  obj-$(CONFIG_NET_SCH_TEQL)	+= sch_teql.o | ||||
|  obj-$(CONFIG_NET_SCH_PRIO)	+= sch_prio.o | ||||
| --- /dev/null | ||||
| +++ b/net/sched/sch_esfq.c | ||||
| @@ -0,0 +1,700 @@ | ||||
| +/* | ||||
| + * net/sched/sch_esfq.c	Extended Stochastic Fairness Queueing discipline. | ||||
| + * | ||||
| + *		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:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> | ||||
| + * | ||||
| + * Changes:	Alexander Atanasov, <alex@ssi.bg> | ||||
| + *		Added dynamic depth,limit,divisor,hash_kind options. | ||||
| + *		Added dst and src hashes. | ||||
| + * | ||||
| + * 		Alexander Clouter, <alex@digriz.org.uk> | ||||
| + *		Ported ESFQ to Linux 2.6. | ||||
| + * | ||||
| + * 		Corey Hickey, <bugfood-c@fatooh.org> | ||||
| + *		Maintenance of the Linux 2.6 port. | ||||
| + *		Added fwmark hash (thanks to Robert Kurjata). | ||||
| + *		Added usage of jhash. | ||||
| + *		Added conntrack support. | ||||
| + *		Added ctnatchg hash (thanks to Ben Pfountz). | ||||
| + */ | ||||
| + | ||||
| +#include <linux/module.h> | ||||
| +#include <asm/uaccess.h> | ||||
| +#include <asm/system.h> | ||||
| +#include <linux/bitops.h> | ||||
| +#include <linux/types.h> | ||||
| +#include <linux/kernel.h> | ||||
| +#include <linux/jiffies.h> | ||||
| +#include <linux/string.h> | ||||
| +#include <linux/mm.h> | ||||
| +#include <linux/socket.h> | ||||
| +#include <linux/sockios.h> | ||||
| +#include <linux/in.h> | ||||
| +#include <linux/errno.h> | ||||
| +#include <linux/interrupt.h> | ||||
| +#include <linux/if_ether.h> | ||||
| +#include <linux/inet.h> | ||||
| +#include <linux/netdevice.h> | ||||
| +#include <linux/etherdevice.h> | ||||
| +#include <linux/notifier.h> | ||||
| +#include <linux/init.h> | ||||
| +#include <net/ip.h> | ||||
| +#include <net/netlink.h> | ||||
| +#include <linux/ipv6.h> | ||||
| +#include <net/route.h> | ||||
| +#include <linux/skbuff.h> | ||||
| +#include <net/sock.h> | ||||
| +#include <net/pkt_sched.h> | ||||
| +#include <linux/jhash.h> | ||||
| +#include <net/netfilter/nf_conntrack.h> | ||||
| + | ||||
| +/*	Stochastic Fairness Queuing algorithm. | ||||
| +	For more comments look at sch_sfq.c. | ||||
| +	The difference is that you can change limit, depth, | ||||
| +	hash table size and choose alternate hash types. | ||||
| + | ||||
| +	classic:	same as in sch_sfq.c | ||||
| +	dst:		destination IP address | ||||
| +	src:		source IP address | ||||
| +	fwmark:		netfilter mark value | ||||
| +	ctorigdst:	original destination IP address | ||||
| +	ctorigsrc:	original source IP address | ||||
| +	ctrepldst:	reply destination IP address | ||||
| +	ctreplsrc:	reply source IP | ||||
| + | ||||
| +*/ | ||||
| + | ||||
| +#define ESFQ_HEAD 0 | ||||
| +#define ESFQ_TAIL 1 | ||||
| + | ||||
| +/* This type should contain at least SFQ_DEPTH*2 values */ | ||||
| +typedef unsigned int esfq_index; | ||||
| + | ||||
| +struct esfq_head | ||||
| +{ | ||||
| +	esfq_index	next; | ||||
| +	esfq_index	prev; | ||||
| +}; | ||||
| + | ||||
| +struct esfq_sched_data | ||||
| +{ | ||||
| +/* Parameters */ | ||||
| +	int		perturb_period; | ||||
| +	unsigned	quantum;	/* Allotment per round: MUST BE >= MTU */ | ||||
| +	int		limit; | ||||
| +	unsigned	depth; | ||||
| +	unsigned	hash_divisor; | ||||
| +	unsigned	hash_kind; | ||||
| +/* Variables */ | ||||
| +	struct timer_list perturb_timer; | ||||
| +	int		perturbation; | ||||
| +	esfq_index	tail;		/* Index of current slot in round */ | ||||
| +	esfq_index	max_depth;	/* Maximal depth */ | ||||
| + | ||||
| +	esfq_index	*ht;			/* Hash table */ | ||||
| +	esfq_index	*next;			/* Active slots link */ | ||||
| +	short		*allot;			/* Current allotment per slot */ | ||||
| +	unsigned short	*hash;			/* Hash value indexed by slots */ | ||||
| +	struct sk_buff_head	*qs;		/* Slot queue */ | ||||
| +	struct esfq_head	*dep;		/* Linked list of slots, indexed by depth */ | ||||
| +}; | ||||
| + | ||||
| +/* This contains the info we will hash. */ | ||||
| +struct esfq_packet_info | ||||
| +{ | ||||
| +	u32	proto;		/* protocol or port */ | ||||
| +	u32	src;		/* source from packet header */ | ||||
| +	u32	dst;		/* destination from packet header */ | ||||
| +	u32	ctorigsrc;	/* original source from conntrack */ | ||||
| +	u32	ctorigdst;	/* original destination from conntrack */ | ||||
| +	u32	ctreplsrc;	/* reply source from conntrack */ | ||||
| +	u32	ctrepldst;	/* reply destination from conntrack */ | ||||
| +	u32	mark;		/* netfilter mark (fwmark) */ | ||||
| +}; | ||||
| + | ||||
| +static __inline__ unsigned esfq_jhash_1word(struct esfq_sched_data *q,u32 a) | ||||
| +{ | ||||
| +	return jhash_1word(a, q->perturbation) & (q->hash_divisor-1); | ||||
| +} | ||||
| + | ||||
| +static __inline__ unsigned esfq_jhash_2words(struct esfq_sched_data *q, u32 a, u32 b) | ||||
| +{ | ||||
| +	return jhash_2words(a, b, q->perturbation) & (q->hash_divisor-1); | ||||
| +} | ||||
| + | ||||
| +static __inline__ unsigned esfq_jhash_3words(struct esfq_sched_data *q, u32 a, u32 b, u32 c) | ||||
| +{ | ||||
| +	return jhash_3words(a, b, c, q->perturbation) & (q->hash_divisor-1); | ||||
| +} | ||||
| + | ||||
| +static unsigned esfq_hash(struct esfq_sched_data *q, struct sk_buff *skb) | ||||
| +{ | ||||
| +	struct esfq_packet_info info; | ||||
| +#ifdef CONFIG_NET_SCH_ESFQ_NFCT | ||||
| +	enum ip_conntrack_info ctinfo; | ||||
| +	struct nf_conn *ct = nf_ct_get(skb, &ctinfo); | ||||
| +#endif | ||||
| + | ||||
| +	switch (skb->protocol) { | ||||
| +	case __constant_htons(ETH_P_IP): | ||||
| +	{ | ||||
| +		struct iphdr *iph = ip_hdr(skb); | ||||
| +		info.dst = iph->daddr; | ||||
| +		info.src = iph->saddr; | ||||
| +		if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) && | ||||
| +		    (iph->protocol == IPPROTO_TCP || | ||||
| +		     iph->protocol == IPPROTO_UDP || | ||||
| +		     iph->protocol == IPPROTO_SCTP || | ||||
| +		     iph->protocol == IPPROTO_DCCP || | ||||
| +		     iph->protocol == IPPROTO_ESP)) | ||||
| +			info.proto = *(((u32*)iph) + iph->ihl); | ||||
| +		else | ||||
| +			info.proto = iph->protocol; | ||||
| +		break; | ||||
| +	} | ||||
| +	case __constant_htons(ETH_P_IPV6): | ||||
| +	{ | ||||
| +		struct ipv6hdr *iph = ipv6_hdr(skb); | ||||
| +		/* Hash ipv6 addresses into a u32. This isn't ideal, | ||||
| +		 * but the code is simple. */ | ||||
| +		info.dst = jhash2(iph->daddr.s6_addr32, 4, q->perturbation); | ||||
| +		info.src = jhash2(iph->saddr.s6_addr32, 4, q->perturbation); | ||||
| +		if (iph->nexthdr == IPPROTO_TCP || | ||||
| +		    iph->nexthdr == IPPROTO_UDP || | ||||
| +		    iph->nexthdr == IPPROTO_SCTP || | ||||
| +		    iph->nexthdr == IPPROTO_DCCP || | ||||
| +		    iph->nexthdr == IPPROTO_ESP) | ||||
| +			info.proto = *(u32*)&iph[1]; | ||||
| +		else | ||||
| +			info.proto = iph->nexthdr; | ||||
| +		break; | ||||
| +	} | ||||
| +	default: | ||||
| +		info.dst   = (u32)(unsigned long)skb->dst; | ||||
| +		info.src   = (u32)(unsigned long)skb->sk; | ||||
| +		info.proto = skb->protocol; | ||||
| +	} | ||||
| + | ||||
| +	info.mark = skb->mark; | ||||
| + | ||||
| +#ifdef CONFIG_NET_SCH_ESFQ_NFCT | ||||
| +	/* defaults if there is no conntrack info */ | ||||
| +	info.ctorigsrc = info.src; | ||||
| +	info.ctorigdst = info.dst; | ||||
| +	info.ctreplsrc = info.dst; | ||||
| +	info.ctrepldst = info.src; | ||||
| +	/* collect conntrack info */ | ||||
| +	if (ct && ct != &nf_conntrack_untracked) { | ||||
| +		if (skb->protocol == __constant_htons(ETH_P_IP)) { | ||||
| +			info.ctorigsrc = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip; | ||||
| +			info.ctorigdst = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip; | ||||
| +			info.ctreplsrc = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip; | ||||
| +			info.ctrepldst = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip; | ||||
| +		} | ||||
| +		else if (skb->protocol == __constant_htons(ETH_P_IPV6)) { | ||||
| +			/* Again, hash ipv6 addresses into a single u32. */ | ||||
| +			info.ctorigsrc = jhash2(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip6, 4, q->perturbation); | ||||
| +			info.ctorigdst = jhash2(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip6, 4, q->perturbation); | ||||
| +			info.ctreplsrc = jhash2(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip6, 4, q->perturbation); | ||||
| +			info.ctrepldst = jhash2(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip6, 4, q->perturbation); | ||||
| +		} | ||||
| + | ||||
| +	} | ||||
| +#endif | ||||
| + | ||||
| +	switch(q->hash_kind) { | ||||
| +	case TCA_SFQ_HASH_CLASSIC: | ||||
| +		return esfq_jhash_3words(q, info.dst, info.src, info.proto); | ||||
| +	case TCA_SFQ_HASH_DST: | ||||
| +		return esfq_jhash_1word(q, info.dst); | ||||
| +	case TCA_SFQ_HASH_SRC: | ||||
| +		return esfq_jhash_1word(q, info.src); | ||||
| +	case TCA_SFQ_HASH_FWMARK: | ||||
| +		return esfq_jhash_1word(q, info.mark); | ||||
| +#ifdef CONFIG_NET_SCH_ESFQ_NFCT | ||||
| +	case TCA_SFQ_HASH_CTORIGDST: | ||||
| +		return esfq_jhash_1word(q, info.ctorigdst); | ||||
| +	case TCA_SFQ_HASH_CTORIGSRC: | ||||
| +		return esfq_jhash_1word(q, info.ctorigsrc); | ||||
| +	case TCA_SFQ_HASH_CTREPLDST: | ||||
| +		return esfq_jhash_1word(q, info.ctrepldst); | ||||
| +	case TCA_SFQ_HASH_CTREPLSRC: | ||||
| +		return esfq_jhash_1word(q, info.ctreplsrc); | ||||
| +	case TCA_SFQ_HASH_CTNATCHG: | ||||
| +	{ | ||||
| +		if (info.ctorigdst == info.ctreplsrc) | ||||
| +			return esfq_jhash_1word(q, info.ctorigsrc); | ||||
| +		return esfq_jhash_1word(q, info.ctreplsrc); | ||||
| +	} | ||||
| +#endif | ||||
| +	default: | ||||
| +		if (net_ratelimit()) | ||||
| +			printk(KERN_WARNING "ESFQ: Unknown hash method. Falling back to classic.\n"); | ||||
| +	} | ||||
| +	return esfq_jhash_3words(q, info.dst, info.src, info.proto); | ||||
| +} | ||||
| + | ||||
| +static inline void esfq_link(struct esfq_sched_data *q, esfq_index x) | ||||
| +{ | ||||
| +	esfq_index p, n; | ||||
| +	int d = q->qs[x].qlen + q->depth; | ||||
| + | ||||
| +	p = d; | ||||
| +	n = q->dep[d].next; | ||||
| +	q->dep[x].next = n; | ||||
| +	q->dep[x].prev = p; | ||||
| +	q->dep[p].next = q->dep[n].prev = x; | ||||
| +} | ||||
| + | ||||
| +static inline void esfq_dec(struct esfq_sched_data *q, esfq_index x) | ||||
| +{ | ||||
| +	esfq_index p, n; | ||||
| + | ||||
| +	n = q->dep[x].next; | ||||
| +	p = q->dep[x].prev; | ||||
| +	q->dep[p].next = n; | ||||
| +	q->dep[n].prev = p; | ||||
| + | ||||
| +	if (n == p && q->max_depth == q->qs[x].qlen + 1) | ||||
| +		q->max_depth--; | ||||
| + | ||||
| +	esfq_link(q, x); | ||||
| +} | ||||
| + | ||||
| +static inline void esfq_inc(struct esfq_sched_data *q, esfq_index x) | ||||
| +{ | ||||
| +	esfq_index p, n; | ||||
| +	int d; | ||||
| + | ||||
| +	n = q->dep[x].next; | ||||
| +	p = q->dep[x].prev; | ||||
| +	q->dep[p].next = n; | ||||
| +	q->dep[n].prev = p; | ||||
| +	d = q->qs[x].qlen; | ||||
| +	if (q->max_depth < d) | ||||
| +		q->max_depth = d; | ||||
| + | ||||
| +	esfq_link(q, x); | ||||
| +} | ||||
| + | ||||
| +static unsigned int esfq_drop(struct Qdisc *sch) | ||||
| +{ | ||||
| +	struct esfq_sched_data *q = qdisc_priv(sch); | ||||
| +	esfq_index d = q->max_depth; | ||||
| +	struct sk_buff *skb; | ||||
| +	unsigned int len; | ||||
| + | ||||
| +	/* Queue is full! Find the longest slot and | ||||
| +	   drop a packet from it */ | ||||
| + | ||||
| +	if (d > 1) { | ||||
| +		esfq_index x = q->dep[d+q->depth].next; | ||||
| +		skb = q->qs[x].prev; | ||||
| +		len = skb->len; | ||||
| +		__skb_unlink(skb, &q->qs[x]); | ||||
| +		kfree_skb(skb); | ||||
| +		esfq_dec(q, x); | ||||
| +		sch->q.qlen--; | ||||
| +		sch->qstats.drops++; | ||||
| +		sch->qstats.backlog -= len; | ||||
| +		return len; | ||||
| +	} | ||||
| + | ||||
| +	if (d == 1) { | ||||
| +		/* It is difficult to believe, but ALL THE SLOTS HAVE LENGTH 1. */ | ||||
| +		d = q->next[q->tail]; | ||||
| +		q->next[q->tail] = q->next[d]; | ||||
| +		q->allot[q->next[d]] += q->quantum; | ||||
| +		skb = q->qs[d].prev; | ||||
| +		len = skb->len; | ||||
| +		__skb_unlink(skb, &q->qs[d]); | ||||
| +		kfree_skb(skb); | ||||
| +		esfq_dec(q, d); | ||||
| +		sch->q.qlen--; | ||||
| +		q->ht[q->hash[d]] = q->depth; | ||||
| +		sch->qstats.drops++; | ||||
| +		sch->qstats.backlog -= len; | ||||
| +		return len; | ||||
| +	} | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static void esfq_q_enqueue(struct sk_buff *skb, struct esfq_sched_data *q, unsigned int end) | ||||
| +{ | ||||
| +	unsigned hash = esfq_hash(q, skb); | ||||
| +	unsigned depth = q->depth; | ||||
| +	esfq_index x; | ||||
| + | ||||
| +	x = q->ht[hash]; | ||||
| +	if (x == depth) { | ||||
| +		q->ht[hash] = x = q->dep[depth].next; | ||||
| +		q->hash[x] = hash; | ||||
| +	} | ||||
| + | ||||
| +	if (end == ESFQ_TAIL) | ||||
| +		__skb_queue_tail(&q->qs[x], skb); | ||||
| +	else | ||||
| +		__skb_queue_head(&q->qs[x], skb); | ||||
| + | ||||
| +	esfq_inc(q, x); | ||||
| +	if (q->qs[x].qlen == 1) {		/* The flow is new */ | ||||
| +		if (q->tail == depth) {	/* It is the first flow */ | ||||
| +			q->tail = x; | ||||
| +			q->next[x] = x; | ||||
| +			q->allot[x] = q->quantum; | ||||
| +		} else { | ||||
| +			q->next[x] = q->next[q->tail]; | ||||
| +			q->next[q->tail] = x; | ||||
| +			q->tail = x; | ||||
| +		} | ||||
| +	} | ||||
| +} | ||||
| + | ||||
| +static int esfq_enqueue(struct sk_buff *skb, struct Qdisc* sch) | ||||
| +{ | ||||
| +	struct esfq_sched_data *q = qdisc_priv(sch); | ||||
| +	esfq_q_enqueue(skb, q, ESFQ_TAIL); | ||||
| +	sch->qstats.backlog += skb->len; | ||||
| +	if (++sch->q.qlen < q->limit-1) { | ||||
| +		sch->bstats.bytes += skb->len; | ||||
| +		sch->bstats.packets++; | ||||
| +		return 0; | ||||
| +	} | ||||
| + | ||||
| +	sch->qstats.drops++; | ||||
| +	esfq_drop(sch); | ||||
| +	return NET_XMIT_CN; | ||||
| +} | ||||
| + | ||||
| +static struct sk_buff *esfq_peek(struct Qdisc* sch) | ||||
| +{ | ||||
| +	struct esfq_sched_data *q = qdisc_priv(sch); | ||||
| +	esfq_index a; | ||||
| + | ||||
| +	/* No active slots */ | ||||
| +	if (q->tail == q->depth) | ||||
| +		return NULL; | ||||
| + | ||||
| +	a = q->next[q->tail]; | ||||
| +	return skb_peek(&q->qs[a]); | ||||
| +} | ||||
| + | ||||
| +static struct sk_buff *esfq_q_dequeue(struct esfq_sched_data *q) | ||||
| +{ | ||||
| +	struct sk_buff *skb; | ||||
| +	unsigned depth = q->depth; | ||||
| +	esfq_index a, old_a; | ||||
| + | ||||
| +	/* No active slots */ | ||||
| +	if (q->tail == depth) | ||||
| +		return NULL; | ||||
| + | ||||
| +	a = old_a = q->next[q->tail]; | ||||
| + | ||||
| +	/* Grab packet */ | ||||
| +	skb = __skb_dequeue(&q->qs[a]); | ||||
| +	esfq_dec(q, a); | ||||
| + | ||||
| +	/* Is the slot empty? */ | ||||
| +	if (q->qs[a].qlen == 0) { | ||||
| +		q->ht[q->hash[a]] = depth; | ||||
| +		a = q->next[a]; | ||||
| +		if (a == old_a) { | ||||
| +			q->tail = depth; | ||||
| +			return skb; | ||||
| +		} | ||||
| +		q->next[q->tail] = a; | ||||
| +		q->allot[a] += q->quantum; | ||||
| +	} else if ((q->allot[a] -= skb->len) <= 0) { | ||||
| +		q->tail = a; | ||||
| +		a = q->next[a]; | ||||
| +		q->allot[a] += q->quantum; | ||||
| +	} | ||||
| + | ||||
| +	return skb; | ||||
| +} | ||||
| + | ||||
| +static struct sk_buff *esfq_dequeue(struct Qdisc* sch) | ||||
| +{ | ||||
| +	struct esfq_sched_data *q = qdisc_priv(sch); | ||||
| +	struct sk_buff *skb; | ||||
| + | ||||
| +	skb = esfq_q_dequeue(q); | ||||
| +	if (skb == NULL) | ||||
| +		return NULL; | ||||
| +	sch->q.qlen--; | ||||
| +	sch->qstats.backlog -= skb->len; | ||||
| +	return skb; | ||||
| +} | ||||
| + | ||||
| +static void esfq_q_destroy(struct esfq_sched_data *q) | ||||
| +{ | ||||
| +	del_timer(&q->perturb_timer); | ||||
| +	if(q->ht) | ||||
| +		kfree(q->ht); | ||||
| +	if(q->dep) | ||||
| +		kfree(q->dep); | ||||
| +	if(q->next) | ||||
| +		kfree(q->next); | ||||
| +	if(q->allot) | ||||
| +		kfree(q->allot); | ||||
| +	if(q->hash) | ||||
| +		kfree(q->hash); | ||||
| +	if(q->qs) | ||||
| +		kfree(q->qs); | ||||
| +} | ||||
| + | ||||
| +static void esfq_destroy(struct Qdisc *sch) | ||||
| +{ | ||||
| +	struct esfq_sched_data *q = qdisc_priv(sch); | ||||
| +	esfq_q_destroy(q); | ||||
| +} | ||||
| + | ||||
| + | ||||
| +static void esfq_reset(struct Qdisc* sch) | ||||
| +{ | ||||
| +	struct sk_buff *skb; | ||||
| + | ||||
| +	while ((skb = esfq_dequeue(sch)) != NULL) | ||||
| +		kfree_skb(skb); | ||||
| +} | ||||
| + | ||||
| +static void esfq_perturbation(unsigned long arg) | ||||
| +{ | ||||
| +	struct Qdisc *sch = (struct Qdisc*)arg; | ||||
| +	struct esfq_sched_data *q = qdisc_priv(sch); | ||||
| + | ||||
| +	q->perturbation = net_random()&0x1F; | ||||
| + | ||||
| +	if (q->perturb_period) { | ||||
| +		q->perturb_timer.expires = jiffies + q->perturb_period; | ||||
| +		add_timer(&q->perturb_timer); | ||||
| +	} | ||||
| +} | ||||
| + | ||||
| +static unsigned int esfq_check_hash(unsigned int kind) | ||||
| +{ | ||||
| +	switch (kind) { | ||||
| +	case TCA_SFQ_HASH_CTORIGDST: | ||||
| +	case TCA_SFQ_HASH_CTORIGSRC: | ||||
| +	case TCA_SFQ_HASH_CTREPLDST: | ||||
| +	case TCA_SFQ_HASH_CTREPLSRC: | ||||
| +	case TCA_SFQ_HASH_CTNATCHG: | ||||
| +#ifndef CONFIG_NET_SCH_ESFQ_NFCT | ||||
| +	{ | ||||
| +		if (net_ratelimit()) | ||||
| +			printk(KERN_WARNING "ESFQ: Conntrack hash types disabled in kernel config. Falling back to classic.\n"); | ||||
| +		return TCA_SFQ_HASH_CLASSIC; | ||||
| +	} | ||||
| +#endif | ||||
| +	case TCA_SFQ_HASH_CLASSIC: | ||||
| +	case TCA_SFQ_HASH_DST: | ||||
| +	case TCA_SFQ_HASH_SRC: | ||||
| +	case TCA_SFQ_HASH_FWMARK: | ||||
| +		return kind; | ||||
| +	default: | ||||
| +	{ | ||||
| +		if (net_ratelimit()) | ||||
| +			printk(KERN_WARNING "ESFQ: Unknown hash type. Falling back to classic.\n"); | ||||
| +		return TCA_SFQ_HASH_CLASSIC; | ||||
| +	} | ||||
| +	} | ||||
| +} | ||||
| + | ||||
| +static int esfq_q_init(struct esfq_sched_data *q, struct nlattr *opt) | ||||
| +{ | ||||
| +	struct tc_esfq_qopt *ctl = nla_data(opt); | ||||
| +	esfq_index p = ~0U/2; | ||||
| +	int i; | ||||
| + | ||||
| +	if (opt && opt->nla_len < nla_attr_size(sizeof(*ctl))) | ||||
| +		return -EINVAL; | ||||
| + | ||||
| +	q->perturbation = 0; | ||||
| +	q->hash_kind = TCA_SFQ_HASH_CLASSIC; | ||||
| +	q->max_depth = 0; | ||||
| +	if (opt == NULL) { | ||||
| +		q->perturb_period = 0; | ||||
| +		q->hash_divisor = 1024; | ||||
| +		q->tail = q->limit = q->depth = 128; | ||||
| + | ||||
| +	} else { | ||||
| +		struct tc_esfq_qopt *ctl = nla_data(opt); | ||||
| +		if (ctl->quantum) | ||||
| +			q->quantum = ctl->quantum; | ||||
| +		q->perturb_period = ctl->perturb_period*HZ; | ||||
| +		q->hash_divisor = ctl->divisor ? : 1024; | ||||
| +		q->tail = q->limit = q->depth = ctl->flows ? : 128; | ||||
| + | ||||
| +		if ( q->depth > p - 1 ) | ||||
| +			return -EINVAL; | ||||
| + | ||||
| +		if (ctl->limit) | ||||
| +			q->limit = min_t(u32, ctl->limit, q->depth); | ||||
| + | ||||
| +		if (ctl->hash_kind) { | ||||
| +			q->hash_kind = esfq_check_hash(ctl->hash_kind); | ||||
| +		} | ||||
| +	} | ||||
| + | ||||
| +	q->ht = kmalloc(q->hash_divisor*sizeof(esfq_index), GFP_KERNEL); | ||||
| +	if (!q->ht) | ||||
| +		goto err_case; | ||||
| +	q->dep = kmalloc((1+q->depth*2)*sizeof(struct esfq_head), GFP_KERNEL); | ||||
| +	if (!q->dep) | ||||
| +		goto err_case; | ||||
| +	q->next = kmalloc(q->depth*sizeof(esfq_index), GFP_KERNEL); | ||||
| +	if (!q->next) | ||||
| +		goto err_case; | ||||
| +	q->allot = kmalloc(q->depth*sizeof(short), GFP_KERNEL); | ||||
| +	if (!q->allot) | ||||
| +		goto err_case; | ||||
| +	q->hash = kmalloc(q->depth*sizeof(unsigned short), GFP_KERNEL); | ||||
| +	if (!q->hash) | ||||
| +		goto err_case; | ||||
| +	q->qs = kmalloc(q->depth*sizeof(struct sk_buff_head), GFP_KERNEL); | ||||
| +	if (!q->qs) | ||||
| +		goto err_case; | ||||
| + | ||||
| +	for (i=0; i< q->hash_divisor; i++) | ||||
| +		q->ht[i] = q->depth; | ||||
| +	for (i=0; i<q->depth; i++) { | ||||
| +		skb_queue_head_init(&q->qs[i]); | ||||
| +		q->dep[i+q->depth].next = i+q->depth; | ||||
| +		q->dep[i+q->depth].prev = i+q->depth; | ||||
| +	} | ||||
| + | ||||
| +	for (i=0; i<q->depth; i++) | ||||
| +		esfq_link(q, i); | ||||
| +	return 0; | ||||
| +err_case: | ||||
| +	esfq_q_destroy(q); | ||||
| +	return -ENOBUFS; | ||||
| +} | ||||
| + | ||||
| +static int esfq_init(struct Qdisc *sch, struct nlattr *opt) | ||||
| +{ | ||||
| +	struct esfq_sched_data *q = qdisc_priv(sch); | ||||
| +	int err; | ||||
| + | ||||
| +	q->quantum = psched_mtu(qdisc_dev(sch)); /* default */ | ||||
| +	if ((err = esfq_q_init(q, opt))) | ||||
| +		return err; | ||||
| + | ||||
| +	init_timer(&q->perturb_timer); | ||||
| +	q->perturb_timer.data = (unsigned long)sch; | ||||
| +	q->perturb_timer.function = esfq_perturbation; | ||||
| +	if (q->perturb_period) { | ||||
| +		q->perturb_timer.expires = jiffies + q->perturb_period; | ||||
| +		add_timer(&q->perturb_timer); | ||||
| +	} | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static int esfq_change(struct Qdisc *sch, struct nlattr *opt) | ||||
| +{ | ||||
| +	struct esfq_sched_data *q = qdisc_priv(sch); | ||||
| +	struct esfq_sched_data new; | ||||
| +	struct sk_buff *skb; | ||||
| +	int err; | ||||
| + | ||||
| +	/* set up new queue */ | ||||
| +	memset(&new, 0, sizeof(struct esfq_sched_data)); | ||||
| +	new.quantum = psched_mtu(qdisc_dev(sch)); /* default */ | ||||
| +	if ((err = esfq_q_init(&new, opt))) | ||||
| +		return err; | ||||
| + | ||||
| +	/* copy all packets from the old queue to the new queue */ | ||||
| +	sch_tree_lock(sch); | ||||
| +	while ((skb = esfq_q_dequeue(q)) != NULL) | ||||
| +		esfq_q_enqueue(skb, &new, ESFQ_TAIL); | ||||
| + | ||||
| +	/* clean up the old queue */ | ||||
| +	esfq_q_destroy(q); | ||||
| + | ||||
| +	/* copy elements of the new queue into the old queue */ | ||||
| +	q->perturb_period = new.perturb_period; | ||||
| +	q->quantum        = new.quantum; | ||||
| +	q->limit          = new.limit; | ||||
| +	q->depth          = new.depth; | ||||
| +	q->hash_divisor   = new.hash_divisor; | ||||
| +	q->hash_kind      = new.hash_kind; | ||||
| +	q->tail           = new.tail; | ||||
| +	q->max_depth      = new.max_depth; | ||||
| +	q->ht    = new.ht; | ||||
| +	q->dep   = new.dep; | ||||
| +	q->next  = new.next; | ||||
| +	q->allot = new.allot; | ||||
| +	q->hash  = new.hash; | ||||
| +	q->qs    = new.qs; | ||||
| + | ||||
| +	/* finish up */ | ||||
| +	if (q->perturb_period) { | ||||
| +		q->perturb_timer.expires = jiffies + q->perturb_period; | ||||
| +		add_timer(&q->perturb_timer); | ||||
| +	} else { | ||||
| +		q->perturbation = 0; | ||||
| +	} | ||||
| +	sch_tree_unlock(sch); | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static int esfq_dump(struct Qdisc *sch, struct sk_buff *skb) | ||||
| +{ | ||||
| +	struct esfq_sched_data *q = qdisc_priv(sch); | ||||
| +	unsigned char *b = skb_tail_pointer(skb); | ||||
| +	struct tc_esfq_qopt opt; | ||||
| + | ||||
| +	opt.quantum = q->quantum; | ||||
| +	opt.perturb_period = q->perturb_period/HZ; | ||||
| + | ||||
| +	opt.limit = q->limit; | ||||
| +	opt.divisor = q->hash_divisor; | ||||
| +	opt.flows = q->depth; | ||||
| +	opt.hash_kind = q->hash_kind; | ||||
| + | ||||
| +	NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); | ||||
| + | ||||
| +	return skb->len; | ||||
| + | ||||
| +nla_put_failure: | ||||
| +	nlmsg_trim(skb, b); | ||||
| +	return -1; | ||||
| +} | ||||
| + | ||||
| +static struct Qdisc_ops esfq_qdisc_ops = | ||||
| +{ | ||||
| +	.next		=	NULL, | ||||
| +	.cl_ops		=	NULL, | ||||
| +	.id		=	"esfq", | ||||
| +	.priv_size	=	sizeof(struct esfq_sched_data), | ||||
| +	.enqueue	=	esfq_enqueue, | ||||
| +	.dequeue	=	esfq_dequeue, | ||||
| +	.peek		=	esfq_peek, | ||||
| +	.drop		=	esfq_drop, | ||||
| +	.init		=	esfq_init, | ||||
| +	.reset		=	esfq_reset, | ||||
| +	.destroy	=	esfq_destroy, | ||||
| +	.change		=	esfq_change, | ||||
| +	.dump		=	esfq_dump, | ||||
| +	.owner		=	THIS_MODULE, | ||||
| +}; | ||||
| + | ||||
| +static int __init esfq_module_init(void) | ||||
| +{ | ||||
| +	return register_qdisc(&esfq_qdisc_ops); | ||||
| +} | ||||
| +static void __exit esfq_module_exit(void) | ||||
| +{ | ||||
| +	unregister_qdisc(&esfq_qdisc_ops); | ||||
| +} | ||||
| +module_init(esfq_module_init) | ||||
| +module_exit(esfq_module_exit) | ||||
| +MODULE_LICENSE("GPL"); | ||||
| @@ -1,227 +0,0 @@ | ||||
| --- a/include/linux/jhash.h | ||||
| +++ b/include/linux/jhash.h | ||||
| @@ -3,80 +3,95 @@ | ||||
|   | ||||
|  /* jhash.h: Jenkins hash support. | ||||
|   * | ||||
| - * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net) | ||||
| + * Copyright (C) 2006. Bob Jenkins (bob_jenkins@burtleburtle.net) | ||||
|   * | ||||
|   * http://burtleburtle.net/bob/hash/ | ||||
|   * | ||||
|   * These are the credits from Bob's sources: | ||||
|   * | ||||
| - * lookup2.c, by Bob Jenkins, December 1996, Public Domain. | ||||
| - * hash(), hash2(), hash3, and mix() are externally useful functions. | ||||
| - * Routines to test the hash are included if SELF_TEST is defined. | ||||
| - * You can use this free for any purpose.  It has no warranty. | ||||
| + * lookup3.c, by Bob Jenkins, May 2006, Public Domain. | ||||
|   * | ||||
| - * Copyright (C) 2003 David S. Miller (davem@redhat.com) | ||||
| + * These are functions for producing 32-bit hashes for hash table lookup. | ||||
| + * hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final()  | ||||
| + * are externally useful functions.  Routines to test the hash are included  | ||||
| + * if SELF_TEST is defined.  You can use this free for any purpose.  It's in | ||||
| + * the public domain.  It has no warranty. | ||||
| + * | ||||
| + * Copyright (C) 2009 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu) | ||||
|   * | ||||
|   * I've modified Bob's hash to be useful in the Linux kernel, and | ||||
| - * any bugs present are surely my fault.  -DaveM | ||||
| + * any bugs present are my fault.  Jozsef | ||||
|   */ | ||||
|   | ||||
| -/* NOTE: Arguments are modified. */ | ||||
| -#define __jhash_mix(a, b, c) \ | ||||
| +#define __rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) | ||||
| + | ||||
| +/* __jhash_mix - mix 3 32-bit values reversibly. */ | ||||
| +#define __jhash_mix(a,b,c) \ | ||||
| +{ \ | ||||
| +  a -= c;  a ^= __rot(c, 4);  c += b; \ | ||||
| +  b -= a;  b ^= __rot(a, 6);  a += c; \ | ||||
| +  c -= b;  c ^= __rot(b, 8);  b += a; \ | ||||
| +  a -= c;  a ^= __rot(c,16);  c += b; \ | ||||
| +  b -= a;  b ^= __rot(a,19);  a += c; \ | ||||
| +  c -= b;  c ^= __rot(b, 4);  b += a; \ | ||||
| +} | ||||
| + | ||||
| +/* __jhash_final - final mixing of 3 32-bit values (a,b,c) into c */ | ||||
| +#define __jhash_final(a,b,c) \ | ||||
|  { \ | ||||
| -  a -= b; a -= c; a ^= (c>>13); \ | ||||
| -  b -= c; b -= a; b ^= (a<<8); \ | ||||
| -  c -= a; c -= b; c ^= (b>>13); \ | ||||
| -  a -= b; a -= c; a ^= (c>>12);  \ | ||||
| -  b -= c; b -= a; b ^= (a<<16); \ | ||||
| -  c -= a; c -= b; c ^= (b>>5); \ | ||||
| -  a -= b; a -= c; a ^= (c>>3);  \ | ||||
| -  b -= c; b -= a; b ^= (a<<10); \ | ||||
| -  c -= a; c -= b; c ^= (b>>15); \ | ||||
| +  c ^= b; c -= __rot(b,14); \ | ||||
| +  a ^= c; a -= __rot(c,11); \ | ||||
| +  b ^= a; b -= __rot(a,25); \ | ||||
| +  c ^= b; c -= __rot(b,16); \ | ||||
| +  a ^= c; a -= __rot(c,4);  \ | ||||
| +  b ^= a; b -= __rot(a,14); \ | ||||
| +  c ^= b; c -= __rot(b,24); \ | ||||
|  } | ||||
|   | ||||
| -/* The golden ration: an arbitrary value */ | ||||
| -#define JHASH_GOLDEN_RATIO	0x9e3779b9 | ||||
| +/* An arbitrary initial parameter */ | ||||
| +#define JHASH_GOLDEN_RATIO	0xdeadbeef | ||||
|   | ||||
|  /* The most generic version, hashes an arbitrary sequence | ||||
|   * of bytes.  No alignment or length assumptions are made about | ||||
| - * the input key. | ||||
| + * the input key. The result depends on endianness. | ||||
|   */ | ||||
|  static inline u32 jhash(const void *key, u32 length, u32 initval) | ||||
|  { | ||||
| -	u32 a, b, c, len; | ||||
| +	u32 a,b,c; | ||||
|  	const u8 *k = key; | ||||
|   | ||||
| -	len = length; | ||||
| -	a = b = JHASH_GOLDEN_RATIO; | ||||
| -	c = initval; | ||||
| - | ||||
| -	while (len >= 12) { | ||||
| -		a += (k[0] +((u32)k[1]<<8) +((u32)k[2]<<16) +((u32)k[3]<<24)); | ||||
| -		b += (k[4] +((u32)k[5]<<8) +((u32)k[6]<<16) +((u32)k[7]<<24)); | ||||
| -		c += (k[8] +((u32)k[9]<<8) +((u32)k[10]<<16)+((u32)k[11]<<24)); | ||||
| - | ||||
| -		__jhash_mix(a,b,c); | ||||
| +	/* Set up the internal state */ | ||||
| +	a = b = c = JHASH_GOLDEN_RATIO + length + initval; | ||||
|   | ||||
| +	/* all but the last block: affect some 32 bits of (a,b,c) */ | ||||
| +	while (length > 12) { | ||||
| +    		a += (k[0] + ((u32)k[1]<<8) + ((u32)k[2]<<16) + ((u32)k[3]<<24)); | ||||
| +		b += (k[4] + ((u32)k[5]<<8) + ((u32)k[6]<<16) + ((u32)k[7]<<24)); | ||||
| +		c += (k[8] + ((u32)k[9]<<8) + ((u32)k[10]<<16) + ((u32)k[11]<<24)); | ||||
| +		__jhash_mix(a, b, c); | ||||
| +		length -= 12; | ||||
|  		k += 12; | ||||
| -		len -= 12; | ||||
|  	} | ||||
|   | ||||
| -	c += length; | ||||
| -	switch (len) { | ||||
| -	case 11: c += ((u32)k[10]<<24); | ||||
| -	case 10: c += ((u32)k[9]<<16); | ||||
| -	case 9 : c += ((u32)k[8]<<8); | ||||
| -	case 8 : b += ((u32)k[7]<<24); | ||||
| -	case 7 : b += ((u32)k[6]<<16); | ||||
| -	case 6 : b += ((u32)k[5]<<8); | ||||
| +	/* last block: affect all 32 bits of (c) */ | ||||
| +	/* all the case statements fall through */ | ||||
| +	switch (length) { | ||||
| +	case 12: c += (u32)k[11]<<24; | ||||
| +	case 11: c += (u32)k[10]<<16; | ||||
| +	case 10: c += (u32)k[9]<<8; | ||||
| +	case 9 : c += k[8]; | ||||
| +	case 8 : b += (u32)k[7]<<24; | ||||
| +	case 7 : b += (u32)k[6]<<16; | ||||
| +	case 6 : b += (u32)k[5]<<8; | ||||
|  	case 5 : b += k[4]; | ||||
| -	case 4 : a += ((u32)k[3]<<24); | ||||
| -	case 3 : a += ((u32)k[2]<<16); | ||||
| -	case 2 : a += ((u32)k[1]<<8); | ||||
| +	case 4 : a += (u32)k[3]<<24; | ||||
| +	case 3 : a += (u32)k[2]<<16; | ||||
| +	case 2 : a += (u32)k[1]<<8; | ||||
|  	case 1 : a += k[0]; | ||||
| -	}; | ||||
| - | ||||
| -	__jhash_mix(a,b,c); | ||||
| +		__jhash_final(a, b, c); | ||||
| +	case 0 : | ||||
| +		break; | ||||
| +	} | ||||
|   | ||||
|  	return c; | ||||
|  } | ||||
| @@ -86,58 +101,57 @@ static inline u32 jhash(const void *key, | ||||
|   */ | ||||
|  static inline u32 jhash2(const u32 *k, u32 length, u32 initval) | ||||
|  { | ||||
| -	u32 a, b, c, len; | ||||
| +	u32 a, b, c; | ||||
|   | ||||
| -	a = b = JHASH_GOLDEN_RATIO; | ||||
| -	c = initval; | ||||
| -	len = length; | ||||
| +	/* Set up the internal state */ | ||||
| +	a = b = c = JHASH_GOLDEN_RATIO + (length<<2) + initval; | ||||
|   | ||||
| -	while (len >= 3) { | ||||
| +	/* handle most of the key */ | ||||
| +	while (length > 3) { | ||||
|  		a += k[0]; | ||||
|  		b += k[1]; | ||||
|  		c += k[2]; | ||||
|  		__jhash_mix(a, b, c); | ||||
| -		k += 3; len -= 3; | ||||
| +		length -= 3; | ||||
| +		k += 3; | ||||
|  	} | ||||
|   | ||||
| -	c += length * 4; | ||||
| - | ||||
| -	switch (len) { | ||||
| -	case 2 : b += k[1]; | ||||
| -	case 1 : a += k[0]; | ||||
| -	}; | ||||
| - | ||||
| -	__jhash_mix(a,b,c); | ||||
| +	/* handle the last 3 u32's */ | ||||
| +	/* all the case statements fall through */  | ||||
| +	switch (length) { | ||||
| +	case 3: c += k[2]; | ||||
| +	case 2: b += k[1]; | ||||
| +	case 1: a += k[0]; | ||||
| +		__jhash_final(a, b, c); | ||||
| +	case 0:     /* case 0: nothing left to add */ | ||||
| +		break; | ||||
| +	} | ||||
|   | ||||
|  	return c; | ||||
|  } | ||||
|   | ||||
| - | ||||
|  /* A special ultra-optimized versions that knows they are hashing exactly | ||||
|   * 3, 2 or 1 word(s). | ||||
| - * | ||||
| - * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally | ||||
| - *       done at the end is not done here. | ||||
|   */ | ||||
|  static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval) | ||||
|  { | ||||
| -	a += JHASH_GOLDEN_RATIO; | ||||
| -	b += JHASH_GOLDEN_RATIO; | ||||
| -	c += initval; | ||||
| +	a += JHASH_GOLDEN_RATIO + initval; | ||||
| +	b += JHASH_GOLDEN_RATIO + initval; | ||||
| +	c += JHASH_GOLDEN_RATIO + initval; | ||||
|   | ||||
| -	__jhash_mix(a, b, c); | ||||
| +	__jhash_final(a, b, c); | ||||
|   | ||||
|  	return c; | ||||
|  } | ||||
|   | ||||
|  static inline u32 jhash_2words(u32 a, u32 b, u32 initval) | ||||
|  { | ||||
| -	return jhash_3words(a, b, 0, initval); | ||||
| +	return jhash_3words(0, a, b, initval); | ||||
|  } | ||||
|   | ||||
|  static inline u32 jhash_1word(u32 a, u32 initval) | ||||
|  { | ||||
| -	return jhash_3words(a, 0, 0, initval); | ||||
| +	return jhash_3words(0, 0, a, initval); | ||||
|  } | ||||
|   | ||||
|  #endif /* _LINUX_JHASH_H */ | ||||
| @@ -1,12 +0,0 @@ | ||||
| --- a/arch/mips/Makefile | ||||
| +++ b/arch/mips/Makefile | ||||
| @@ -609,6 +609,9 @@ else | ||||
|  load-$(CONFIG_CPU_CAVIUM_OCTEON) 	+= 0xffffffff81100000 | ||||
|  endif | ||||
|   | ||||
| +# temporary until string.h is fixed | ||||
| +cflags-y += -ffreestanding | ||||
| + | ||||
|  cflags-y			+= -I$(srctree)/arch/mips/include/asm/mach-generic | ||||
|  drivers-$(CONFIG_PCI)		+= arch/mips/pci/ | ||||
|   | ||||
| @@ -1,13 +0,0 @@ | ||||
| --- a/include/linux/slab.h | ||||
| +++ b/include/linux/slab.h | ||||
| @@ -115,8 +115,8 @@ int kmem_ptr_validate(struct kmem_cache  | ||||
|   * to do various tricks to work around compiler limitations in order to | ||||
|   * ensure proper constant folding. | ||||
|   */ | ||||
| -#define KMALLOC_SHIFT_HIGH	((MAX_ORDER + PAGE_SHIFT - 1) <= 25 ? \ | ||||
| -				(MAX_ORDER + PAGE_SHIFT - 1) : 25) | ||||
| +#define KMALLOC_SHIFT_HIGH	((MAX_ORDER + PAGE_SHIFT - 1) <= 17 ? \ | ||||
| +				(MAX_ORDER + PAGE_SHIFT - 1) : 17) | ||||
|   | ||||
|  #define KMALLOC_MAX_SIZE	(1UL << KMALLOC_SHIFT_HIGH) | ||||
|  #define KMALLOC_MAX_ORDER	(KMALLOC_SHIFT_HIGH - PAGE_SHIFT) | ||||
| @@ -1,132 +0,0 @@ | ||||
| --- a/fs/jffs2/build.c | ||||
| +++ b/fs/jffs2/build.c | ||||
| @@ -111,6 +111,17 @@ static int jffs2_build_filesystem(struct | ||||
|  	dbg_fsbuild("scanned flash completely\n"); | ||||
|  	jffs2_dbg_dump_block_lists_nolock(c); | ||||
|   | ||||
| +	if (c->flags & (1 << 7)) { | ||||
| +		printk("%s(): unlocking the mtd device... ", __func__); | ||||
| +		if (c->mtd->unlock) | ||||
| +			c->mtd->unlock(c->mtd, 0, c->mtd->size); | ||||
| +		printk("done.\n"); | ||||
| + | ||||
| +		printk("%s(): erasing all blocks after the end marker... ", __func__); | ||||
| +		jffs2_erase_pending_blocks(c, -1); | ||||
| +		printk("done.\n"); | ||||
| +	} | ||||
| + | ||||
|  	dbg_fsbuild("pass 1 starting\n"); | ||||
|  	c->flags |= JFFS2_SB_FLAG_BUILDING; | ||||
|  	/* Now scan the directory tree, increasing nlink according to every dirent found. */ | ||||
| --- a/fs/jffs2/scan.c | ||||
| +++ b/fs/jffs2/scan.c | ||||
| @@ -72,7 +72,7 @@ static int file_dirty(struct jffs2_sb_in | ||||
|  		return ret; | ||||
|  	if ((ret = jffs2_scan_dirty_space(c, jeb, jeb->free_size))) | ||||
|  		return ret; | ||||
| -	/* Turned wasted size into dirty, since we apparently  | ||||
| +	/* Turned wasted size into dirty, since we apparently | ||||
|  	   think it's recoverable now. */ | ||||
|  	jeb->dirty_size += jeb->wasted_size; | ||||
|  	c->dirty_size += jeb->wasted_size; | ||||
| @@ -144,8 +144,11 @@ int jffs2_scan_medium(struct jffs2_sb_in | ||||
|  		/* reset summary info for next eraseblock scan */ | ||||
|  		jffs2_sum_reset_collected(s); | ||||
|   | ||||
| -		ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset), | ||||
| -						buf_size, s); | ||||
| +		if (c->flags & (1 << 7)) | ||||
| +			ret = BLK_STATE_ALLFF; | ||||
| +		else | ||||
| +			ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset), | ||||
| +							buf_size, s); | ||||
|   | ||||
|  		if (ret < 0) | ||||
|  			goto out; | ||||
| @@ -400,7 +403,7 @@ static int jffs2_scan_xref_node(struct j | ||||
|  	if (!ref) | ||||
|  		return -ENOMEM; | ||||
|   | ||||
| -	/* BEFORE jffs2_build_xattr_subsystem() called,  | ||||
| +	/* BEFORE jffs2_build_xattr_subsystem() called, | ||||
|  	 * and AFTER xattr_ref is marked as a dead xref, | ||||
|  	 * ref->xid is used to store 32bit xid, xd is not used | ||||
|  	 * ref->ino is used to store 32bit inode-number, ic is not used | ||||
| @@ -473,7 +476,7 @@ static int jffs2_scan_eraseblock (struct | ||||
|  		struct jffs2_sum_marker *sm; | ||||
|  		void *sumptr = NULL; | ||||
|  		uint32_t sumlen; | ||||
| -	       | ||||
| + | ||||
|  		if (!buf_size) { | ||||
|  			/* XIP case. Just look, point at the summary if it's there */ | ||||
|  			sm = (void *)buf + c->sector_size - sizeof(*sm); | ||||
| @@ -489,9 +492,9 @@ static int jffs2_scan_eraseblock (struct | ||||
|  				buf_len = sizeof(*sm); | ||||
|   | ||||
|  			/* Read as much as we want into the _end_ of the preallocated buffer */ | ||||
| -			err = jffs2_fill_scan_buf(c, buf + buf_size - buf_len,  | ||||
| +			err = jffs2_fill_scan_buf(c, buf + buf_size - buf_len, | ||||
|  						  jeb->offset + c->sector_size - buf_len, | ||||
| -						  buf_len);				 | ||||
| +						  buf_len); | ||||
|  			if (err) | ||||
|  				return err; | ||||
|   | ||||
| @@ -510,9 +513,9 @@ static int jffs2_scan_eraseblock (struct | ||||
|  				} | ||||
|  				if (buf_len < sumlen) { | ||||
|  					/* Need to read more so that the entire summary node is present */ | ||||
| -					err = jffs2_fill_scan_buf(c, sumptr,  | ||||
| +					err = jffs2_fill_scan_buf(c, sumptr, | ||||
|  								  jeb->offset + c->sector_size - sumlen, | ||||
| -								  sumlen - buf_len);				 | ||||
| +								  sumlen - buf_len); | ||||
|  					if (err) | ||||
|  						return err; | ||||
|  				} | ||||
| @@ -525,7 +528,7 @@ static int jffs2_scan_eraseblock (struct | ||||
|   | ||||
|  			if (buf_size && sumlen > buf_size) | ||||
|  				kfree(sumptr); | ||||
| -			/* If it returns with a real error, bail.  | ||||
| +			/* If it returns with a real error, bail. | ||||
|  			   If it returns positive, that's a block classification | ||||
|  			   (i.e. BLK_STATE_xxx) so return that too. | ||||
|  			   If it returns zero, fall through to full scan. */ | ||||
| @@ -546,6 +549,17 @@ static int jffs2_scan_eraseblock (struct | ||||
|  			return err; | ||||
|  	} | ||||
|   | ||||
| +	if ((buf[0] == 0xde) && | ||||
| +		(buf[1] == 0xad) && | ||||
| +		(buf[2] == 0xc0) && | ||||
| +		(buf[3] == 0xde)) { | ||||
| +		/* end of filesystem. erase everything after this point */ | ||||
| +		printk("%s(): End of filesystem marker found at 0x%x\n", __func__, jeb->offset); | ||||
| +		c->flags |= (1 << 7); | ||||
| + | ||||
| +		return BLK_STATE_ALLFF; | ||||
| +	} | ||||
| + | ||||
|  	/* We temporarily use 'ofs' as a pointer into the buffer/jeb */ | ||||
|  	ofs = 0; | ||||
|   | ||||
| @@ -671,7 +685,7 @@ scan_more: | ||||
|  				scan_end = buf_len; | ||||
|  				goto more_empty; | ||||
|  			} | ||||
| -			 | ||||
| + | ||||
|  			/* See how much more there is to read in this eraseblock... */ | ||||
|  			buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs); | ||||
|  			if (!buf_len) { | ||||
| @@ -907,7 +921,7 @@ scan_more: | ||||
|   | ||||
|  	D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x, wasted 0x%08x\n", | ||||
|  		  jeb->offset,jeb->free_size, jeb->dirty_size, jeb->unchecked_size, jeb->used_size, jeb->wasted_size)); | ||||
| -	 | ||||
| + | ||||
|  	/* mark_node_obsolete can add to wasted !! */ | ||||
|  	if (jeb->wasted_size) { | ||||
|  		jeb->dirty_size += jeb->wasted_size; | ||||
| @@ -1,56 +0,0 @@ | ||||
| --- a/include/linux/skbuff.h | ||||
| +++ b/include/linux/skbuff.h | ||||
| @@ -1306,11 +1306,18 @@ static inline int skb_network_offset(con | ||||
|   * | ||||
|   * Various parts of the networking layer expect at least 16 bytes of | ||||
|   * headroom, you should not reduce this. | ||||
| + * | ||||
| + * This has been changed to 64 to acommodate for routing between ethernet | ||||
| + * and wireless, but only for new allocations | ||||
|   */ | ||||
|  #ifndef NET_SKB_PAD | ||||
|  #define NET_SKB_PAD	16 | ||||
|  #endif | ||||
|   | ||||
| +#ifndef NET_SKB_PAD_ALLOC | ||||
| +#define NET_SKB_PAD_ALLOC	64 | ||||
| +#endif | ||||
| + | ||||
|  extern int ___pskb_trim(struct sk_buff *skb, unsigned int len); | ||||
|   | ||||
|  static inline void __skb_trim(struct sk_buff *skb, unsigned int len) | ||||
| @@ -1400,9 +1407,9 @@ static inline void __skb_queue_purge(str | ||||
|  static inline struct sk_buff *__dev_alloc_skb(unsigned int length, | ||||
|  					      gfp_t gfp_mask) | ||||
|  { | ||||
| -	struct sk_buff *skb = alloc_skb(length + NET_SKB_PAD, gfp_mask); | ||||
| +	struct sk_buff *skb = alloc_skb(length + NET_SKB_PAD_ALLOC, gfp_mask); | ||||
|  	if (likely(skb)) | ||||
| -		skb_reserve(skb, NET_SKB_PAD); | ||||
| +		skb_reserve(skb, NET_SKB_PAD_ALLOC); | ||||
|  	return skb; | ||||
|  } | ||||
|   | ||||
| @@ -1475,7 +1482,7 @@ static inline int __skb_cow(struct sk_bu | ||||
|  		delta = headroom - skb_headroom(skb); | ||||
|   | ||||
|  	if (delta || cloned) | ||||
| -		return pskb_expand_head(skb, ALIGN(delta, NET_SKB_PAD), 0, | ||||
| +		return pskb_expand_head(skb, ALIGN(delta, NET_SKB_PAD_ALLOC), 0, | ||||
|  					GFP_ATOMIC); | ||||
|  	return 0; | ||||
|  } | ||||
| --- a/net/core/skbuff.c | ||||
| +++ b/net/core/skbuff.c | ||||
| @@ -320,9 +320,9 @@ struct sk_buff *__netdev_alloc_skb(struc | ||||
|  	int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1; | ||||
|  	struct sk_buff *skb; | ||||
|   | ||||
| -	skb = __alloc_skb(length + NET_SKB_PAD, gfp_mask, 0, node); | ||||
| +	skb = __alloc_skb(length + NET_SKB_PAD_ALLOC, gfp_mask, 0, node); | ||||
|  	if (likely(skb)) { | ||||
| -		skb_reserve(skb, NET_SKB_PAD); | ||||
| +		skb_reserve(skb, NET_SKB_PAD_ALLOC); | ||||
|  		skb->dev = dev; | ||||
|  	} | ||||
|  	return skb; | ||||
| @@ -1,9 +0,0 @@ | ||||
| --- /dev/null | ||||
| +++ b/include/asm-powerpc/segment.h | ||||
| @@ -0,0 +1,6 @@ | ||||
| +#ifndef _ASM_SEGMENT_H | ||||
| +#define _ASM_SEGMENT_H | ||||
| + | ||||
| +/* Only here because we have some old header files that expect it.. */ | ||||
| + | ||||
| +#endif /* _ASM_SEGMENT_H */ | ||||
| @@ -1,42 +0,0 @@ | ||||
| --- a/drivers/net/r8169.c | ||||
| +++ b/drivers/net/r8169.c | ||||
| @@ -1889,7 +1889,7 @@ static const struct rtl_cfg_info { | ||||
|  		.hw_start	= rtl_hw_start_8169, | ||||
|  		.region		= 1, | ||||
|  		.align		= 0, | ||||
| -		.intr_event	= SYSErr | LinkChg | RxOverflow | | ||||
| +		.intr_event	= LinkChg | RxOverflow | | ||||
|  				  RxFIFOOver | TxErr | TxOK | RxOK | RxErr, | ||||
|  		.napi_event	= RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, | ||||
|  		.features	= RTL_FEATURE_GMII | ||||
| @@ -1898,7 +1898,7 @@ static const struct rtl_cfg_info { | ||||
|  		.hw_start	= rtl_hw_start_8168, | ||||
|  		.region		= 2, | ||||
|  		.align		= 8, | ||||
| -		.intr_event	= SYSErr | LinkChg | RxOverflow | | ||||
| +		.intr_event	= LinkChg | RxOverflow | | ||||
|  				  TxErr | TxOK | RxOK | RxErr, | ||||
|  		.napi_event	= TxErr | TxOK | RxOK | RxOverflow, | ||||
|  		.features	= RTL_FEATURE_GMII | RTL_FEATURE_MSI | ||||
| @@ -1907,7 +1907,7 @@ static const struct rtl_cfg_info { | ||||
|  		.hw_start	= rtl_hw_start_8101, | ||||
|  		.region		= 2, | ||||
|  		.align		= 8, | ||||
| -		.intr_event	= SYSErr | LinkChg | RxOverflow | PCSTimeout | | ||||
| +		.intr_event	= LinkChg | RxOverflow | PCSTimeout | | ||||
|  				  RxFIFOOver | TxErr | TxOK | RxOK | RxErr, | ||||
|  		.napi_event	= RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, | ||||
|  		.features	= RTL_FEATURE_MSI | ||||
| @@ -3576,10 +3576,12 @@ static irqreturn_t rtl8169_interrupt(int | ||||
|  			break; | ||||
|  		} | ||||
|   | ||||
| +#if 0 | ||||
|  		if (unlikely(status & SYSErr)) { | ||||
|  			rtl8169_pcierr_interrupt(dev); | ||||
|  			break; | ||||
|  		} | ||||
| +#endif | ||||
|   | ||||
|  		if (status & LinkChg) | ||||
|  			rtl8169_check_link_status(dev, tp, ioaddr); | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,143 +0,0 @@ | ||||
| --- a/fs/mini_fo/main.c | ||||
| +++ b/fs/mini_fo/main.c | ||||
| @@ -79,6 +79,7 @@ mini_fo_tri_interpose(dentry_t *hidden_d | ||||
|  	 * of the new inode's fields | ||||
|  	 */ | ||||
|   | ||||
| +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) | ||||
|  	/* | ||||
|  	 * original: inode = iget(sb, hidden_inode->i_ino); | ||||
|  	 */ | ||||
| @@ -87,6 +88,13 @@ mini_fo_tri_interpose(dentry_t *hidden_d | ||||
|  		err = -EACCES;		/* should be impossible??? */ | ||||
|  		goto out; | ||||
|  	} | ||||
| +#else | ||||
| +	inode = mini_fo_iget(sb, iunique(sb, 25)); | ||||
| +	if (IS_ERR(inode)) { | ||||
| +		err = PTR_ERR(inode); | ||||
| +		goto out; | ||||
| +	} | ||||
| +#endif | ||||
|   | ||||
|  	/* | ||||
|  	 * interpose the inode if not already interposed | ||||
| @@ -184,9 +192,9 @@ mini_fo_parse_options(super_block_t *sb, | ||||
|  				hidden_root = ERR_PTR(err); | ||||
|  				goto out; | ||||
|  			} | ||||
| -			hidden_root = nd.dentry; | ||||
| -			stopd(sb)->base_dir_dentry = nd.dentry; | ||||
| -			stopd(sb)->hidden_mnt = nd.mnt; | ||||
| +			hidden_root = nd_get_dentry(&nd); | ||||
| +			stopd(sb)->base_dir_dentry = nd_get_dentry(&nd); | ||||
| +			stopd(sb)->hidden_mnt = nd_get_mnt(&nd); | ||||
|   | ||||
|  		} else if(!strncmp("sto=", options, 4)) { | ||||
|  			/* parse the storage dir */ | ||||
| @@ -204,9 +212,9 @@ mini_fo_parse_options(super_block_t *sb, | ||||
|  				hidden_root2 = ERR_PTR(err); | ||||
|  				goto out; | ||||
|  			} | ||||
| -			hidden_root2 = nd2.dentry; | ||||
| -			stopd(sb)->storage_dir_dentry = nd2.dentry; | ||||
| -			stopd(sb)->hidden_mnt2 = nd2.mnt; | ||||
| +			hidden_root2 = nd_get_dentry(&nd2); | ||||
| +			stopd(sb)->storage_dir_dentry = nd_get_dentry(&nd2); | ||||
| +			stopd(sb)->hidden_mnt2 = nd_get_mnt(&nd2); | ||||
|  			stohs2(sb) = hidden_root2->d_sb; | ||||
|   | ||||
|  			/* validate storage dir, this is done in | ||||
| --- a/fs/mini_fo/mini_fo.h | ||||
| +++ b/fs/mini_fo/mini_fo.h | ||||
| @@ -302,6 +302,10 @@ extern int mini_fo_tri_interpose(dentry_ | ||||
|  extern int mini_fo_cp_cont(dentry_t *tgt_dentry, struct vfsmount *tgt_mnt, | ||||
|  			   dentry_t *src_dentry, struct vfsmount *src_mnt); | ||||
|   | ||||
| +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) | ||||
| +extern struct inode *mini_fo_iget(struct super_block *sb, unsigned long ino); | ||||
| +#endif | ||||
| + | ||||
|  #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  | ||||
|  #endif  /* if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) */ | ||||
|  #endif /* __KERNEL__ */ | ||||
|   | ||||
| + | ||||
| +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) | ||||
| +static inline dentry_t *nd_get_dentry(struct nameidata *nd) | ||||
| +{ | ||||
| +	return (nd->path.dentry); | ||||
| +} | ||||
| + | ||||
| +static inline struct vfsmount *nd_get_mnt(struct nameidata *nd) | ||||
| +{ | ||||
| +	return (nd->path.mnt); | ||||
| +} | ||||
| +#else | ||||
| +static inline dentry_t *nd_get_dentry(struct nameidata *nd) | ||||
| +{ | ||||
| +	return (nd->dentry); | ||||
| +} | ||||
| + | ||||
| +static inline struct vfsmount *nd_get_mnt(struct nameidata *nd) | ||||
| +{ | ||||
| +	return (nd->mnt); | ||||
| +} | ||||
| +#endif | ||||
| + | ||||
|  /* | ||||
|   * Definitions for user and kernel code | ||||
|   */ | ||||
| --- a/fs/mini_fo/super.c | ||||
| +++ b/fs/mini_fo/super.c | ||||
| @@ -262,10 +262,31 @@ mini_fo_umount_begin(super_block_t *sb) | ||||
|  } | ||||
|  #endif | ||||
|   | ||||
| +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) | ||||
| +struct inode * | ||||
| +mini_fo_iget(struct super_block *sb, unsigned long ino) | ||||
| +{ | ||||
| +	struct inode *inode; | ||||
| + | ||||
| +	inode = iget_locked(sb, ino); | ||||
| +	if (!inode) | ||||
| +		return ERR_PTR(-ENOMEM); | ||||
| + | ||||
| +	if (!(inode->i_state & I_NEW)) | ||||
| +		return inode; | ||||
| + | ||||
| +	mini_fo_read_inode(inode); | ||||
| + | ||||
| +	unlock_new_inode(inode); | ||||
| +	return inode; | ||||
| +} | ||||
| +#endif /* if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) */ | ||||
|   | ||||
|  struct super_operations mini_fo_sops = | ||||
|  { | ||||
| +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) | ||||
|  	read_inode:		mini_fo_read_inode, | ||||
| +#endif | ||||
|  #if defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) | ||||
|  	write_inode:	mini_fo_write_inode, | ||||
|  #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,  | ||||
|  	err = vfs_path_lookup(mnt->mnt_root, mnt, bpath+1, 0, &nd); | ||||
|   | ||||
|  	/* validate */ | ||||
| -	if (err || !nd.dentry || !nd.dentry->d_inode) { | ||||
| +	if (err || !nd_get_dentry(&nd) || !nd_get_dentry(&nd)->d_inode) { | ||||
|  		printk(KERN_CRIT "mini_fo: bpath_walk: path_walk failed.\n"); | ||||
|  		return NULL; | ||||
|  	} | ||||
| -	return nd.dentry; | ||||
| +	return nd_get_dentry(&nd); | ||||
|  } | ||||
|   | ||||
|   | ||||
| @@ -1,66 +0,0 @@ | ||||
| --- a/fs/mini_fo/meta.c | ||||
| +++ b/fs/mini_fo/meta.c | ||||
| @@ -442,6 +442,11 @@ int meta_write_d_entry(dentry_t *dentry, | ||||
|  			   S_IRUSR | S_IWUSR); | ||||
|  #endif | ||||
|  	} | ||||
| + | ||||
| +	/* $%& err, is this correct? */ | ||||
| +	meta_mnt = stopd(dentry->d_inode->i_sb)->hidden_mnt2; | ||||
| +	mntget(meta_mnt); | ||||
| + | ||||
|          /* open META-file for writing */ | ||||
|          meta_file = dentry_open(meta_dentry, meta_mnt, 0x1); | ||||
|          if(!meta_file || IS_ERR(meta_file)) { | ||||
| @@ -535,6 +540,11 @@ int meta_write_r_entry(dentry_t *dentry, | ||||
|  			   meta_dentry, S_IRUSR | S_IWUSR); | ||||
|  #endif | ||||
|  	} | ||||
| + | ||||
| +	/* $%& err, is this correct? */ | ||||
| +	meta_mnt = stopd(dentry->d_inode->i_sb)->hidden_mnt2; | ||||
| +	mntget(meta_mnt); | ||||
| + | ||||
|          /* open META-file for writing */ | ||||
|          meta_file = dentry_open(meta_dentry, meta_mnt, 0x1); | ||||
|          if(!meta_file || IS_ERR(meta_file)) { | ||||
| @@ -671,14 +681,16 @@ int meta_sync_d_list(dentry_t *dentry, i | ||||
|  		} | ||||
|  	} | ||||
|   | ||||
| +	/* $%& err, is this correct? */ | ||||
| +	meta_mnt = stopd(dentry->d_inode->i_sb)->hidden_mnt2; | ||||
| +	mntget(meta_mnt); | ||||
| + | ||||
|          /* open META-file for writing */ | ||||
|          meta_file = dentry_open(meta_dentry, meta_mnt, 0x1); | ||||
|          if(!meta_file || IS_ERR(meta_file)) { | ||||
|                  printk(KERN_CRIT "mini_fo: meta_sync_d_list: \ | ||||
|                                    ERROR opening meta file.\n"); | ||||
| -		/* we don't mntget so we dont't mntput (for now) | ||||
| -		 * mntput(meta_mnt); | ||||
| -		 */ | ||||
| +		mntput(meta_mnt); | ||||
|  		dput(meta_dentry); | ||||
|  		err = -1; | ||||
|                  goto out; | ||||
| @@ -811,14 +823,16 @@ int meta_sync_r_list(dentry_t *dentry, i | ||||
|  		} | ||||
|  	} | ||||
|   | ||||
| +	/* $%& err, is this correct? */ | ||||
| +	meta_mnt = stopd(dentry->d_inode->i_sb)->hidden_mnt2; | ||||
| +	mntget(meta_mnt); | ||||
| + | ||||
|          /* open META-file for writing */ | ||||
|          meta_file = dentry_open(meta_dentry, meta_mnt, 0x1); | ||||
|          if(!meta_file || IS_ERR(meta_file)) { | ||||
|                  printk(KERN_CRIT "mini_fo: meta_sync_r_list: \ | ||||
|                                    ERROR opening meta file.\n"); | ||||
| -		/* we don't mntget so we dont't mntput (for now) | ||||
| -		 * mntput(meta_mnt); | ||||
| -		 */ | ||||
| +		mntput(meta_mnt); | ||||
|  		dput(meta_dentry); | ||||
|  		err = -1; | ||||
|                  goto out; | ||||
| @@ -1,37 +0,0 @@ | ||||
| --- a/fs/mini_fo/super.c | ||||
| +++ b/fs/mini_fo/super.c | ||||
| @@ -84,6 +84,7 @@ mini_fo_write_inode(inode_t *inode, int  | ||||
|  #endif /* defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) */ | ||||
|   | ||||
|   | ||||
| +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) | ||||
|  STATIC void | ||||
|  mini_fo_put_inode(inode_t *inode) | ||||
|  { | ||||
| @@ -99,6 +100,7 @@ mini_fo_put_inode(inode_t *inode) | ||||
|  	if (atomic_read(&inode->i_count) == 1) | ||||
|  		inode->i_nlink = 0; | ||||
|  } | ||||
| +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) */ | ||||
|   | ||||
|   | ||||
|  #if defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) | ||||
| @@ -238,7 +240,7 @@ mini_fo_clear_inode(inode_t *inode) | ||||
|   * dies. | ||||
|   */ | ||||
|  STATIC void | ||||
| -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) | ||||
| +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)) | ||||
|  mini_fo_umount_begin(struct vfsmount *mnt, int flags) | ||||
|  { | ||||
|  	struct vfsmount *hidden_mnt; | ||||
| @@ -290,7 +292,9 @@ struct super_operations mini_fo_sops = | ||||
|  #if defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) | ||||
|  	write_inode:	mini_fo_write_inode, | ||||
|  #endif /* defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) */ | ||||
| +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) | ||||
|  	put_inode:		mini_fo_put_inode, | ||||
| +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) */ | ||||
|  #if defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) | ||||
|  	delete_inode:	mini_fo_delete_inode, | ||||
|  #endif /* defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) */ | ||||
| @@ -1,41 +0,0 @@ | ||||
| --- a/fs/mini_fo/inode.c | ||||
| +++ b/fs/mini_fo/inode.c | ||||
| @@ -439,7 +439,7 @@ mini_fo_symlink(inode_t *dir, dentry_t * | ||||
|  	int err=0; | ||||
|  	dentry_t *hidden_sto_dentry; | ||||
|  	dentry_t *hidden_sto_dir_dentry; | ||||
| -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) | ||||
| +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)) | ||||
|          umode_t mode; | ||||
|  #endif | ||||
|   | ||||
| @@ -466,7 +466,7 @@ mini_fo_symlink(inode_t *dir, dentry_t * | ||||
|  	down(&hidden_sto_dir_dentry->d_inode->i_sem); | ||||
|  #endif | ||||
|   | ||||
| -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) | ||||
| +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)) | ||||
|  	mode = S_IALLUGO; | ||||
|  	err = vfs_symlink(hidden_sto_dir_dentry->d_inode, | ||||
|  			  hidden_sto_dentry, symname, mode); | ||||
| @@ -1128,7 +1128,7 @@ void mini_fo_put_link(struct dentry *den | ||||
|  #endif | ||||
|   | ||||
|  STATIC int | ||||
| -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) | ||||
| +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)) | ||||
|  mini_fo_permission(inode_t *inode, int mask, struct nameidata *nd) | ||||
|  #else | ||||
|  mini_fo_permission(inode_t *inode, int mask) | ||||
| @@ -1150,8 +1150,9 @@ mini_fo_permission(inode_t *inode, int m | ||||
|  	 *	if (err) | ||||
|  	 *		goto out; | ||||
|  	 */ | ||||
| - | ||||
| -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) | ||||
| +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) | ||||
| +	err = inode_permission(hidden_inode, mask); | ||||
| +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) | ||||
|  	err = permission(hidden_inode, mask, nd); | ||||
|  #else | ||||
|  	err = permission(hidden_inode, mask); | ||||
| @@ -1,96 +0,0 @@ | ||||
| --- a/fs/mini_fo/aux.c | ||||
| +++ b/fs/mini_fo/aux.c | ||||
| @@ -236,7 +236,7 @@ int mini_fo_cp_cont(dentry_t *tgt_dentry | ||||
|  	mntget(src_mnt); | ||||
|   | ||||
|  	/* open file write only */ | ||||
| -	tgt_file = dentry_open(tgt_dentry, tgt_mnt, 0x1); | ||||
| +	tgt_file = dentry_open(tgt_dentry, tgt_mnt, 0x1, current_cred()); | ||||
|  	if(!tgt_file || IS_ERR(tgt_file)) { | ||||
|  		printk(KERN_CRIT "mini_fo_cp_cont: ERROR opening target file.\n"); | ||||
|  		err = PTR_ERR(tgt_file); | ||||
| @@ -244,7 +244,7 @@ int mini_fo_cp_cont(dentry_t *tgt_dentry | ||||
|  	} | ||||
|   | ||||
|  	/* open file read only */ | ||||
| -	src_file = dentry_open(src_dentry, src_mnt, 0x0); | ||||
| +	src_file = dentry_open(src_dentry, src_mnt, 0x0, current_cred()); | ||||
|  	if(!src_file || IS_ERR(src_file)) { | ||||
|  		printk(KERN_CRIT "mini_fo_cp_cont: ERROR opening source file.\n"); | ||||
|  		err = PTR_ERR(src_file); | ||||
| --- a/fs/mini_fo/file.c | ||||
| +++ b/fs/mini_fo/file.c | ||||
| @@ -437,7 +437,7 @@ mini_fo_open(inode_t *inode, file_t *fil | ||||
|  			mntget(stopd(inode->i_sb)->hidden_mnt); | ||||
|  			hidden_file = dentry_open(hidden_dentry, | ||||
|  						  stopd(inode->i_sb)->hidden_mnt, | ||||
| -						  hidden_flags); | ||||
| +						  hidden_flags, file->f_cred); | ||||
|  			if (IS_ERR(hidden_file)) { | ||||
|  				err = PTR_ERR(hidden_file); | ||||
|  				dput(hidden_dentry); | ||||
| @@ -479,7 +479,7 @@ mini_fo_open(inode_t *inode, file_t *fil | ||||
|  			mntget(stopd(inode->i_sb)->hidden_mnt); | ||||
|  			hidden_file = dentry_open(hidden_dentry, | ||||
|  						  stopd(inode->i_sb)->hidden_mnt, | ||||
| -						  hidden_flags); | ||||
| +						  hidden_flags, file->f_cred); | ||||
|  			if (IS_ERR(hidden_file)) { | ||||
|  				err = PTR_ERR(hidden_file); | ||||
|  				dput(hidden_dentry); | ||||
| @@ -512,7 +512,7 @@ mini_fo_open(inode_t *inode, file_t *fil | ||||
|  	mntget(stopd(inode->i_sb)->hidden_mnt2); | ||||
|  	hidden_sto_file = dentry_open(hidden_sto_dentry, | ||||
|  				      stopd(inode->i_sb)->hidden_mnt2, | ||||
| -				      hidden_flags); | ||||
| +				      hidden_flags, file->f_cred); | ||||
|   | ||||
|  	/* dentry_open dputs the dentry if it fails */ | ||||
|  	if (IS_ERR(hidden_sto_file)) { | ||||
| --- a/fs/mini_fo/meta.c | ||||
| +++ b/fs/mini_fo/meta.c | ||||
| @@ -56,7 +56,7 @@ int meta_build_lists(dentry_t *dentry) | ||||
|   | ||||
|   | ||||
|  		/* open META-file for reading */ | ||||
| -		meta_file = dentry_open(meta_dentry, meta_mnt, 0x0); | ||||
| +		meta_file = dentry_open(meta_dentry, meta_mnt, 0x0, current_cred()); | ||||
|  		if(!meta_file || IS_ERR(meta_file)) { | ||||
|  			printk(KERN_CRIT "mini_fo: meta_build_lists: \ | ||||
|                                            ERROR opening META file.\n"); | ||||
| @@ -448,7 +448,7 @@ int meta_write_d_entry(dentry_t *dentry, | ||||
|  	mntget(meta_mnt); | ||||
|   | ||||
|          /* open META-file for writing */ | ||||
| -        meta_file = dentry_open(meta_dentry, meta_mnt, 0x1); | ||||
| +        meta_file = dentry_open(meta_dentry, meta_mnt, 0x1, current_cred()); | ||||
|          if(!meta_file || IS_ERR(meta_file)) { | ||||
|                  printk(KERN_CRIT "mini_fo: meta_write_d_entry: \ | ||||
|                                    ERROR opening meta file.\n"); | ||||
| @@ -546,7 +546,7 @@ int meta_write_r_entry(dentry_t *dentry, | ||||
|  	mntget(meta_mnt); | ||||
|   | ||||
|          /* open META-file for writing */ | ||||
| -        meta_file = dentry_open(meta_dentry, meta_mnt, 0x1); | ||||
| +        meta_file = dentry_open(meta_dentry, meta_mnt, 0x1, current_cred()); | ||||
|          if(!meta_file || IS_ERR(meta_file)) { | ||||
|                  printk(KERN_CRIT "mini_fo: meta_write_r_entry: \ | ||||
|                                    ERROR opening meta file.\n"); | ||||
| @@ -686,7 +686,7 @@ int meta_sync_d_list(dentry_t *dentry, i | ||||
|  	mntget(meta_mnt); | ||||
|   | ||||
|          /* open META-file for writing */ | ||||
| -        meta_file = dentry_open(meta_dentry, meta_mnt, 0x1); | ||||
| +        meta_file = dentry_open(meta_dentry, meta_mnt, 0x1, current_cred()); | ||||
|          if(!meta_file || IS_ERR(meta_file)) { | ||||
|                  printk(KERN_CRIT "mini_fo: meta_sync_d_list: \ | ||||
|                                    ERROR opening meta file.\n"); | ||||
| @@ -828,7 +828,7 @@ int meta_sync_r_list(dentry_t *dentry, i | ||||
|  	mntget(meta_mnt); | ||||
|   | ||||
|          /* open META-file for writing */ | ||||
| -        meta_file = dentry_open(meta_dentry, meta_mnt, 0x1); | ||||
| +        meta_file = dentry_open(meta_dentry, meta_mnt, 0x1, current_cred()); | ||||
|          if(!meta_file || IS_ERR(meta_file)) { | ||||
|                  printk(KERN_CRIT "mini_fo: meta_sync_r_list: \ | ||||
|                                    ERROR opening meta file.\n"); | ||||
| @@ -1,42 +0,0 @@ | ||||
| --- a/lib/kobject_uevent.c | ||||
| +++ b/lib/kobject_uevent.c | ||||
| @@ -29,7 +29,8 @@ u64 uevent_seqnum; | ||||
|  char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH; | ||||
|  static DEFINE_SPINLOCK(sequence_lock); | ||||
|  #if defined(CONFIG_NET) | ||||
| -static struct sock *uevent_sock; | ||||
| +struct sock *uevent_sock = NULL; | ||||
| +EXPORT_SYMBOL_GPL(uevent_sock); | ||||
|  #endif | ||||
|   | ||||
|  /* the strings here must match the enum in include/linux/kobject.h */ | ||||
| @@ -42,6 +43,18 @@ static const char *kobject_actions[] = { | ||||
|  	[KOBJ_OFFLINE] =	"offline", | ||||
|  }; | ||||
|   | ||||
| +u64 uevent_next_seqnum(void) | ||||
| +{ | ||||
| +	u64 seq; | ||||
| + | ||||
| +	spin_lock(&sequence_lock); | ||||
| +	seq = ++uevent_seqnum; | ||||
| +	spin_unlock(&sequence_lock); | ||||
| + | ||||
| +	return seq; | ||||
| +} | ||||
| +EXPORT_SYMBOL_GPL(uevent_next_seqnum); | ||||
| + | ||||
|  /** | ||||
|   * kobject_action_type - translate action string to numeric type | ||||
|   * | ||||
| @@ -194,9 +207,7 @@ int kobject_uevent_env(struct kobject *k | ||||
|  		kobj->state_remove_uevent_sent = 1; | ||||
|   | ||||
|  	/* we will send an event, so request a new sequence number */ | ||||
| -	spin_lock(&sequence_lock); | ||||
| -	seq = ++uevent_seqnum; | ||||
| -	spin_unlock(&sequence_lock); | ||||
| +	seq = uevent_next_seqnum(); | ||||
|  	retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)seq); | ||||
|  	if (retval) | ||||
|  		goto exit; | ||||
| @@ -1,11 +0,0 @@ | ||||
| --- a/sound/core/Kconfig | ||||
| +++ b/sound/core/Kconfig | ||||
| @@ -7,7 +7,7 @@ config SND_PCM | ||||
|  	select SND_TIMER | ||||
|   | ||||
|  config SND_HWDEP | ||||
| -	tristate | ||||
| +	tristate "Sound hardware support" | ||||
|   | ||||
|  config SND_RAWMIDI | ||||
|  	tristate | ||||
| @@ -1,11 +0,0 @@ | ||||
| --- a/fs/binfmt_elf.c | ||||
| +++ b/fs/binfmt_elf.c | ||||
| @@ -1211,7 +1211,7 @@ static unsigned long vma_dump_size(struc | ||||
|  	if (FILTER(ELF_HEADERS) && | ||||
|  	    vma->vm_pgoff == 0 && (vma->vm_flags & VM_READ)) { | ||||
|  		u32 __user *header = (u32 __user *) vma->vm_start; | ||||
| -		u32 word; | ||||
| +		u32 word = 0; | ||||
|  		mm_segment_t fs = get_fs(); | ||||
|  		/* | ||||
|  		 * Doing it this way gets the constant folded by GCC. | ||||
| @@ -1,132 +0,0 @@ | ||||
| This patch allows the user to specify desired packet types (outgoing, | ||||
| broadcast, unicast, etc.) on packet sockets via setsockopt. | ||||
| This can reduce the load in situations where only a limited number | ||||
| of packet types are necessary | ||||
|  | ||||
| Signed-off-by: Felix Fietkau <nbd@openwrt.org> | ||||
|  | ||||
| --- a/include/linux/if_packet.h | ||||
| +++ b/include/linux/if_packet.h | ||||
| @@ -31,6 +31,8 @@ struct sockaddr_ll | ||||
|  /* These ones are invisible by user level */ | ||||
|  #define PACKET_LOOPBACK		5		/* MC/BRD frame looped back */ | ||||
|  #define PACKET_FASTROUTE	6		/* Fastrouted frame	*/ | ||||
| +#define PACKET_MASK_ANY		0xffffffff	/* mask for packet type bits */ | ||||
| + | ||||
|   | ||||
|  /* Packet socket options */ | ||||
|   | ||||
| @@ -46,6 +48,7 @@ struct sockaddr_ll | ||||
|  #define PACKET_VERSION			10 | ||||
|  #define PACKET_HDRLEN			11 | ||||
|  #define PACKET_RESERVE			12 | ||||
| +#define PACKET_RECV_TYPE		13 | ||||
|   | ||||
|  struct tpacket_stats | ||||
|  { | ||||
| --- a/net/packet/af_packet.c | ||||
| +++ b/net/packet/af_packet.c | ||||
| @@ -192,6 +192,7 @@ struct packet_sock { | ||||
|  	unsigned int		tp_hdrlen; | ||||
|  	unsigned int		tp_reserve; | ||||
|  #endif | ||||
| +	unsigned int		pkt_type; | ||||
|  }; | ||||
|   | ||||
|  struct packet_skb_cb { | ||||
| @@ -282,6 +283,7 @@ static int packet_rcv_spkt(struct sk_buf | ||||
|  { | ||||
|  	struct sock *sk; | ||||
|  	struct sockaddr_pkt *spkt; | ||||
| +	struct packet_sock *po; | ||||
|   | ||||
|  	/* | ||||
|  	 *	When we registered the protocol we saved the socket in the data | ||||
| @@ -289,6 +291,7 @@ static int packet_rcv_spkt(struct sk_buf | ||||
|  	 */ | ||||
|   | ||||
|  	sk = pt->af_packet_priv; | ||||
| +	po = pkt_sk(sk); | ||||
|   | ||||
|  	/* | ||||
|  	 *	Yank back the headers [hope the device set this | ||||
| @@ -301,7 +304,7 @@ static int packet_rcv_spkt(struct sk_buf | ||||
|  	 *	so that this procedure is noop. | ||||
|  	 */ | ||||
|   | ||||
| -	if (skb->pkt_type == PACKET_LOOPBACK) | ||||
| +	if (!(po->pkt_type & (1 << skb->pkt_type))) | ||||
|  		goto out; | ||||
|   | ||||
|  	if (dev_net(dev) != sock_net(sk)) | ||||
| @@ -486,12 +489,12 @@ static int packet_rcv(struct sk_buff *sk | ||||
|  	int skb_len = skb->len; | ||||
|  	unsigned int snaplen, res; | ||||
|   | ||||
| -	if (skb->pkt_type == PACKET_LOOPBACK) | ||||
| -		goto drop; | ||||
| - | ||||
|  	sk = pt->af_packet_priv; | ||||
|  	po = pkt_sk(sk); | ||||
|   | ||||
| +	if (!(po->pkt_type & (1 << skb->pkt_type))) | ||||
| +		goto drop; | ||||
| + | ||||
|  	if (dev_net(dev) != sock_net(sk)) | ||||
|  		goto drop; | ||||
|   | ||||
| @@ -608,12 +611,12 @@ static int tpacket_rcv(struct sk_buff *s | ||||
|  	struct timeval tv; | ||||
|  	struct timespec ts; | ||||
|   | ||||
| -	if (skb->pkt_type == PACKET_LOOPBACK) | ||||
| -		goto drop; | ||||
| - | ||||
|  	sk = pt->af_packet_priv; | ||||
|  	po = pkt_sk(sk); | ||||
|   | ||||
| +	if (!(po->pkt_type & (1 << skb->pkt_type))) | ||||
| +		goto drop; | ||||
| + | ||||
|  	if (dev_net(dev) != sock_net(sk)) | ||||
|  		goto drop; | ||||
|   | ||||
| @@ -1073,6 +1076,7 @@ static int packet_create(struct net *net | ||||
|  	spin_lock_init(&po->bind_lock); | ||||
|  	mutex_init(&po->pg_vec_lock); | ||||
|  	po->prot_hook.func = packet_rcv; | ||||
| +	po->pkt_type = PACKET_MASK_ANY & ~(1 << PACKET_LOOPBACK); | ||||
|   | ||||
|  	if (sock->type == SOCK_PACKET) | ||||
|  		po->prot_hook.func = packet_rcv_spkt; | ||||
| @@ -1413,6 +1417,16 @@ packet_setsockopt(struct socket *sock, i | ||||
|  			ret = packet_mc_drop(sk, &mreq); | ||||
|  		return ret; | ||||
|  	} | ||||
| +	case PACKET_RECV_TYPE: | ||||
| +	{ | ||||
| +		unsigned int val; | ||||
| +		if (optlen != sizeof(val)) | ||||
| +			return -EINVAL; | ||||
| +		if (copy_from_user(&val, optval, sizeof(val))) | ||||
| +			return -EFAULT; | ||||
| +		po->pkt_type = val & ~PACKET_LOOPBACK; | ||||
| +		return 0; | ||||
| +	} | ||||
|   | ||||
|  #ifdef CONFIG_PACKET_MMAP | ||||
|  	case PACKET_RX_RING: | ||||
| @@ -1544,6 +1558,13 @@ static int packet_getsockopt(struct sock | ||||
|   | ||||
|  		data = &val; | ||||
|  		break; | ||||
| +	case PACKET_RECV_TYPE: | ||||
| +		if (len > sizeof(unsigned int)) | ||||
| +			len = sizeof(unsigned int); | ||||
| +		val = po->pkt_type; | ||||
| + | ||||
| +		data = &val; | ||||
| +		break; | ||||
|  #ifdef CONFIG_PACKET_MMAP | ||||
|  	case PACKET_VERSION: | ||||
|  		if (len > sizeof(int)) | ||||
| @@ -1,20 +0,0 @@ | ||||
| --- a/drivers/net/pppoe.c | ||||
| +++ b/drivers/net/pppoe.c | ||||
| @@ -812,7 +812,7 @@ static int pppoe_sendmsg(struct kiocb *i | ||||
|  		goto end; | ||||
|   | ||||
|   | ||||
| -	skb = sock_wmalloc(sk, total_len + dev->hard_header_len + 32, | ||||
| +	skb = sock_wmalloc(sk, total_len + dev->hard_header_len + 32 + NET_SKB_PAD, | ||||
|  			   0, GFP_KERNEL); | ||||
|  	if (!skb) { | ||||
|  		error = -ENOMEM; | ||||
| @@ -820,7 +820,7 @@ static int pppoe_sendmsg(struct kiocb *i | ||||
|  	} | ||||
|   | ||||
|  	/* Reserve space for headers. */ | ||||
| -	skb_reserve(skb, dev->hard_header_len); | ||||
| +	skb_reserve(skb, dev->hard_header_len + NET_SKB_PAD); | ||||
|  	skb_reset_network_header(skb); | ||||
|   | ||||
|  	skb->dev = dev; | ||||
| @@ -1,18 +0,0 @@ | ||||
| --- a/drivers/leds/Kconfig | ||||
| +++ b/drivers/leds/Kconfig | ||||
| @@ -223,4 +223,8 @@ config LEDS_TRIGGER_DEFAULT_ON | ||||
|  	  This allows LEDs to be initialised in the ON state. | ||||
|  	  If unsure, say Y. | ||||
|   | ||||
| +config LEDS_TRIGGER_MORSE | ||||
| +	tristate "LED Morse Trigger" | ||||
| +	depends on LEDS_TRIGGERS | ||||
| + | ||||
|  endif # NEW_LEDS | ||||
| --- a/drivers/leds/Makefile | ||||
| +++ b/drivers/leds/Makefile | ||||
| @@ -31,3 +31,4 @@ obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK)	+= l | ||||
|  obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT)	+= ledtrig-heartbeat.o | ||||
|  obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT)	+= ledtrig-backlight.o | ||||
|  obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON)	+= ledtrig-default-on.o | ||||
| +obj-$(CONFIG_LEDS_TRIGGER_MORSE)	+= ledtrig-morse.o | ||||
| @@ -1,21 +0,0 @@ | ||||
| --- a/drivers/leds/Kconfig | ||||
| +++ b/drivers/leds/Kconfig | ||||
| @@ -227,4 +227,11 @@ config LEDS_TRIGGER_MORSE | ||||
|  	tristate "LED Morse Trigger" | ||||
|  	depends on LEDS_TRIGGERS | ||||
|   | ||||
| +config LEDS_TRIGGER_NETDEV | ||||
| +	tristate "LED Netdev Trigger" | ||||
| +	depends on LEDS_TRIGGERS | ||||
| +	help | ||||
| +	  This allows LEDs to be controlled by network device activity. | ||||
| +	  If unsure, say Y. | ||||
| + | ||||
|  endif # NEW_LEDS | ||||
| --- a/drivers/leds/Makefile | ||||
| +++ b/drivers/leds/Makefile | ||||
| @@ -32,3 +32,4 @@ obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT)	+=  | ||||
|  obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT)	+= ledtrig-backlight.o | ||||
|  obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON)	+= ledtrig-default-on.o | ||||
|  obj-$(CONFIG_LEDS_TRIGGER_MORSE)	+= ledtrig-morse.o | ||||
| +obj-$(CONFIG_LEDS_TRIGGER_NETDEV)      += ledtrig-netdev.o | ||||
| @@ -1,30 +0,0 @@ | ||||
| --- a/drivers/input/misc/Kconfig | ||||
| +++ b/drivers/input/misc/Kconfig | ||||
| @@ -227,4 +227,20 @@ config INPUT_PCF50633_PMU | ||||
|  	 Say Y to include support for delivering  PMU events via  input | ||||
|  	 layer on NXP PCF50633. | ||||
|   | ||||
| +config INPUT_GPIO_BUTTONS | ||||
| +	tristate "Polled GPIO buttons interface" | ||||
| +	depends on GENERIC_GPIO | ||||
| +	select INPUT_POLLDEV | ||||
| +	help | ||||
| +	  This driver implements support for buttons connected | ||||
| +	  to GPIO pins of various CPUs (and some other chips). | ||||
| + | ||||
| +	  Say Y here if your device has buttons connected | ||||
| +	  directly to such GPIO pins.  Your board-specific | ||||
| +	  setup logic must also provide a platform device, | ||||
| +	  with configuration data saying which GPIOs are used. | ||||
| + | ||||
| +	  To compile this driver as a module, choose M here: the | ||||
| +	  module will be called gpio-buttons. | ||||
| + | ||||
|  endif | ||||
| --- a/drivers/input/misc/Makefile | ||||
| +++ b/drivers/input/misc/Makefile | ||||
| @@ -22,3 +22,4 @@ obj-$(CONFIG_INPUT_UINPUT)		+= uinput.o | ||||
|  obj-$(CONFIG_INPUT_APANEL)		+= apanel.o | ||||
|  obj-$(CONFIG_INPUT_SGI_BTNS)		+= sgi_btns.o | ||||
|  obj-$(CONFIG_INPUT_PCF50633_PMU)	+= pcf50633-input.o | ||||
| +obj-$(CONFIG_INPUT_GPIO_BUTTONS)	+= gpio_buttons.o | ||||
| @@ -1,26 +0,0 @@ | ||||
| --- a/drivers/char/Kconfig | ||||
| +++ b/drivers/char/Kconfig | ||||
| @@ -1016,6 +1016,13 @@ config CS5535_GPIO | ||||
|   | ||||
|  	  If compiled as a module, it will be called cs5535_gpio. | ||||
|   | ||||
| +config GPIO_DEVICE | ||||
| +	tristate "GPIO device support" | ||||
| +	depends on GENERIC_GPIO | ||||
| +	help | ||||
| +	  Say Y to enable Linux GPIO device support.  This allows control of | ||||
| +	  GPIO pins using a character device | ||||
| + | ||||
|  config GPIO_VR41XX | ||||
|  	tristate "NEC VR4100 series General-purpose I/O Unit support" | ||||
|  	depends on CPU_VR41XX | ||||
| --- a/drivers/char/Makefile | ||||
| +++ b/drivers/char/Makefile | ||||
| @@ -94,6 +94,7 @@ obj-$(CONFIG_SCx200_GPIO)	+= scx200_gpio | ||||
|  obj-$(CONFIG_PC8736x_GPIO)	+= pc8736x_gpio.o | ||||
|  obj-$(CONFIG_NSC_GPIO)		+= nsc_gpio.o | ||||
|  obj-$(CONFIG_CS5535_GPIO)	+= cs5535_gpio.o | ||||
| +obj-$(CONFIG_GPIO_DEVICE)	+= gpio_dev.o | ||||
|  obj-$(CONFIG_GPIO_VR41XX)	+= vr41xx_giu.o | ||||
|  obj-$(CONFIG_GPIO_TB0219)	+= tb0219.o | ||||
|  obj-$(CONFIG_TELCLOCK)		+= tlclk.o | ||||
| @@ -1,134 +0,0 @@ | ||||
| Subject: [PATCH 2/3] I2C: at24: add kernel interface for reading/writing EEPROM | ||||
| Date: Monday 25 August 2008 | ||||
| From: Kevin Hilman <khilman@deeprootsystems.com> | ||||
| To: davinci-linux-open-source@linux.davincidsp.com | ||||
|  | ||||
| This patch adds an interface by which other kernel code can read/write | ||||
| detected EEPROM. | ||||
|  | ||||
| The platform code registers a 'setup' callback with the | ||||
| at24_platform_data.  When the at24 driver detects an EEPROM, it fills | ||||
| out the read and write functions of at24_iface and calls the setup | ||||
| callback.  The platform code can then use the read/write functions in | ||||
| the at24_iface struct for reading and writing the EEPROM. | ||||
|  | ||||
| Original idea, review and updates by David Brownell <david-b@pacbell.net> | ||||
|  | ||||
| Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com> | ||||
| --- | ||||
|  drivers/i2c/chips/at24.c |   42 +++++++++++++++++++++++++++++++++++------- | ||||
|  include/linux/i2c/at24.h |   10 ++++++++++ | ||||
|  2 files changed, 45 insertions(+), 7 deletions(-) | ||||
|  | ||||
| --- a/drivers/misc/eeprom/at24.c | ||||
| +++ b/drivers/misc/eeprom/at24.c | ||||
| @@ -53,6 +53,7 @@ | ||||
|   | ||||
|  struct at24_data { | ||||
|  	struct at24_platform_data chip; | ||||
| +	struct at24_iface iface; | ||||
|  	bool use_smbus; | ||||
|   | ||||
|  	/* | ||||
| @@ -264,13 +265,6 @@ static ssize_t at24_bin_read(struct kobj | ||||
|   | ||||
|   | ||||
|  /* | ||||
| - * REVISIT: export at24_bin{read,write}() to let other kernel code use | ||||
| - * eeprom data. For example, it might hold a board's Ethernet address, or | ||||
| - * board-specific calibration data generated on the manufacturing floor. | ||||
| - */ | ||||
| - | ||||
| - | ||||
| -/* | ||||
|   * Note that if the hardware write-protect pin is pulled high, the whole | ||||
|   * chip is normally write protected. But there are plenty of product | ||||
|   * variants here, including OTP fuses and partial chip protect. | ||||
| @@ -386,6 +380,30 @@ static ssize_t at24_bin_write(struct kob | ||||
|   | ||||
|  /*-------------------------------------------------------------------------*/ | ||||
|   | ||||
| +/* | ||||
| + * This lets other kernel code access the eeprom data. For example, it | ||||
| + * might hold a board's Ethernet address, or board-specific calibration | ||||
| + * data generated on the manufacturing floor. | ||||
| + */ | ||||
| + | ||||
| +static ssize_t at24_iface_read(struct at24_iface *iface, char *buf, | ||||
| +			      off_t offset, size_t count) | ||||
| +{ | ||||
| +	struct at24_data *at24 = container_of(iface, struct at24_data, iface); | ||||
| + | ||||
| +	return at24_eeprom_read(at24, buf, offset, count); | ||||
| +} | ||||
| + | ||||
| +static ssize_t at24_iface_write(struct at24_iface *iface, char *buf, | ||||
| +			       off_t offset, size_t count) | ||||
| +{ | ||||
| +	struct at24_data *at24 = container_of(iface, struct at24_data, iface); | ||||
| + | ||||
| +	return at24_eeprom_write(at24, buf, offset, count); | ||||
| +} | ||||
| + | ||||
| +/*-------------------------------------------------------------------------*/ | ||||
| + | ||||
|  static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) | ||||
|  { | ||||
|  	struct at24_platform_data chip; | ||||
| @@ -413,6 +431,9 @@ static int at24_probe(struct i2c_client  | ||||
|  		 * is recommended anyhow. | ||||
|  		 */ | ||||
|  		chip.page_size = 1; | ||||
| + | ||||
| +		chip.setup = NULL; | ||||
| +		chip.context = NULL; | ||||
|  	} | ||||
|   | ||||
|  	if (!is_power_of_2(chip.byte_len)) | ||||
| @@ -449,6 +470,9 @@ static int at24_probe(struct i2c_client  | ||||
|  		goto err_out; | ||||
|  	} | ||||
|   | ||||
| +	at24->iface.read = at24_iface_read; | ||||
| +	at24->iface.write = at24_iface_write; | ||||
| + | ||||
|  	mutex_init(&at24->lock); | ||||
|  	at24->use_smbus = use_smbus; | ||||
|  	at24->chip = chip; | ||||
| @@ -520,6 +544,10 @@ static int at24_probe(struct i2c_client  | ||||
|  		at24->write_max, | ||||
|  		use_smbus ? ", use_smbus" : ""); | ||||
|   | ||||
| +	/* export data to kernel code */ | ||||
| +	if (chip.setup) | ||||
| +		chip.setup(&at24->iface, chip.context); | ||||
| + | ||||
|  	return 0; | ||||
|   | ||||
|  err_clients: | ||||
| --- a/include/linux/i2c/at24.h | ||||
| +++ b/include/linux/i2c/at24.h | ||||
| @@ -15,6 +15,13 @@ | ||||
|   * is bigger than what the chip actually supports! | ||||
|   */ | ||||
|   | ||||
| +struct at24_iface { | ||||
| +	ssize_t (*read)(struct at24_iface *, char *buf, off_t offset, | ||||
| +			size_t count); | ||||
| +	ssize_t (*write)(struct at24_iface *, char *buf, off_t offset, | ||||
| +			 size_t count); | ||||
| +}; | ||||
| + | ||||
|  struct at24_platform_data { | ||||
|  	u32		byte_len;		/* size (sum of all addr) */ | ||||
|  	u16		page_size;		/* for writes */ | ||||
| @@ -23,6 +30,9 @@ struct at24_platform_data { | ||||
|  #define AT24_FLAG_READONLY	0x40	/* sysfs-entry will be read-only */ | ||||
|  #define AT24_FLAG_IRUGO		0x20	/* sysfs-entry will be world-readable */ | ||||
|  #define AT24_FLAG_TAKE8ADDR	0x10	/* take always 8 addresses (24c00) */ | ||||
| + | ||||
| +	int             (*setup)(struct at24_iface *, void *context); | ||||
| +	void		*context; | ||||
|  }; | ||||
|   | ||||
|  #endif /* _LINUX_AT24_H */ | ||||
| @@ -1,17 +0,0 @@ | ||||
| --- a/fs/Kconfig | ||||
| +++ b/fs/Kconfig | ||||
| @@ -223,6 +223,7 @@ source "fs/qnx4/Kconfig" | ||||
|  source "fs/romfs/Kconfig" | ||||
|  source "fs/sysv/Kconfig" | ||||
|  source "fs/ufs/Kconfig" | ||||
| +source "fs/yaffs2/Kconfig" | ||||
|   | ||||
|  endif # MISC_FILESYSTEMS | ||||
|   | ||||
| --- a/fs/Makefile | ||||
| +++ b/fs/Makefile | ||||
| @@ -125,3 +125,4 @@ obj-$(CONFIG_DEBUG_FS)		+= debugfs/ | ||||
|  obj-$(CONFIG_OCFS2_FS)		+= ocfs2/ | ||||
|  obj-$(CONFIG_BTRFS_FS)		+= btrfs/ | ||||
|  obj-$(CONFIG_GFS2_FS)           += gfs2/ | ||||
| +obj-$(CONFIG_YAFFS_FS)		+= yaffs2/ | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,83 +0,0 @@ | ||||
| --- a/drivers/net/phy/phy.c | ||||
| +++ b/drivers/net/phy/phy.c | ||||
| @@ -299,6 +299,50 @@ int phy_ethtool_gset(struct phy_device * | ||||
|  } | ||||
|  EXPORT_SYMBOL(phy_ethtool_gset); | ||||
|   | ||||
| +int phy_ethtool_ioctl(struct phy_device *phydev, void *useraddr) | ||||
| +{ | ||||
| +	u32 cmd; | ||||
| +	int tmp; | ||||
| +	struct ethtool_cmd ecmd = { ETHTOOL_GSET }; | ||||
| +	struct ethtool_value edata = { ETHTOOL_GLINK }; | ||||
| + | ||||
| +	if (get_user(cmd, (u32 *) useraddr)) | ||||
| +		return -EFAULT; | ||||
| + | ||||
| +	switch (cmd) { | ||||
| +	case ETHTOOL_GSET: | ||||
| +		phy_ethtool_gset(phydev, &ecmd); | ||||
| +		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) | ||||
| +			return -EFAULT; | ||||
| +		return 0; | ||||
| + | ||||
| +	case ETHTOOL_SSET: | ||||
| +		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) | ||||
| +			return -EFAULT; | ||||
| +		return phy_ethtool_sset(phydev, &ecmd); | ||||
| + | ||||
| +	case ETHTOOL_NWAY_RST: | ||||
| +		/* if autoneg is off, it's an error */ | ||||
| +		tmp = phy_read(phydev, MII_BMCR); | ||||
| +		if (tmp & BMCR_ANENABLE) { | ||||
| +			tmp |= (BMCR_ANRESTART); | ||||
| +			phy_write(phydev, MII_BMCR, tmp); | ||||
| +			return 0; | ||||
| +		} | ||||
| +		return -EINVAL; | ||||
| + | ||||
| +	case ETHTOOL_GLINK: | ||||
| +		edata.data = (phy_read(phydev, | ||||
| +				MII_BMSR) & BMSR_LSTATUS) ? 1 : 0; | ||||
| +		if (copy_to_user(useraddr, &edata, sizeof(edata))) | ||||
| +			return -EFAULT; | ||||
| +		return 0; | ||||
| +	} | ||||
| + | ||||
| +	return -EOPNOTSUPP; | ||||
| +} | ||||
| +EXPORT_SYMBOL(phy_ethtool_ioctl); | ||||
| + | ||||
|  /** | ||||
|   * phy_mii_ioctl - generic PHY MII ioctl interface | ||||
|   * @phydev: the phy_device struct | ||||
| @@ -355,8 +399,8 @@ int phy_mii_ioctl(struct phy_device *phy | ||||
|  		} | ||||
|   | ||||
|  		phy_write(phydev, mii_data->reg_num, val); | ||||
| -		 | ||||
| -		if (mii_data->reg_num == MII_BMCR  | ||||
| + | ||||
| +		if (mii_data->reg_num == MII_BMCR | ||||
|  				&& val & BMCR_RESET | ||||
|  				&& phydev->drv->config_init) { | ||||
|  			phy_scan_fixups(phydev); | ||||
| @@ -476,7 +520,7 @@ static void phy_force_reduction(struct p | ||||
|  	int idx; | ||||
|   | ||||
|  	idx = phy_find_setting(phydev->speed, phydev->duplex); | ||||
| -	 | ||||
| + | ||||
|  	idx++; | ||||
|   | ||||
|  	idx = phy_find_valid(idx, phydev->supported); | ||||
| --- a/include/linux/phy.h | ||||
| +++ b/include/linux/phy.h | ||||
| @@ -478,6 +478,7 @@ void phy_start_machine(struct phy_device | ||||
|  void phy_stop_machine(struct phy_device *phydev); | ||||
|  int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd); | ||||
|  int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd); | ||||
| +int phy_ethtool_ioctl(struct phy_device *phydev, void *useraddr); | ||||
|  int phy_mii_ioctl(struct phy_device *phydev, | ||||
|  		struct mii_ioctl_data *mii_data, int cmd); | ||||
|  int phy_start_interrupts(struct phy_device *phydev); | ||||
| @@ -1,24 +0,0 @@ | ||||
| --- a/drivers/net/phy/Kconfig | ||||
| +++ b/drivers/net/phy/Kconfig | ||||
| @@ -82,6 +82,11 @@ config LSI_ET1011C_PHY | ||||
|  	---help--- | ||||
|  	  Supports the LSI ET1011C PHY. | ||||
|   | ||||
| +config ADM6996_PHY | ||||
| +	tristate "Driver for ADM6996 switches" | ||||
| +	---help--- | ||||
| +	  Currently supports the ADM6996F switch | ||||
| + | ||||
|  config FIXED_PHY | ||||
|  	bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs" | ||||
|  	depends on PHYLIB=y | ||||
| --- a/drivers/net/phy/Makefile | ||||
| +++ b/drivers/net/phy/Makefile | ||||
| @@ -12,6 +12,7 @@ obj-$(CONFIG_SMSC_PHY)		+= smsc.o | ||||
|  obj-$(CONFIG_VITESSE_PHY)	+= vitesse.o | ||||
|  obj-$(CONFIG_BROADCOM_PHY)	+= broadcom.o | ||||
|  obj-$(CONFIG_ICPLUS_PHY)	+= icplus.o | ||||
| +obj-$(CONFIG_ADM6996_PHY)	+= adm6996.o | ||||
|  obj-$(CONFIG_REALTEK_PHY)	+= realtek.o | ||||
|  obj-$(CONFIG_LSI_ET1011C_PHY)	+= et1011c.o | ||||
|  obj-$(CONFIG_FIXED_PHY)		+= fixed.o | ||||
| @@ -1,63 +0,0 @@ | ||||
| --- a/drivers/net/phy/phy_device.c | ||||
| +++ b/drivers/net/phy/phy_device.c | ||||
| @@ -143,6 +143,18 @@ int phy_scan_fixups(struct phy_device *p | ||||
|  } | ||||
|  EXPORT_SYMBOL(phy_scan_fixups); | ||||
|   | ||||
| +static int generic_receive_skb(struct sk_buff *skb) | ||||
| +{ | ||||
| +	skb->protocol = eth_type_trans(skb, skb->dev); | ||||
| +	return netif_receive_skb(skb); | ||||
| +} | ||||
| + | ||||
| +static int generic_rx(struct sk_buff *skb) | ||||
| +{ | ||||
| +	skb->protocol = eth_type_trans(skb, skb->dev); | ||||
| +	return netif_rx(skb); | ||||
| +} | ||||
| + | ||||
|  struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id) | ||||
|  { | ||||
|  	struct phy_device *dev; | ||||
| @@ -168,6 +180,8 @@ struct phy_device* phy_device_create(str | ||||
|  	dev->bus = bus; | ||||
|   | ||||
|  	dev->state = PHY_DOWN; | ||||
| +	dev->netif_receive_skb = &generic_receive_skb; | ||||
| +	dev->netif_rx = &generic_rx; | ||||
|   | ||||
|  	mutex_init(&dev->lock); | ||||
|   | ||||
| --- a/include/linux/phy.h | ||||
| +++ b/include/linux/phy.h | ||||
| @@ -326,6 +326,20 @@ struct phy_device { | ||||
|  	void (*adjust_link)(struct net_device *dev); | ||||
|   | ||||
|  	void (*adjust_state)(struct net_device *dev); | ||||
| + | ||||
| +	/* | ||||
| +	 * By default these point to the original functions | ||||
| +	 * with the same name. adding them to the phy_device | ||||
| +	 * allows the phy driver to override them for packet | ||||
| +	 * mangling if the ethernet driver supports it | ||||
| +	 * This is required to support some really horrible | ||||
| +	 * switches such as the Marvell 88E6060 | ||||
| +	 */ | ||||
| +	int (*netif_receive_skb)(struct sk_buff *skb); | ||||
| +	int (*netif_rx)(struct sk_buff *skb); | ||||
| + | ||||
| +	/* alignment offset for packets */ | ||||
| +	int pkt_align; | ||||
|  }; | ||||
|  #define to_phy_device(d) container_of(d, struct phy_device, dev) | ||||
|   | ||||
| --- a/include/linux/netdevice.h | ||||
| +++ b/include/linux/netdevice.h | ||||
| @@ -747,6 +747,7 @@ struct net_device | ||||
|  	void			*ax25_ptr;	/* AX.25 specific data */ | ||||
|  	struct wireless_dev	*ieee80211_ptr;	/* IEEE 802.11 specific data, | ||||
|  						   assign before registering */ | ||||
| +	void			*phy_ptr; /* PHY device specific data */ | ||||
|   | ||||
|  /* | ||||
|   * Cache line mostly used on receive path (including eth_type_trans()) | ||||
| @@ -1,25 +0,0 @@ | ||||
| --- a/drivers/net/phy/Kconfig | ||||
| +++ b/drivers/net/phy/Kconfig | ||||
| @@ -13,6 +13,12 @@ menuconfig PHYLIB | ||||
|   | ||||
|  if PHYLIB | ||||
|   | ||||
| +config SWCONFIG | ||||
| +	tristate "Switch configuration API" | ||||
| +	---help--- | ||||
| +	  Switch configuration API using netlink. This allows | ||||
| +	  you to configure the VLAN features of certain switches. | ||||
| + | ||||
|  comment "MII PHY device drivers" | ||||
|   | ||||
|  config MARVELL_PHY | ||||
| --- a/drivers/net/phy/Makefile | ||||
| +++ b/drivers/net/phy/Makefile | ||||
| @@ -3,6 +3,7 @@ | ||||
|  libphy-objs			:= phy.o phy_device.o mdio_bus.o | ||||
|   | ||||
|  obj-$(CONFIG_PHYLIB)		+= libphy.o | ||||
| +obj-$(CONFIG_SWCONFIG)		+= swconfig.o | ||||
|  obj-$(CONFIG_MARVELL_PHY)	+= marvell.o | ||||
|  obj-$(CONFIG_DAVICOM_PHY)	+= davicom.o | ||||
|  obj-$(CONFIG_CICADA_PHY)	+= cicada.o | ||||
| @@ -1,22 +0,0 @@ | ||||
| --- a/drivers/net/phy/Kconfig | ||||
| +++ b/drivers/net/phy/Kconfig | ||||
| @@ -93,6 +93,9 @@ config ADM6996_PHY | ||||
|  	---help--- | ||||
|  	  Currently supports the ADM6996F switch | ||||
|   | ||||
| +config MVSWITCH_PHY | ||||
| +	tristate "Driver for Marvell 88E6060 switches" | ||||
| + | ||||
|  config FIXED_PHY | ||||
|  	bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs" | ||||
|  	depends on PHYLIB=y | ||||
| --- a/drivers/net/phy/Makefile | ||||
| +++ b/drivers/net/phy/Makefile | ||||
| @@ -14,6 +14,7 @@ obj-$(CONFIG_VITESSE_PHY)	+= vitesse.o | ||||
|  obj-$(CONFIG_BROADCOM_PHY)	+= broadcom.o | ||||
|  obj-$(CONFIG_ICPLUS_PHY)	+= icplus.o | ||||
|  obj-$(CONFIG_ADM6996_PHY)	+= adm6996.o | ||||
| +obj-$(CONFIG_MVSWITCH_PHY)	+= mvswitch.o | ||||
|  obj-$(CONFIG_REALTEK_PHY)	+= realtek.o | ||||
|  obj-$(CONFIG_LSI_ET1011C_PHY)	+= et1011c.o | ||||
|  obj-$(CONFIG_FIXED_PHY)		+= fixed.o | ||||
| @@ -1,23 +0,0 @@ | ||||
| --- a/drivers/net/phy/Kconfig | ||||
| +++ b/drivers/net/phy/Kconfig | ||||
| @@ -96,6 +96,10 @@ config ADM6996_PHY | ||||
|  config MVSWITCH_PHY | ||||
|  	tristate "Driver for Marvell 88E6060 switches" | ||||
|   | ||||
| +config IP175C_PHY | ||||
| +	tristate "Driver for IC+ IP175C/IP178C switches" | ||||
| +	select SWCONFIG | ||||
| + | ||||
|  config FIXED_PHY | ||||
|  	bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs" | ||||
|  	depends on PHYLIB=y | ||||
| --- a/drivers/net/phy/Makefile | ||||
| +++ b/drivers/net/phy/Makefile | ||||
| @@ -15,6 +15,7 @@ obj-$(CONFIG_BROADCOM_PHY)	+= broadcom.o | ||||
|  obj-$(CONFIG_ICPLUS_PHY)	+= icplus.o | ||||
|  obj-$(CONFIG_ADM6996_PHY)	+= adm6996.o | ||||
|  obj-$(CONFIG_MVSWITCH_PHY)	+= mvswitch.o | ||||
| +obj-$(CONFIG_IP175C_PHY)	+= ip175c.o | ||||
|  obj-$(CONFIG_REALTEK_PHY)	+= realtek.o | ||||
|  obj-$(CONFIG_LSI_ET1011C_PHY)	+= et1011c.o | ||||
|  obj-$(CONFIG_FIXED_PHY)		+= fixed.o | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user
	 Felix Fietkau
					Felix Fietkau