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