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 | SQUASHFS_OPTS :=  -be | ||||||
| endif | endif | ||||||
|  |  | ||||||
| ifneq ($(CONFIG_LINUX_2_6_29)$(CONFIG_LINUX_2_6_30),) | ifneq ($(CONFIG_LINUX_2_6_30),) | ||||||
| USE_SQUASHFS4 := y | USE_SQUASHFS4 := y | ||||||
| endif | endif | ||||||
|  |  | ||||||
|   | |||||||
| @@ -25,9 +25,6 @@ endif | |||||||
| ifeq ($(LINUX_VERSION),2.6.28.10) | ifeq ($(LINUX_VERSION),2.6.28.10) | ||||||
|   LINUX_KERNEL_MD5SUM:=c4efb2c494d749cb5de274f8ae41c3fa |   LINUX_KERNEL_MD5SUM:=c4efb2c494d749cb5de274f8ae41c3fa | ||||||
| endif | endif | ||||||
| ifeq ($(LINUX_VERSION),2.6.29.6) |  | ||||||
|   LINUX_KERNEL_MD5SUM:=7cd24826fd3c7b0f83d9f662731a7865 |  | ||||||
| endif |  | ||||||
| ifeq ($(LINUX_VERSION),2.6.30.1) | ifeq ($(LINUX_VERSION),2.6.30.1) | ||||||
|   LINUX_KERNEL_MD5SUM:=7da2e2e31f1c00f2673d2dc50de76b33 |   LINUX_KERNEL_MD5SUM:=7da2e2e31f1c00f2673d2dc50de76b33 | ||||||
| endif | endif | ||||||
|   | |||||||
| @@ -45,7 +45,7 @@ endef | |||||||
| define KernelPackage/hostap | define KernelPackage/hostap | ||||||
| $(call KernelPackage/hostap/Default) | $(call KernelPackage/hostap/Default) | ||||||
|   TITLE:=Host AP support for Prism2/2.5/3 |   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 |   KCONFIG:=CONFIG_HOSTAP CONFIG_HOSTAP_FIRMWARE=y CONFIG_HOSTAP_FIRMWARE_NVRAM=y | ||||||
|   PROVIDES:=kmod-hostap |   PROVIDES:=kmod-hostap | ||||||
| endef | endef | ||||||
|   | |||||||
| @@ -289,7 +289,7 @@ define KernelPackage/tg3 | |||||||
|   TITLE:=Broadcom Tigon3 Gigabit Ethernet |   TITLE:=Broadcom Tigon3 Gigabit Ethernet | ||||||
|   FILES:=$(LINUX_DIR)/drivers/net/tg3.$(LINUX_KMOD_SUFFIX) |   FILES:=$(LINUX_DIR)/drivers/net/tg3.$(LINUX_KMOD_SUFFIX) | ||||||
|   KCONFIG:=CONFIG_TIGON3 |   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) |   SUBMENU:=$(NETWORK_DEVICES_MENU) | ||||||
|   AUTOLOAD:=$(call AutoLoad,50,tg3) |   AUTOLOAD:=$(call AutoLoad,50,tg3) | ||||||
| endef | endef | ||||||
|   | |||||||
| @@ -49,7 +49,7 @@ $(eval $(call KernelPackage,ieee80211)) | |||||||
| define KernelPackage/lib80211 | define KernelPackage/lib80211 | ||||||
|   SUBMENU:=$(WIRELESS_MENU) |   SUBMENU:=$(WIRELESS_MENU) | ||||||
|   TITLE:=802.11 Networking stack |   TITLE:=802.11 Networking stack | ||||||
|   DEPENDS:=@LINUX_2_6_29||LINUX_2_6_30 |   DEPENDS:=@LINUX_2_6_30 | ||||||
|   KCONFIG:= \ |   KCONFIG:= \ | ||||||
| 	CONFIG_LIB80211 \ | 	CONFIG_LIB80211 \ | ||||||
| 	CONFIG_LIB80211_CRYPT_WEP \ | 	CONFIG_LIB80211_CRYPT_WEP \ | ||||||
| @@ -87,7 +87,7 @@ endif | |||||||
| define KernelPackage/net-libipw | define KernelPackage/net-libipw | ||||||
|   SUBMENU:=$(WIRELESS_MENU) |   SUBMENU:=$(WIRELESS_MENU) | ||||||
|   TITLE:=libipw for ipw2100 and ipw2200 |   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 |   KCONFIG:=CONFIG_LIBIPW | ||||||
|   FILES:=$(LINUX_DIR)/drivers/net/wireless/$(IPW_DIR)libipw.$(LINUX_KMOD_SUFFIX) |   FILES:=$(LINUX_DIR)/drivers/net/wireless/$(IPW_DIR)libipw.$(LINUX_KMOD_SUFFIX) | ||||||
|   AUTOLOAD:=$(call AutoLoad,49,libipw) |   AUTOLOAD:=$(call AutoLoad,49,libipw) | ||||||
| @@ -103,7 +103,7 @@ $(eval $(call KernelPackage,net-libipw)) | |||||||
| define KernelPackage/net-ipw2100 | define KernelPackage/net-ipw2100 | ||||||
|   SUBMENU:=$(WIRELESS_MENU) |   SUBMENU:=$(WIRELESS_MENU) | ||||||
|   TITLE:=Intel IPW2100 driver |   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 |   KCONFIG:=CONFIG_IPW2100 | ||||||
|   FILES:=$(LINUX_DIR)/drivers/net/wireless/$(IPW_DIR)ipw2100.$(LINUX_KMOD_SUFFIX) |   FILES:=$(LINUX_DIR)/drivers/net/wireless/$(IPW_DIR)ipw2100.$(LINUX_KMOD_SUFFIX) | ||||||
|   AUTOLOAD:=$(call AutoLoad,50,ipw2100) |   AUTOLOAD:=$(call AutoLoad,50,ipw2100) | ||||||
| @@ -121,7 +121,7 @@ $(eval $(call KernelPackage,net-ipw2100)) | |||||||
| define KernelPackage/net-ipw2200 | define KernelPackage/net-ipw2200 | ||||||
|   SUBMENU:=$(WIRELESS_MENU) |   SUBMENU:=$(WIRELESS_MENU) | ||||||
|   TITLE:=Intel IPW2200 driver |   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 |   KCONFIG:=CONFIG_IPW2200 | ||||||
|   FILES:=$(LINUX_DIR)/drivers/net/wireless/$(IPW_DIR)ipw2200.$(LINUX_KMOD_SUFFIX) |   FILES:=$(LINUX_DIR)/drivers/net/wireless/$(IPW_DIR)ipw2200.$(LINUX_KMOD_SUFFIX) | ||||||
|   AUTOLOAD:=$(call AutoLoad,50,ipw2200) |   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